c# - net - ¿Cómo extraer el valor del encabezado personalizado en el controlador de mensajes Web API?
web api rest c# (8)
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<string> keys = null;
if (!request.Headers.TryGetValues(key, out keys))
return null;
return keys.First();
}
Actualmente tengo un controlador de mensajes en mi servicio Web API que reemplaza a ''SendAsync'' de la siguiente manera:
protected override Task<HttpResponseMessage> 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?
La siguiente línea throws exception
si la clave no existe.
IEnumerable<string> headerValues = request.Headers.GetValues("MyCustomID");
Trabaja alrededor:
Incluir System.Linq;
IEnumerable<string> headerValues;
var userId = string.Empty;
if (request.Headers.TryGetValues("MyCustomID", out headerValues))
{
userId = headerValues.FirstOrDefault();
}
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<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}");
...
}
}
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.
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<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;
}
}
Uso de muestra:
var myValue = response.GetFirstHeaderValueOrDefault<int>("MyValue");
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<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);
}
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.
Pruebe algo como esto:
IEnumerable<string> 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.
request.Headers.FirstOrDefault( x => x.Key == "MyCustomID" ).Value?.FirstOrDefault()
variante moderna :)