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.
Using IHTTPContextAccessor to extract custom header The above–discussed HttpContext or Request class gives us access to metadata including headers of given HttpContext within Controller. However, if you need to access headers or any HttpContext metadata in other services or modules then please use IHTTPContextAccessor.
IHttpActionResult contains a single method, ExecuteAsync, which asynchronously creates an HttpResponseMessage instance. If a controller action returns an IHttpActionResult, Web API calls the ExecuteAsync method to create an HttpResponseMessage. Then it converts the HttpResponseMessage into an HTTP response message.
Custom HTTP headers are commonly meant to provide additional information that may be pertinent to a web developer, or for troubleshooting purposes. These headers often times begin with X- , however, we'll discuss naming convention further on.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With