176 votes

Comment extraire la valeur d'un en-tête personnalisé dans le gestionnaire de messages de l'API Web ?

J'ai actuellement un gestionnaire de messages dans mon service d'API Web qui remplace "SendAsync" comme suit :

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

Dans ce code, je dois inspecter une valeur d'en-tête de demande ajoutée personnalisée nommée MyCustomID . Le problème est que lorsque je fais ce qui suit :

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

...je reçois le message d'erreur suivant :

Impossible d'appliquer l'indexation avec [] à une expression de type System.Net.Http.Headers.HttpRequestHeaders'.

Comment puis-je accéder à un simple l'en-tête de demande personnalisé via l'en-tête HttpRequestMessage ( Documentation MSDN ) passée dans cette méthode surchargée ?

0 votes

Que se passe-t-il si vous utilisez request.Headers.Get("MyCustomID"); ?

3 votes

Il n'y a pas Get' on the Type "HttpRequestHeaders". Le message : "Cannot resolve symbol 'Get'" est produit.

292voto

Youssef Moussaoui Points 5494

Essayez quelque chose comme ça :

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

Il y a aussi un TryGetValues sur les en-têtes que vous pouvez utiliser si vous n'avez pas toujours la garantie d'avoir accès à l'en-tête.

28 votes

Le contrôle de nullité pour GetValues ne sert à rien car il ne retournera jamais null. Si l'en-tête n'existe pas, vous obtiendrez une InvalidOperationException. Vous devez utiliser TryGetHeaders s'il est possible que l'en-tête n'existe pas dans la demande et vérifier si la réponse est fausse OU utiliser try/catch autour de l'appel GetValues (non recommandé).

5 votes

@Drew request.Headers.Single(h => h.Key == "Authorization") ; Beaucoup moins de code pour faire la même chose !

21 votes

Pourquoi ne pas simplement var id = request.Headers.GetValues("MyCustomID").FirstOrDefault();

46voto

SharpCoder Points 1167

La ligne ci-dessous throws exception si la clé n'existe pas.

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

Solution sûre utilisant TryGetValues :

Inclure System.Linq ;

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

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

17voto

neontapir Points 2692

Pour développer la réponse de Youssef, j'ai écrit cette méthode en me basant sur les préoccupations de Drew concernant l'inexistence de l'en-tête, car j'ai rencontré cette situation lors des tests unitaires.

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

Voici un exemple d'utilisation :

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

Consultez également la réponse de @doguhan-uluca pour une solution plus générale.

1 votes

Func et Action sont des constructions génériques de signature de délégué intégrées dans .NET 3.5 et plus. Je serais heureux de discuter de questions spécifiques sur la méthode, mais je vous recommande de vous renseigner d'abord sur ces questions.

1 votes

@neontapir (et d'autres) le deuxième paramètre est utilisé pour fournir une valeur par défaut si la clé n'est pas trouvée. Le troisième paramètre est utilisé pour "transformer" la valeur de retour afin qu'elle soit du type souhaité, qui spécifie également le type à retourner. Dans l'exemple, si 'X-MyGuid' n'est pas trouvé, le paramètre 2 lambda fournit essentiellement un guide par défaut sous forme de chaîne (comme il aurait été récupéré dans l'en-tête) et le troisième paramètre Guid.Parse traduira la valeur de chaîne trouvée ou par défaut en un GUID.

0 votes

@neontapir d'où vient Request dans cette fonction ? (et si c'est null, comment un nouveau HttpRequestMessage() aura-t-il des en-têtes ? N'est-il pas logique de retourner la valeur par défaut si Request est null ?

13voto

SRI Points 180

Créer une nouvelle méthode - ' Renvoie une valeur d'en-tête HTTP individuelle et appelez cette méthode avec la valeur de la clé à chaque fois que vous avez besoin d'accéder à plusieurs valeurs de clé à partir de 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();
        }

10voto

Doguhan Uluca Points 1733

Pour approfondir la solution de @neontapir, voici une solution plus générique qui peut s'appliquer aussi bien à HttpRequestMessage qu'à HttpResponseMessage et qui ne nécessite pas d'expressions ou de fonctions codées à la main.

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

Exemple d'utilisation :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X