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

时间:2015-02-19 11:09:52

标签: asp.net-mvc model-view-controller asp.net-web-api asp.net-mvc-5 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编码的字符串。

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

当然我可以修改代码以接受一个字符串,然后将其转换为字节数组,但如果可能的话,我的首选是透明地执行此操作。

1 个答案:

答案 0 :(得分:7)

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

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

对于我的解决方案,我为'基本64字节数组'创建了一个模型绑定器:

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);

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

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

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

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

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