172

我目前在我的 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

...我收到以下错误消息:

无法使用 [] 将索引应用于“System.Net.Http.Headers.HttpRequestHeaders”类型的表达式

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

4

12 回答 12

283

尝试这样的事情:

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

如果您不能始终保证可以访问标头,则可以使用标头上的TryGetValues方法。

于 2013-02-19T21:14:06.347 回答
44

throws exception如果密钥不存在,则在下面的行。

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

使用 TryGetValues 的安全解决方案:

包括 System.Linq;

IEnumerable<string> headerValues;
var userId = string.Empty;

     if (request.Headers.TryGetValues("MyCustomID", out headerValues))
     {
         userId = headerValues.FirstOrDefault();
     }           
于 2014-09-03T09:01:05.067 回答
17

为了扩展优素福的回答,我基于 Drew 对不存在标头的担忧编写了此方法,因为我在单元测试期间遇到了这种情况。

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 的答案以获得更通用的解决方案。

于 2013-07-24T22:25:30.203 回答
13

创建一个新方法 - '返回一个单独的 HTTP Header 值',并在每次需要从 HttpRequestMessage 访问多个键值时使用键值调用此方法。

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();
        }
于 2016-04-05T17:39:31.897 回答
10

为了进一步扩展@neontapir 的解决方案,这里有一个更通用的解决方案,可以同样适用于 HttpRequestMessage 或 HttpResponseMessage 并且不需要手动编码的表达式或函数。

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");
于 2016-02-17T15:50:08.220 回答
6

对于 ASP.NET,您可以使用这个简单的 library/package直接从控制器方法中的参数获取标头。它提供了一个[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}");
            ...
        }
    }
于 2017-11-05T09:17:31.377 回答
6

一行解决方案(假设表头存在)

var id = request.Headers.GetValues("MyCustomID").FirstOrDefault();
于 2018-06-22T23:10:11.003 回答
4

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

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

附加信息:在我的情况下,“myParam”必须是一个字符串,int 总是 0。

于 2017-05-24T08:46:44.477 回答
3
request.Headers.FirstOrDefault( x => x.Key == "MyCustomID" ).Value.FirstOrDefault()

现代变体:)

于 2017-06-02T06:42:11.137 回答
0

这听起来很明显,但请确保您正在读取标头的控制器是请求通过的第一个控制器。

我有两个相互通信的 WebAPI 项目。第一个是代理,第二个包含逻辑。愚蠢的我,我尝试阅读第二个控制器中的自定义标题,而不是第一个。

于 2020-09-16T13:04:56.110 回答
0
var token = string.Empty;
if (Request.Headers.TryGetValue("MyKey",  out headerValues))
{
    token = headerValues.FirstOrDefault();
}
于 2020-12-03T06:36:34.720 回答
0

另一种方法

 string customHeader = string.Empty;
        if (Request.Headers.TryGetValue("x-date", out var xdateValue))
        {
            customHeader = xdateValue;
        };
于 2021-10-15T18:55:39.837 回答