在.NetCore中禁用ModelBinder

时间:2017-07-12 14:00:38

标签: c# asp.net-core model-binding asp.net-core-webapi

HeyGuys

我正在开发一个WebApi项目,该项目接收来自客户端的请求,并将这些请求重定向到其他未开放供直接访问的服务。

默认情况下,.Net自动序列化和反序列化Json请求参数,因此我需要在调用适当的服务之前重新序列化它们。收到服务响应时会出现同样的问题。我需要在将响应发送给用户之前对其进行反序列化;否则.Net框架会再次序列化它,导致Json" Json of Json"响应。

我找到this answer但它似乎与.NetCore无关;所以我试着创建自己的ModelBinder,只读取Json对象并返回它。

class JsonUnformatterBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider
  {
    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {      
      return new JsonUnformatterBinder(new SimpleTypeModelBinder(context.Metadata.ModelType));      
    }
  }

class JsonUnformatterBinder : IModelBinder
{
    private readonly IModelBinder _fallbackBinder;

    public JsonUnformatterBinder(IModelBinder fallbackBinder)
    {
      _fallbackBinder = fallbackBinder;
    }

    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
      string currMethod = bindingContext.ActionContext.HttpContext.Request.Method;

      if ("POST".Equals(currMethod) || "PUT".Equals(currMethod))
      {
        string strData = new StreamReader(bindingContext.ActionContext.HttpContext.Request.Body).ReadToEnd();
        bindingContext.Result = ModelBindingResult.Success(strData);
        return Task.CompletedTask;
      }

      return _fallbackBinder.BindModelAsync(bindingContext);
    }
}

这段代码非常简单,这是我的第一次尝试,它适用于我的目的。但是,我仍然得到了Json" Json of Json"当我接受第二个服务答案并返回给用户时出现问题。

我基本上不知道我能做些什么来克服这个问题,所以欢迎任何解决方法。

1 个答案:

答案 0 :(得分:0)

如果您只是需要重定向请求而不进行修改,您可以直接从输入流中读取它并将其发送到内部服务。您也可以使用这种方法从内部服务中读取响应。

//1. Set empty parameter list in action then neither serializator nor model binder are not invoked.
public async Task<ContentResult> ProxyAction(/*empty parameter list*/)
{
    var newUrl = @"https://stackoverflow.com";
    var data = this.Request.Body;

    using (var client = new HttpClient())
    {
        //2. Read request body from input stream.
        var reader = new StreamReader(data);
        var json = reader.ReadToEnd();

        using (var content = new StringContent(json))
        {
            //3. Set correct content type
            content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(this.Request.ContentType);

            //4. Post request to inner service
            var response = await client.PostAsync(newUrl, content);

            //5. Read response without deserialization
            var innerResponse = await response.Content.ReadAsStringAsync();
            var contentType = response.Content.Headers.ContentType.ToString();
            var statusCode = response.StatusCode;

            //6. Return inner response without serialization
            var outerResponse = this.Content(innerResponse, contentType);
            outerResponse.StatusCode = (int)statusCode;
            return outerResponse;
        }
    }
}