如何在Web API消息处理程序中提取自定义标题值?

我目前有一个消息处理程序在我的Web API服务,覆盖“SendAsync”,如下所示:

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { //implementation } 

在这个代码中,我需要检查一个名为MyCustomID的自定义添加请求标头值。 问题是,当我做到以下几点:

 if (request.Headers.Contains("MyCustomID")) //OK var id = request.Headers["MyCustomID"]; //build error - not OK 

…我收到以下错误信息:

无法将[]的索引应用于types为“System.Net.Http.Headers.HttpRequestHeaders”的expression式

如何通过传入此重写方法的HttpRequestMessage ( MSDN文档 )实例访问单个自定义请求标头?

尝试这样的事情:

 IEnumerable<string> headerValues = request.Headers.GetValues("MyCustomID"); var id = headerValues.FirstOrDefault(); 

如果您不总是保证有权访问标题,则可以使用Headers上的TryGetValues方法。

如果该键不存在,则下面的行将throws exception

 IEnumerable<string> headerValues = request.Headers.GetValues("MyCustomID"); 

解决方法:

包含System.Linq;

 IEnumerable<string> headerValues; var userId = string.Empty; if (request.Headers.TryGetValues("MyCustomID", out headerValues)) { userId = headerValues.FirstOrDefault(); } 

为了扩大Youssef的回答,我写了这个方法,这个方法是根据Drew关于头部不存在的问题,因为我在unit testing中遇到了这种情况。

 private T GetFirstHeaderValueOrDefault<T>(string headerKey, Func<HttpRequestMessage, string> defaultValue, Func<string,T> valueTransform) { IEnumerable<string> headerValues; HttpRequestMessage message = Request ?? new HttpRequestMessage(); if (!message.Headers.TryGetValues(headerKey, out headerValues)) return valueTransform(defaultValue(message)); string firstHeaderValue = headerValues.FirstOrDefault() ?? defaultValue(message); return valueTransform(firstHeaderValue); } 

这是一个示例用法:

 GetFirstHeaderValueOrDefault("X-MyGuid", h => Guid.NewGuid().ToString(), Guid.Parse); 

也可以看看@ doguhan-uluca为更一般的解决scheme的答案。

创build一个新的方法 – 当你需要访问HttpRequestMessage中的多个键值时,每次都返回一个单独的HTTP Header值 ,并用键值调用这个方法。

 public static string GetHeader(this HttpRequestMessage request, string key) { IEnumerable<string> keys = null; if (!request.Headers.TryGetValues(key, out keys)) return null; return keys.First(); } 

要进一步扩展@ neontapir的解决scheme,下面是一个更通用的解决scheme,可以同时应用于HttpRequestMessage或HttpResponseMessage,不需要手动编码的expression式或函数。

 using System.Net.Http; using System.Collections.Generic; using System.Linq; public static class HttpResponseMessageExtensions { public static T GetFirstHeaderValueOrDefault<T>( this HttpResponseMessage response, string headerKey) { var toReturn = default(T); IEnumerable<string> headerValues; if (response.Content.Headers.TryGetValues(headerKey, out headerValues)) { var valueString = headerValues.FirstOrDefault(); if (valueString != null) { return (T)Convert.ChangeType(valueString, typeof(T)); } } return toReturn; } } 

示例用法:

 var myValue = response.GetFirstHeaderValueOrDefault<int>("MyValue"); 

对于ASP.Net Core,如果想直接在控制器方法中使用param,有一个简单的解决scheme:使用[FromHeader]注释。

  public JsonResult SendAsync([FromHeader] string myParam) { if(myParam == null) //Param not set in request header { return null; } return doSomething(); } 

附加信息:在我的情况下,“myParam”必须是一个string,int始终是0。

 request.Headers.FirstOrDefault( x => x.Key == "MyCustomID" ).Value?.FirstOrDefault() 

现代变种:)

对于ASP.NET,您可以使用这个简单的库/包直接从控制器方法中的参数获取头文件。 它提供了一个[FromHeader]属性,就像你在ASP.NET Core中的:)。 例如:

  ... using RazHeaderAttribute.Attributes; [Route("api/{controller}")] public class RandomController : ApiController { ... // GET api/random [HttpGet] public IEnumerable<string> Get([FromHeader("pages")] int page, [FromHeader] string rows) { // Print in the debug window to be sure our bound stuff are passed :) Debug.WriteLine($"Rows {rows}, Page {page}"); ... } }