私は現在、私の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'型の式に適用することはできません
このオーバーライドされたメソッドに渡されたHttpRequestMessage
( MSDN Documentation )インスタンスを介して単一のカスタム要求ヘッダーにアクセスする方法を教えてください。
このようなことを試してください:
IEnumerable<string> headerValues = request.Headers.GetValues("MyCustomID");
var id = headerValues.FirstOrDefault();
ヘッダへのアクセス権が常に保証されているわけではない場合に使用できるヘッダの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の懸念に基づいてこの方法を書きました。
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の答えも見てください。
HttpRequestMessageから複数のキー値にアクセスする必要があるときは、新しいメソッド - '個々のHTTPヘッダー値を返す'を作成し、このメソッドをキー値で呼び出します。
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のソリューションをさらに拡張するために、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");
ASP.Net Coreの場合、コントローラーメソッドで直接paramを使用したい場合は簡単な解決策があります。[FromHeader]アノテーションを使用します。
public JsonResult SendAsync([FromHeader] string myParam)
{
if(myParam == null) //Param not set in request header
{
return null;
}
return doSomething();
}
追加情報:私の場合、 "myParam"は文字列でなければならず、intは常に0でした。
ASP.NETでは、 この単純なライブラリ/パッケージ を使用して、コントローラメソッドのパラメータから直接ヘッダを取得できます。 ASP.NET Core :)と同じように[FromHeader]
属性を提供します。例えば:
...
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}");
...
}
}
request.Headers.FirstOrDefault( x => x.Key == "MyCustomID" ).Value?.FirstOrDefault()
現代の変種:)
ワンラインソリューション
var id = request.Headers.GetValues("MyCustomID").FirstOrDefault();