Cómo agregar y obtener valores de encabezado en WebApi

98

Necesito crear un método POST en WebApi para poder enviar datos desde la aplicación al método WebApi. No puedo obtener el valor del encabezado.

Aquí he agregado valores de encabezado en la aplicación:

 using (var client = new WebClient())
        {
            // Set the header so it knows we are sending JSON.
            client.Headers[HttpRequestHeader.ContentType] = "application/json";

            client.Headers.Add("Custom", "sample");
            // Make the request
            var response = client.UploadString(url, jsonObj);
        }

Siguiendo el método de publicación de WebApi:

 public string Postsam([FromBody]object jsonData)
    {
        HttpRequestMessage re = new HttpRequestMessage();
        var headers = re.Headers;

        if (headers.Contains("Custom"))
        {
            string token = headers.GetValues("Custom").First();
        }
    }

¿Cuál es el método correcto para obtener valores de encabezado?

Gracias.

AndrewRalon
fuente

Respuestas:

186

En el lado de la API web, simplemente use el objeto Request en lugar de crear un nuevo HttpRequestMessage

     var re = Request;
    var headers = re.Headers;

    if (headers.Contains("Custom"))
    {
        string token = headers.GetValues("Custom").First();
    }

    return null;

Salida -

ingrese la descripción de la imagen aquí

ramiramilu
fuente
¿No puedes usar string token = headers.GetValues("Custom").FirstOrDefault();? Editar: Acabo de notar que coincidías con el estilo Qs original.
Aidanapword
Respondiendo a mi propia P: No. El headers.GetValues("somethingNotFound")lanza un InvalidOperationException.
Aidanapword
¿Uso beforeSenden JQuery ajax para enviar el encabezado?
Si8
Perfecto ... Usé el beforeSendy funcionó. Impresionante :) +1
Si8
¿Cuál es el tipo de variable de solicitud y puedo acceder a ella dentro del método del controlador? Estoy usando la API web 2. ¿Qué espacio de nombres necesito importar?
lohiarahul
21

Supongamos que tenemos un controlador de API ProductsController: ApiController

Hay una función Obtener que devuelve algún valor y espera algún encabezado de entrada (por ejemplo, nombre de usuario y contraseña)

[HttpGet]
public IHttpActionResult GetProduct(int id)
{
    System.Net.Http.Headers.HttpRequestHeaders headers = this.Request.Headers;
    string token = string.Empty;
    string pwd = string.Empty;
    if (headers.Contains("username"))
    {
        token = headers.GetValues("username").First();
    }
    if (headers.Contains("password"))
    {
        pwd = headers.GetValues("password").First();
    }
    //code to authenticate and return some thing
    if (!Authenticated(token, pwd)
        return Unauthorized();
    var product = products.FirstOrDefault((p) => p.Id == id);
    if (product == null)
    {
        return NotFound();
    }
    return Ok(product);
}

Ahora podemos enviar la solicitud desde la página usando JQuery:

$.ajax({
    url: 'api/products/10',
    type: 'GET',
    headers: { 'username': 'test','password':'123' },
    success: function (data) {
        alert(data);
    },
    failure: function (result) {
        alert('Error: ' + result);
    }
});

Espero que esto ayude a alguien ...

Venugopal M
fuente
9

Otra forma de usar el método TryGetValues.

public string Postsam([FromBody]object jsonData)
{
    IEnumerable<string> headerValues;

    if (Request.Headers.TryGetValues("Custom", out headerValues))
    {
        string token = headerValues.First();
    }
}   
Schandlich
fuente
6

Para .NET Core:

string Token = Request.Headers["Custom"];

O

var re = Request;
var headers = re.Headers;
string token = string.Empty;
StringValues x = default(StringValues);
if (headers.ContainsKey("Custom"))
{
   var m = headers.TryGetValue("Custom", out x);
}
SaadK
fuente
6

En caso de que alguien esté usando ASP.NET Core para el enlace de modelos,

https://docs.microsoft.com/en-us/aspnet/core/mvc/models/model-binding

Hay soporte integrado para recuperar valores del encabezado usando el atributo [FromHeader]

public string Test([FromHeader]string Host, [FromHeader]string Content-Type )
{
     return $"Host: {Host} Content-Type: {Content-Type}";
}
maravilla
fuente
3
Content-Typeno es un identificador válido de C #
thepirat000
5

prueba esta línea de códigos que funcionan en mi caso:

IEnumerable<string> values = new List<string>();
this.Request.Headers.TryGetValues("Authorization", out values);
Sufyan Ahmad
fuente
5

Como alguien ya señaló cómo hacer esto con .Net Core, si su encabezado contiene un "-" o algún otro carácter que .Net no permite, puede hacer algo como:

public string Test([FromHeader]string host, [FromHeader(Name = "Content-Type")] string contentType)
{
}
Scott
fuente
1

Para WEB API 2.0:

Tuve que usar en Request.Content.Headerslugar de Request.Headers

y luego declaré una extensión como se muestra a continuación

  /// <summary>
    /// Returns an individual HTTP Header value
    /// </summary>
    /// <param name="headers"></param>
    /// <param name="key"></param>
    /// <returns></returns>
    public static string GetHeader(this HttpContentHeaders headers, string key, string defaultValue)
    {
        IEnumerable<string> keys = null;
        if (!headers.TryGetValues(key, out keys))
            return defaultValue;

        return keys.First();
    }

Y luego lo invoqué de esta manera.

  var headerValue = Request.Content.Headers.GetHeader("custom-header-key", "default-value");

Espero que pueda ser de ayuda

Oscar Emilio Pérez Martínez
fuente
0

Necesita obtener el HttpRequestMessage del OperationContext actual. Usando OperationContext puedes hacerlo así

OperationContext context = OperationContext.Current;
MessageProperties messageProperties = context.IncomingMessageProperties;

HttpRequestMessageProperty requestProperty = messageProperties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;

string customHeaderValue = requestProperty.Headers["Custom"];
Jehof
fuente
0

Para .net Core en el método GET, puede hacer lo siguiente:

 StringValues value1;
 string DeviceId = string.Empty;

  if (Request.Headers.TryGetValue("param1", out value1))
      {
                DeviceId = value1.FirstOrDefault();
      }
Sharif Yazdian
fuente