wake-up-neo.net

So extrahieren Sie einen benutzerdefinierten Header-Wert im Web-API-Meldungshandler

Ich habe derzeit einen Message-Handler in meinem Web-API-Dienst, der 'SendAsync' wie folgt überschreibt:

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
  //implementation
}

In diesem Code muss ich einen benutzerdefinierten hinzugefügten Anforderungsheaderwert namens MyCustomID überprüfen. Das Problem ist, wenn ich Folgendes mache:

if (request.Headers.Contains("MyCustomID"))  //OK
    var id = request.Headers["MyCustomID"];  //build error - not OK

... bekomme ich folgende Fehlermeldung:

Die Indexierung mit [] kann nicht auf einen Ausdruck vom Typ .__ angewendet werden. 'System.Net.Http.Headers.HttpRequestHeaders'

Wie kann ich auf einen benutzerdefinierten Anforderungsheader single über die Instanz HttpRequestMessage ( MSDN Documentation ) zugreifen, die an diese überschriebene Methode übergeben wird?

129
atconway

Versuchen Sie etwas so:

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

Es gibt auch eine TryGetValues-Methode für Header, die Sie verwenden können, wenn der Zugriff auf den Header nicht immer gewährleistet ist.

225

Die Zeile unter throws exception, falls der Schlüssel nicht vorhanden ist. 

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

Umgehen:

Include System.Linq;

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

     if (request.Headers.TryGetValues("MyCustomID", out headerValues))
     {
         userId = headerValues.FirstOrDefault();
     }           
30
SharpCoder

Um Youssefs Antwort zu erläutern, habe ich diese Methode aufgrund der Bedenken von Drew bezüglich des nicht existierenden Headers geschrieben, da ich während des Unit-Tests auf diese Situation gestoßen bin.

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);
    }

Hier ein Beispiel:

GetFirstHeaderValueOrDefault("X-MyGuid", h => Guid.NewGuid().ToString(), Guid.Parse);

Sehen Sie sich auch die Antwort von @ doguhan-uluca an, um eine allgemeinere Lösung zu finden.

16
neontapir

Erstellen Sie eine neue Methode - ' Gibt einen einzelnen HTTP-Header-Wert zurück ' und ruft diese Methode jedes Mal mit einem Schlüsselwert auf, wenn Sie auf mehrere Schlüsselwerte von HttpRequestMessage zugreifen müssen.

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

Um die Lösung von @neontapir weiter zu erweitern, finden Sie hier eine allgemeinere Lösung, die sich gleichermaßen auf HttpRequestMessage oder HttpResponseMessage anwenden lässt und keine handcodierten Ausdrücke oder Funktionen erfordert.

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;
    }
}

Verwendungsbeispiel:

var myValue = response.GetFirstHeaderValueOrDefault<int>("MyValue");
8
Doguhan Uluca

Für ASP.Net Core gibt es eine einfache Lösung, wenn der Parameter param direkt in der Controller-Methode verwendet werden soll: Verwenden Sie die Annotation [FromHeader].

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

Zusatzinfo: In meinem Fall musste "myParam" ein String sein, int war immer 0.

3
Reiner

Bei ASP.NET können Sie den Header direkt von den Parametern in der Controller-Methode abrufen, indem Sie diese einfache Bibliothek/Paket verwenden. Es enthält ein [FromHeader]-Attribut wie in ASP.NET Core :). Zum Beispiel:

    ...
    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()

moderne Variante :)

Einzeilige Lösung

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