如何在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}"); ... } }