将自定义标题添加到Web API中的所有响应

简单的问题,我相信它有一个简单的答案,但我找不到它。

我正在使用WebAPI,并且想要将自定义标题发送回所有响应(由开发人员为同步目的而请求的服务器date/时间)。

我目前正在努力寻找一个清晰的例子,在一个地方(通过global.asax或另一个中心位置),我可以得到一个自定义标题出现所有的响应。


接受的答案,这里是我的filter(几乎相同)和我添加到WebApiconfiguration的注册function的行。

注意:DateTime的东西是NodaTime,没有真正的理由只是有兴趣的看着它。

public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { actionExecutedContext.Response.Content.Headers.Add("ServerTime", Instant.FromDateTimeUtc(DateTime.Now.ToUniversalTime()).ToString()); } 

configuration线:

 config.Filters.Add(new ServerTimeHeaderFilter()); 

为此,您可以使用自定义的ActionFilter( System.Web.Http.Filters

 public class AddCustomHeaderFilter : ActionFilterAttribute { public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { actionExecutedContext.Response.Headers.Add("customHeader", "custom value date time"); } } 

然后,您可以通过在Global.asax中的configuration中添加此filter来将filter应用于所有控制器的操作,例如:

 GlobalConfiguration.Configuration.Filters.Add(new AddCustomHeaderFilter()); 

您也可以将filter属性应用于所需的操作,而不使用全局configuration行。

此问题的以前的答案不解决如果您的控制器操作引发exception如何处理。 有两个基本的方法来实现它的工作:

添加一个例外filter

 using System.Net; using System.Net.Http; using System.Web.Http.Filters; public class HeaderAdderExceptionFilter : ExceptionFilterAttribute { public override void OnException(HttpActionExecutedContext context) { if (context.Response == null) context.Response = context.Request.CreateErrorResponse( HttpStatusCode.InternalServerError, context.Exception); context.Response.Content.Headers.Add("header", "value"); } } 

并在您的WebApi设置:

 configuration.Filters.Add(new HeaderAdderExceptionFilter()); 

这种方法是有效的,因为WebApi的默认exception处理程序将发送在filter中创build的HttpResponseMessage,而不是构build它自己的。

replace默认的exception处理程序:

 using System.Net; using System.Net.Http; using System.Web.Http.ExceptionHandling; using System.Web.Http.Results; public class HeaderAdderExceptionHandler : ExceptionHandler { public override void Handle(ExceptionHandlerContext context) { HttpResponseMessage response = context.Request.CreateErrorResponse( HttpStatusCode.InternalServerError, context.Exception); response.Headers.Add("header", "value"); context.Result = new ResponseMessageResult(response); } } 

并在您的WebApi设置:

 configuration.Services.Replace(typeof(IExceptionHandler), new HeaderAdderExceptionHandler()); 

你不能同时使用这两个。 好的,你可以,但是处理程序永远不会做任何事情,因为filter已经将exception转换为响应。

需要注意的是, 按照书面forms,此代码将向客户端发送所有exception详细信息 。 您可能不想在生产环境中执行此操作,因此请检查CreateErrorResponse()上的所有可用重载,然后select适合您的需求的重载。

Julian的回答让我不得不创buildfilter,但只使用System.Web(v4)和System.Web.Http(v5)命名空间(MVC包不是这个特定项目的一部分)。

 using System.Web; using System.Web.Http.Filters; ... public class AddCustomHeaderActionFilterAttribute : ActionFilterAttribute { public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { base.OnActionExecuted(actionExecutedContext); actionExecutedContext.ActionContext.Response.Headers.Add("name", "value"); } } 

并将其添加到global.asax以使其用于每个控制器/操作

  GlobalConfiguration.Configuration.Filters.Add(new AddCustomHeaderActionFilterAttribute()); 

上述两种解决scheme都不适合我。 他们甚至不会编译。 这是我做的。 添加:

 filters.Add(new AddCustomHeaderFilter()); 

到FiltersConfig.cs中的RegisterGlobalFilters(GlobalFilterCollection filters)方法,然后添加

 public class AddCustomHeaderFilter : ActionFilterAttribute { public override void OnActionExecuted(ActionExecutedContext actionExecutedContext) { actionExecutedContext.HttpContext.Response.Headers.Add("ServerTime", DateTime.Now.ToString()); } } 

我在一个类中组合了常规和exceptionpath:

 public class CustomHeaderAttribute : FilterAttribute, IActionFilter, IExceptionFilter { private static string HEADER_KEY { get { return "X-CustomHeader"; } } private static string HEADER_VALUE { get { return "Custom header value"; } } public Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation) { return (new CustomHeaderAction() as IActionFilter).ExecuteActionFilterAsync(actionContext, cancellationToken, continuation); } public Task ExecuteExceptionFilterAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken) { return (new CustomHeaderException() as IExceptionFilter).ExecuteExceptionFilterAsync(actionExecutedContext, cancellationToken); } private class CustomHeaderAction: ActionFilterAttribute { public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { if (actionExecutedContext.Response != null) { actionExecutedContext.Response.Content.Headers.Add(HEADER_KEY, HEADER_VALUE); } } } private class CustomHeaderException : ExceptionFilterAttribute { public override void OnException(HttpActionExecutedContext context) { if (context.Response == null) { context.Response = context.Request.CreateErrorResponse(HttpStatusCode.InternalServerError, context.Exception); } context.Response.Content.Headers.Add(HEADER_KEY, HEADER_VALUE); } } } 

没有什么奇特的,但至less它给了我一个地方来控制我的额外的标题。 现在,它只是静态的内容,但你总是可以挂钩到某种字典发生器/工厂。