绑定以在ASP.NET MVC / Web API中形成编码的JSON

时间:2013-06-28 18:20:39

标签: asp.net-mvc json github asp.net-web-api

当提交被推送到存储库(Post-Receive Hooks)时,github会提醒您并调用您的Web服务。 github将提交信息作为JSON发送,但在表单编码参数内。也就是说,内容类型为 application / x-www-form-urlencoded ,http请求为

POST /my_uri HTTP/1.1
Content-Type: application/x-www-form-urlencoded

payload=%7B%22ref%22%3A%22refs%2Fheads...

我想编写处理ASP.NET MVC或WebAPI中新提交的web服务。我已经定义了一些类来反序列化json,但是我无法让框架直接初始化我的对象。我现在拥有的是

public string my_uri(string payload)
{
    var s = new JavaScriptSerializer();
    var p = s.Deserialize(payload, typeof(Payload)) as Payload;
    ...
}

但我想要

public string my_uri(Payload payload)
{
    ...
}

我读过有关ValueProviders但我找不到链接它们的方法。我需要编写FormValueProviderFactory和JsonValueProviderFactory。如何让ASP进行绑定?

1 个答案:

答案 0 :(得分:1)

首先,我有点困惑为什么他们会在表格编码的正文数据中填充Json数据。如果一个服务最终可以理解Json(因为它必须反序列化它),为什么不发布为“application / json”本身呢?是因为CORS他们这样做了吗?

除此之外,您可以创建一个自定义参数绑定,如下所示,看看它是否符合您的需求:

<强>动作

public Payload Post([PayloadParamBinding]Payload payload)

自定义参数绑定

public class PayloadParamBindingAttribute : ParameterBindingAttribute
{
    public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter)
    {
        return new PayloadParamBinding(parameter);
    }
}

public class PayloadParamBinding : HttpParameterBinding
{
    HttpParameterBinding _defaultFormatterBinding;

    public PayloadParamBinding(HttpParameterDescriptor desc)
        :base(desc)
    {
        _defaultFormatterBinding = new FromBodyAttribute().GetBinding(desc);
    }

    public override async Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken)
    {
        if (actionContext.Request.Content != null)
        {
            NameValueCollection nvc = await actionContext.Request.Content.ReadAsFormDataAsync();

            StringContent sc = new StringContent(nvc["payload"]);
            //set the header so that Json formatter comes into picture
            sc.Headers.ContentType = new MediaTypeHeaderValue("application/json");

            actionContext.Request.Content = sc;

            //Doing like this here because we want to simulate the default behavior of when a request
            //is posted as Json and the Json formatter would have been picked up and also the model validation is done.
            //This way you are simulating the experience as of a normal "application/json" post request.
            await _defaultFormatterBinding.ExecuteBindingAsync(metadataProvider, actionContext, cancellationToken);
        }
    }

    public override bool WillReadBody
    {
        get
        {
            return true;
        }
    }
}