【问题标题】:Override content headers for MVC POST request覆盖 MVC POST 请求的内容标头
【发布时间】:2017-04-27 02:47:50
【问题描述】:

我对 MVC 相当陌生,所以我希望有一个解决我的问题的方法。我正在使用第三方硬件与我的 MVC Web API 进行通信。硬件以 JSON 格式发送请求,我可以很好地提取这些请求。但是,由于冲突,我正在将这些请求的参数更改为绑定模型对象。

例如

        Public Function POSTRequest(Action As String, Stamp As String) As HttpResponseMessage
           ...
        End Function

        Public Function POSTRequest(Action As String, OpStamp As String) As HttpResponseMessage
           ...
        End Function

所以这两个方法共享同一张电话卡,所以它们不能同时存在于同一个控制器中。

因此,我创建了模型绑定对象来容纳这些参数。问题是,一旦我这样做,Web API 就会抱怨请求说“Content-Type”没有定义。看着它,第三方硬件不会随请求发送内容类型。在网上查看,我发现这导致浏览器将其视为内容类型“application/octet-stream”。这不能然后将其转换为定义为参数的绑定对象。

我们无法控制第三方硬件,因此我们无法为这些请求定义内容类型。所以,我的问题是,有没有办法拦截这些请求并向它们添加内容类型?或者甚至是另一种解决方法?

【问题讨论】:

    标签: .net http model-view-controller asp.net-web-api content-type


    【解决方案1】:

    我认为您可以使用ActionFilterAttribute。请参阅文档:Creating Custom Action Filters

    在您的情况下,您可以使用以下示例(在 C# 中,因为我的 VB 技能已经过时了)。它使用 application/json 值覆盖任何请求 Content-Type 标头。请注意,您可能需要对其进行增强以支持各种 HttpContent(例如,我认为这不应该用于 MultiPart 请求)。

    public class UpdateRequestAttribute: ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            actionContext.Request.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
            base.OnActionExecuting(actionContext);
        }
    }
    

    然后你将这个属性添加到你的控制器类中,例如:

    [UpdateRequest]
    public class HomeController : ApiController
    {
        //[...]
    }
    

    在这种情况下,所有对 Home 控制器的请求都将覆盖其 Content-Type


    或者,您也可以编写一个自定义的HTTP Message Handlers,它在管道的早期被调用,并且不限于特定的控制器。查看下图,了解服务器如何处理请求。

    例如,此消息处理程序会将请求Content-Type 设置为application/json,如果它当前为空。

    public class CustomMessageHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (request.Content.Headers.ContentType == null)
            {
                request.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
            }
            return base.SendAsync(request, cancellationToken);
        }
    }
    

    最后,这里是如何更新 WebApiConfig 以便将您的消息处理程序添加到管道:

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.MessageHandlers.Add(new CustomMessageHandler());
    
            // Other configuration not shown... 
    
        }
    }
    

    【讨论】:

      【解决方案2】:

      您可以通过定义 Route 属性在同一个控制器中同时拥有这两种方法。这样可以避免 Model Binding 属性。

      [Route("Request1")]
      Public Function POSTRequest(Action As String, Stamp As String) As HttpResponseMessage
                 ...
              End Function
              [Route("Request2")]
              Public Function POSTRequest(Action As String, OpStamp As String) As HttpResponseMessage
                 ...
              End Function
      

      不要忘记通过在 webapiconfig.vb 文件中添加 MapHttpAttributeRoutes 来启用属性路由

      Public Module WebApiConfig
          Public Sub Register(ByVal config As HttpConfiguration)
              ' Web API configuration and services
      
              ' Web API routes
              config.MapHttpAttributeRoutes()
      
              config.Routes.MapHttpRoute(
                  name:="DefaultApi",
                  routeTemplate:="api/{controller}/{id}",
                  defaults:=New With {.id = RouteParameter.Optional}
              )
          End Sub
      End Module
      

      【讨论】:

        猜你喜欢
        • 2021-09-19
        • 2013-09-09
        • 1970-01-01
        • 2021-07-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-28
        • 2021-12-03
        相关资源
        最近更新 更多