How to set custom headers when using IHttpActionResult?
asp.net, asp.net-web-api, c#
Solution
For your scenario, you would need to create a custom `IHttpActionResult`. Following is an example where I derive from `OkNegotiatedContentResult<T>` as it runs `Content-Negotiation` and sets the `Ok` status code.
public class CustomOkResult<T> : OkNegotiatedContentResult<T>
{
public CustomOkResult(T content, ApiController controller)
: base(content, controller) { }
public CustomOkResult(T content, IContentNegotiator contentNegotiator, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters)
: base(content, contentNegotiator, request, formatters) { }
public string ETagValue { get; set; }
public override async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage response = await base.ExecuteAsync(cancellationToken);
response.Headers.ETag = new EntityTagHeaderValue(this.ETagValue);
return response;
}
}
Controller:
public class ValuesController : ApiController
{
public IHttpActionResult Get()
{
return new CustomOkResult<string>(content: "Hello World!", controller: this)
{
ETagValue = "You ETag value"
};
}
}
Note that you can also derive from `NegotiatedContentResult<T>`, in which case you would need to supply the StatusCode yourself. Hope this helps.
You can find the source code of `OkNegotiatedContentResult<T>` and `NegotiatedContentResult<T>`, which as you can imagine are simple actually.
Problem
In ASP.NET Web API 2, the `IHttpActionResult` offers a lot of value in simplifying controller code and I'm reluctant to stop using it, but I've hit a problem. I need to set an ETag on an outgoing response, and I cannot find any property which gives me access to the response's headers. At the moment I'm using the `Ok<T>(T content)` helper method from the `ApiController`, which returns an `OkNegotiatedContentResult<T>` object. That doesn't seem to have anything exposed which would let me modify the headers though. Am I missing something, or is there really no way to do this while using the stock `IHttpActionResult` types? I considered a message handler, but then I'd have to figure out how to pass the ETag out of the action (the ETags are generated differently for different actions, so it's not a matter of making a generic handler for all actions). I'd like to avoid having to use the raw HttpResponseMessage, but at the moment that's looking difficult.