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?
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.
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();
}
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.
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();
}
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");
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.
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}");
...
}
}
request.Headers.FirstOrDefault( x => x.Key == "MyCustomID" ).Value?.FirstOrDefault()
moderne Variante :)
Einzeilige Lösung
var id = request.Headers.GetValues("MyCustomID").FirstOrDefault();