Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add Response Headers to ASP.NET Core Middleware

I want to add a processing time middleware to my ASP.NET Core WebApi like this

public class ProcessingTimeMiddleware   {     private readonly RequestDelegate _next;      public ProcessingTimeMiddleware(RequestDelegate next)     {         _next = next;     }      public async Task Invoke(HttpContext context)     {         var watch = new Stopwatch();         watch.Start();          await _next(context);          context.Response.Headers.Add("X-Processing-Time-Milliseconds", new[] { watch.ElapsedMilliseconds.ToString() });     } } 

But doing this throws an exception saying

 System.InvalidOperationException: Headers are readonly, reponse has already started. 

How can I add headers to the response?

like image 471
Gillardo Avatar asked May 23 '16 15:05

Gillardo


People also ask

How do I add a header to a response in net core?

Adding Custom Header for Individual Response We create a very basic HTTP GET endpoint. Within this endpoint, we access the Response object through the HttpContext object. Then, we add a new header, with the name of x-my-custom-header and a value of individual response .

How do I get custom header values in net core API?

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.

What is IHTTPContextAccessor?

IHttpContextAccessor Interface (Microsoft.AspNetCore.Http)Provides access to the current HttpContext, if one is available.


2 Answers

Never mind, the code is here

    public async Task Invoke(HttpContext context)     {         var watch = new Stopwatch();         watch.Start();          //To add Headers AFTER everything you need to do this         context.Response.OnStarting(state => {             var httpContext = (HttpContext)state;             httpContext.Response.Headers.Add("X-Response-Time-Milliseconds", new[] { watch.ElapsedMilliseconds.ToString() });              return Task.CompletedTask;         }, context);          await _next(context);     } 
like image 114
Gillardo Avatar answered Sep 23 '22 21:09

Gillardo


Response headers can't be set after anything has been written to the response body.Once you pass the request to next middleware and it writes to the Response, then the Middleware can't set the Response headers again.

However, there is a solution available using a Callback method.

Microsoft.AspNetCore.Http.HttpResponse defines the OnStarting Method, which Adds a delegate to be invoked just before response headers will be sent to the client. You can think this method as a callback method that will be called right before writing to the response starts.

public class ResponseTimeMiddleware     {         private const string RESPONSE_HEADER_RESPONSE_TIME = "X-Response-Time-ms";          private readonly RequestDelegate _next;          public ResponseTimeMiddleware(RequestDelegate next)         {             _next = next;         }          public Task InvokeAsync(HttpContext context)         {             var watch = new Stopwatch();             watch.Start();              context.Response.OnStarting(() =>              {                 watch.Stop();                 var responseTimeForCompleteRequest = watch.ElapsedMilliseconds;                 context.Response.Headers[RESPONSE_HEADER_RESPONSE_TIME] =  responseTimeForCompleteRequest.ToString();                  return Task.CompletedTask;             });              // Call the next delegate/middleware in the pipeline             return this._next(context);         }     } 
like image 22
Abhinav Galodha Avatar answered Sep 24 '22 21:09

Abhinav Galodha