How to add custom header to ASP.NET Core Web API response

Viewed 139732

I am porting my API from Web API 2 to ASP.NET Core Web API. I used to be able to add a custom header in the following manner:

  HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
  response.Headers.Add("X-Total-Count", count.ToString());
  return ResponseMessage(response);

How does one add a custom header in ASP.NET Core Web API?

7 Answers

For anyone who want to add custom header to all requests, middleware is the best way. make some change in startup.cs like this:

app.Use(async (context, next) =>
{
   context.Response.Headers.Add("X-Developed-By", "Your Name");
   await next.Invoke();
});

Good luck.

A custom attribute can be a good way.

https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-2.2

public class AddHeaderAttribute : ResultFilterAttribute
{
    private readonly string _name;
    private readonly string _value;

    public AddHeaderAttribute(string name, string value)
    {
        _name = name;
        _value = value;
    }

    public override void OnResultExecuting(ResultExecutingContext context)
    {
        context.HttpContext.Response.Headers.Add(_name, new string[] { _value });
        base.OnResultExecuting(context);
    }
}

Then use it like this on your API method

[AddHeader("X-MyHeader", "123")]

If you have a common header you can just extend this class :

public class MySpecialHeaderAttribute : AddHeaderAttribute
{
    public MySpecialHeaderAttribute() : base("X-MyHeader", "true")
    {
    }
}

I agree with @Ho3Ein that

if you want to add a custom header to all requests, middleware is the best way

but modifying Resposne directly in middleware is discouraged. From Microsoft Doc.

Changes to HttpResponse after the response has started, throw an exception. For example, changes such as setting headers and a status code throw an exception.

app.Use(async (context, next) =>
        {
            // Do work that doesn't write to the Response.
            await next.Invoke();
            // Do logging or other work that doesn't write to the Response.
        });

So the better way to add a custom header in middleware is to use Response.OnStarting callback like below:

app.Use(async (context, next) =>
                      {

                          context.Response.OnStarting(() =>
                              {
                                  context.Response.Headers.Add("X-Developed-By", "Your Name");
                                  return Task.FromResult(0);
                              });

                          await next();
                      }
                      );

Other middleware might clear out headers after you set them. To make sure your headers are added, add them just before the response is sent.

app.Use(async (context, next) => {
    context.Response.OnStarting(() => {
        context.Response.Headers.Add("X-Developed-By", "Your Name");
        return Task.FromResult(0);
    });

    await next();
});

Or in a real middleware

public class AddHeadersMiddleware : IMiddleware
{
    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        context.Response.OnStarting(() => {
            context.Response.Headers.Add("X-Developed-By", "Your Name");
            return Task.FromResult(0);
        });

        await next();
    }
}

FWIW, if you have an ApiController, instead of a Controller, here is how you can do it:

public class InfoController : ApiController
{
    // Without custom header
    public IHttpActionResult MyMethod(..)
    {
        var myObject= GetMyResult();
        return Ok(myObject);
    }

    // With custom header
    public IHttpActionResult MyMethod(..)
    {
        var myObject = GetMyResult();

        // inspired from https://docs.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/content-negotiation#how-content-negotiation-works
        var negotiator = Configuration.Services.GetContentNegotiator();
        var result = negotiator.Negotiate(typeof(TypeOfMyObject), Request, Configuration.Formatters);
        var msg = new HttpResponseMessage(HttpStatusCode.OK)
        {
            Content = new ObjectContent<TypeOfMyObject>(myObject, result.Formatter,result.MediaType.MediaType)
        };

        msg.Headers.Add("MyCustomHeader", "MyCustomHeaderValue");
        return ResponseMessage(msg);
    }
}
Related