覆盖 MVC POST 请求的内容 headers
Override content headers for MVC POST request
我对 MVC 还很陌生,所以我希望有解决我的问题的方法。我正在使用第三方硬件与我的 MVC 网络进行通信 API。硬件以 JSON 格式发送请求,我可以很好地提取这种格式。但是,由于冲突,我正在将这些请求的参数更改为绑定模型 objects。
例如
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
所以这两个方法共享同一个调用卡,所以它们不能存在于同一个控制器中。
因此,我创建了模型绑定 objects 来容纳这些参数。问题是,一旦我这样做,网络 API 就会抱怨请求说 "Content-Type" 未定义。看看它,third-party 硬件不会随请求发送 content-type。在网上看,我发现这导致浏览器将其视为内容类型 "application/octet-stream"。这无法将其转换为定义为参数的绑定 object。
我们无法控制第三方硬件,因此我们无法为这些请求定义内容类型。所以,我的问题是,有没有办法拦截这些请求并向它们添加内容类型?还是另一种解决方法?
我想你可以使用 ActionFilterAttribute
。请参阅文档:Creating Custom Action Filters.
对于您的情况,您可以使用以下示例(在 C# 中,因为我的 VB 技能已经过时)。它用 application/json 值覆盖任何请求 Content-Type
header。请注意,您可能需要增强它以支持各种 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);
}
}
然后你将这个属性添加到你的控制器class,例如:
[UpdateRequest]
public class HomeController : ApiController
{
//[...]
}
在这种情况下,所有对家庭控制器的请求都将被覆盖 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...
}
}
您可以通过定义 Route attribute.This 避免模型绑定属性的方式在同一个控制器中使用这两种方法。
[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
我对 MVC 还很陌生,所以我希望有解决我的问题的方法。我正在使用第三方硬件与我的 MVC 网络进行通信 API。硬件以 JSON 格式发送请求,我可以很好地提取这种格式。但是,由于冲突,我正在将这些请求的参数更改为绑定模型 objects。
例如
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
所以这两个方法共享同一个调用卡,所以它们不能存在于同一个控制器中。
因此,我创建了模型绑定 objects 来容纳这些参数。问题是,一旦我这样做,网络 API 就会抱怨请求说 "Content-Type" 未定义。看看它,third-party 硬件不会随请求发送 content-type。在网上看,我发现这导致浏览器将其视为内容类型 "application/octet-stream"。这无法将其转换为定义为参数的绑定 object。
我们无法控制第三方硬件,因此我们无法为这些请求定义内容类型。所以,我的问题是,有没有办法拦截这些请求并向它们添加内容类型?还是另一种解决方法?
我想你可以使用 ActionFilterAttribute
。请参阅文档:Creating Custom Action Filters.
对于您的情况,您可以使用以下示例(在 C# 中,因为我的 VB 技能已经过时)。它用 application/json 值覆盖任何请求 Content-Type
header。请注意,您可能需要增强它以支持各种 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);
}
}
然后你将这个属性添加到你的控制器class,例如:
[UpdateRequest]
public class HomeController : ApiController
{
//[...]
}
在这种情况下,所有对家庭控制器的请求都将被覆盖 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...
}
}
您可以通过定义 Route attribute.This 避免模型绑定属性的方式在同一个控制器中使用这两种方法。
[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