atc*_*way 143 c# httprequest asp.net-web-api
我目前在我的Web API服务中有一个消息处理程序,它覆盖"SendAsync",如下所示:
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
//implementation
}
Run Code Online (Sandbox Code Playgroud)
在此代码中,我需要检查名为的自定义添加的请求标头值MyCustomID
.问题是当我执行以下操作时:
if (request.Headers.Contains("MyCustomID")) //OK
var id = request.Headers["MyCustomID"]; //build error - not OK
Run Code Online (Sandbox Code Playgroud)
...我收到以下错误消息:
无法将带有[]的索引应用于"System.Net.Http.Headers.HttpRequestHeaders"类型的表达式
如何通过传递给此重写方法的(MSDN文档)实例访问单个自定义请求标头?HttpRequestMessage
You*_*oui 240
尝试这样的事情:
IEnumerable<string> headerValues = request.Headers.GetValues("MyCustomID");
var id = headerValues.FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)
如果您并不总是保证能够访问标题,那么您可以使用Header上的TryGetValues方法.
Sha*_*der 37
throws exception
如果密钥不存在,则在下面一行.
IEnumerable<string> headerValues = request.Headers.GetValues("MyCustomID");
Run Code Online (Sandbox Code Playgroud)
解决方法:
包括System.Linq;
IEnumerable<string> headerValues;
var userId = string.Empty;
if (request.Headers.TryGetValues("MyCustomID", out headerValues))
{
userId = headerValues.FirstOrDefault();
}
Run Code Online (Sandbox Code Playgroud)
neo*_*pir 16
为了扩展Youssef的答案,我根据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);
}
Run Code Online (Sandbox Code Playgroud)
这是一个示例用法:
GetFirstHeaderValueOrDefault("X-MyGuid", h => Guid.NewGuid().ToString(), Guid.Parse);
Run Code Online (Sandbox Code Playgroud)
另请参阅@ doguhan-uluca的答案以获得更通用的解决方案.
小智 12
创建一个新方法 - " 返回单个HTTP标头值 ",并在每次需要从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();
}
Run Code Online (Sandbox Code Playgroud)
Rom*_*syk 10
一行解决方案(假设标头存在)
var id = request.Headers.GetValues("MyCustomID").FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)
为了进一步扩展@ 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;
}
}
Run Code Online (Sandbox Code Playgroud)
样品用法:
var myValue = response.GetFirstHeaderValueOrDefault<int>("MyValue");
Run Code Online (Sandbox Code Playgroud)
对于 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}");
...
}
}
Run Code Online (Sandbox Code Playgroud)