web-dev-qa-db-ja.com

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

...次のようなエラーメッセージが表示されます。

[]付きのインデックス付けを 'System.Net.Http.Headers.HttpRequestHeaders'型の式に適用することはできません

このオーバーライドされたメソッドに渡されたHttpRequestMessageMSDN Documentation )インスタンスを介して単一のカスタム要求ヘッダーにアクセスする方法を教えてください。

138
atconway

このようなことを試してください:

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

ヘッダへのアクセス権が常に保証されているわけではない場合に使用できるヘッダのTryGetValuesメソッドもあります。

232

キーが存在しない場合は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();
     }           
33
SharpCoder

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の答えも見てください。

16
neontapir

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();
        }
11
SRI

@ 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");
8
Doguhan Uluca

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でした。

4
Reiner

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}");
            ...
        }
    }
3
lawrenceagbani
request.Headers.FirstOrDefault( x => x.Key == "MyCustomID" ).Value?.FirstOrDefault()

現代の変種:)

ワンラインソリューション

var id = request.Headers.GetValues("MyCustomID").FirstOrDefault();
1
Roman Marusyk