WebApi: mapping parameter to header value WebApi: mapping parameter to header value asp.net asp.net

WebApi: mapping parameter to header value


I don't think this is supported out of the box, like for example with the [FromBody] attribute. It seems you should be able to achieve this functionality by using Model Binders, as described here. In the model binder you have access to the request and its headers, so you should be able to read the header and set its value to the bindingContext.Model property.

Edit: Reading the article further, it seems a custom HttpParameterBinding and a ParameterBindingAttribute is a more appropriate solution, or at least I would go this way. You could implement a generic [FromHeader] attribute, which does the job. I am also fighting the same problem, so I will post my solution once I have it in place.

Edit 2: Here is my implementation:

public class FromHeaderBinding : HttpParameterBinding{    private string name;    public FromHeaderBinding(HttpParameterDescriptor parameter, string headerName)         : base(parameter)    {        if (string.IsNullOrEmpty(headerName))        {            throw new ArgumentNullException("headerName");        }        this.name = headerName;    }    public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken)    {        IEnumerable<string> values;        if (actionContext.Request.Headers.TryGetValues(this.name, out values))        {            actionContext.ActionArguments[this.Descriptor.ParameterName] = values.FirstOrDefault();        }        var taskSource = new TaskCompletionSource<object>();        taskSource.SetResult(null);        return taskSource.Task;    }}public abstract class FromHeaderAttribute : ParameterBindingAttribute{    private string name;    public FromHeaderAttribute(string headerName)    {        this.name = headerName;    }    public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter)    {        return new FromHeaderBinding(parameter, this.name);    }}public class MyHeaderAttribute : FromHeaderAttribute{    public MyHeaderAttribute()        : base("MyHeaderName")    {    }}

Then you can use it like this:

[HttpGet]public IHttpActionResult GetItem([MyHeader] string headerValue){    ...}

Hope that helps.


WebApi on DotNet Core has a has some additional attributes for extracting data from the request. Microsoft.AspNetCore.Mvc.FromHeaderAttribute will read from the request head.

public ActionResult ReadFromHeader([FromHeader(Name = "your-header-property-name")] string data){   //Do something}


Thank you filipov for the answer.. I took your code and modified it a bit to suit my needs. I am posting my changes here in case anyone can make use of this.

I made 2 changes.

  1. I liked the idea of the FromHeaderAttribute, but without subclassing. I made this class public, and require the user to set the param name.

  2. I needed to support other data types besides string. So I attempt to convert the string value to the descriptor's parameterType.

Use it like this:

[HttpGet]public void DeleteWidget(long widgetId, [FromHeader("widgetVersion")] int version){    ... }

And this is my FromHeaderBinding

public class FromHeaderBinding : HttpParameterBinding{    private readonly string _name;    public FromHeaderBinding(HttpParameterDescriptor parameter, string headerName)        : base(parameter)    {        if (string.IsNullOrEmpty(headerName)) throw new ArgumentNullException("headerName");        _name = headerName;    }    public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken)    {        IEnumerable<string> values;        if (actionContext.Request.Headers.TryGetValues(_name, out values))        {            var tempVal = values.FirstOrDefault();            if (tempVal != null)            {                var actionValue = Convert.ChangeType(tempVal, Descriptor.ParameterType);                actionContext.ActionArguments[Descriptor.ParameterName] = actionValue;            }        }        var taskSource = new TaskCompletionSource<object>();        taskSource.SetResult(null);        return taskSource.Task;    }}