在 MVC API 中接受字节数组参数作为 Base64

Accepting a byte array parameter in MVC API as Base64

我目前正在构建一个 ASP.NET MVC WebAPI 服务,我希望在查询字符串中发送一小段二进制数据。此应用程序中的方法是通过 POST 调用的,主体包含实际数据。查询字符串用于描述正文中数据的某些属性(例如,它是如何编码的)。

我想知道是否可以接受字节数组参数作为查询字符串中的 base64 编码字符串。

例如我有这个代码:

using System.Text;
using System.Web.Http;

namespace WebApplication2.Controllers
{
    public class ByteArrayController : ApiController
    {
        public string Get([FromUri] byte[] myarray)
        {
            var strbResult = new StringBuilder();
            foreach (byte byteValue in myarray)
            {
                strbResult.AppendLine(byteValue.ToString() + " ");
            }
            return strbResult.ToString();
        }
    }
}

然后我希望能够通过以下方式发送参数 myarray:

http://.../api/ByteArray/Get?myarray=MTIzNA%3D%3D

请不要介意命名,这只是一个简单的例子。

现在我知道可以通过在查询字符串中多次使用相同的参数来发送数组(例如 myarray=1&myarray=2&myarray=3),但我想接受它作为 base64 编码的字符串。

我一直在寻找一个属性来指定如何解码数组,但找不到这样的属性。

当然,我可以修改代码以接受字符串,然后将其转换为字节数组,但我更喜欢透明地执行此操作(如果可能)。

最终我发现了一篇关于模型绑定器的有趣文章,使我能够实现上述内容:

http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

对于我的解决方案,我为 'base 64 byte arrays':

创建了一个模型活页夹
using System;
using System.Web.Http.ModelBinding;
using System.Web.Http.ValueProviders;

namespace WebApplication2.Models
{
    /// <summary>
    /// Model binder for byte-arrays that are sent as base 64 strings. 
    /// </summary>
    public class ModelBinderWithBase64Arrays : IModelBinder
    {
        public bool BindModel(System.Web.Http.Controllers.HttpActionContext actionContext, ModelBindingContext bindingContext)
        {
            if (bindingContext.ModelType == typeof(byte[]))
            {
                ValueProviderResult val = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
                string valueAsString = val.RawValue as string;
                try
                {
                    bindingContext.Model = Convert.FromBase64String(valueAsString);
                    return true;
                }
                catch
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }
    }
}

然后我将其注册为 WebApiConfig 中的默认模型绑定器,这样我就不必在控制器中的参数上明确声明其类型。我在WebApiConfig中Register方法的开头添加了如下几行代码:

// Register model binder for base 64 encoded byte arrays
var provider = new SimpleModelBinderProvider(typeof(byte[]), new ModelBinderWithBase64Arrays());
config.Services.Insert(typeof(ModelBinderProvider), 0, provider);

最后,我修改了 action 方法,通过添加 [ModelBinder] 属性(您还可以使用该属性设置特定的模型绑定器),使其为 byte[] 参数使用此默认模型绑定器:

public string Get([ModelBinder] byte[] myarray)

现在我可以只使用 Base64 编码值,它作为字节数组接收。

尽管此解决方案确实需要添加 [ModelBinder] 属性,但它允许自由选择模型绑定器的使用位置,并且仍然提供尽可能多的透明度。

当然,同样的解决方案也可用于其他数据,例如自定义日期值等。