¿Cómo extraer el valor del encabezado personalizado en el controlador de mensajes Web API?

Actualmente tengo un controlador de mensajes en mi servicio Web API que reemplaza a ‘SendAsync’ de la siguiente manera:

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

Dentro de este código, debo inspeccionar un valor de encabezado de solicitud personalizado agregado llamado MyCustomID . El problema es cuando hago lo siguiente:

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

… Recibo el siguiente mensaje de error:

No se puede aplicar la indexación con [] a una expresión de tipo ‘System.Net.Http.Headers.HttpRequestHeaders’

¿Cómo puedo acceder a un único encabezado de solicitud personalizado a través de la instancia HttpRequestMessage ( Documentación MSDN ) pasada a este método reemplazado?

Pruebe algo como esto:

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

También hay un método TryGetValues ​​en los encabezados que puede usar si no siempre se garantiza el acceso al encabezado.

La siguiente línea throws exception si la clave no existe.

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

Trabaja alrededor:

Incluir System.Linq;

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

Para ampliar la respuesta de Youssef, escribí este método basado en las preocupaciones de Drew sobre el encabezado inexistente, porque me encontré con esta situación durante la prueba unitaria.

 private T GetFirstHeaderValueOrDefault(string headerKey, Func defaultValue, Func valueTransform) { IEnumerable 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); } 

Aquí hay un ejemplo de uso:

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

También eche un vistazo a la respuesta de @ doguhan-uluca para una solución más general.

Cree un nuevo método: ‘ Devuelve un valor de encabezado HTTP individual ‘ y llame a este método con valor de clave cada vez que necesite acceder a múltiples valores clave desde HttpRequestMessage.

 public static string GetHeader(this HttpRequestMessage request, string key) { IEnumerable keys = null; if (!request.Headers.TryGetValues(key, out keys)) return null; return keys.First(); } 

Para ampliar aún más la solución de @neontapir, aquí hay una solución más genérica que se puede aplicar a HttpRequestMessage o HttpResponseMessage por igual y no requiere expresiones codificadas a mano o funciones.

 using System.Net.Http; using System.Collections.Generic; using System.Linq; public static class HttpResponseMessageExtensions { public static T GetFirstHeaderValueOrDefault( this HttpResponseMessage response, string headerKey) { var toReturn = default(T); IEnumerable 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; } } 

Uso de muestra:

 var myValue = response.GetFirstHeaderValueOrDefault("MyValue"); 

Para ASP.Net Core existe una solución fácil si desea usar el parámetro directamente en el método del controlador: Use la anotación [FromHeader].

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

Información adicional: en mi caso, el “myParam” tenía que ser una cadena, int siempre era 0.

 request.Headers.FirstOrDefault( x => x.Key == "MyCustomID" ).Value?.FirstOrDefault() 

variante moderna 🙂

Para ASP.NET, puede obtener el encabezado directamente del parámetro en el método del controlador usando esta biblioteca / paquete simple . Proporciona un atributo [FromHeader] como el que tiene en ASP.NET Core :). Por ejemplo:

  ... using RazHeaderAttribute.Attributes; [Route("api/{controller}")] public class RandomController : ApiController { ... // GET api/random [HttpGet] public IEnumerable 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}"); ... } } 

Solución de una línea

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