Search code examples
c#asp.net-mvchttpresponseowin-middleware

Reading the response body in owin middleware


I'm trying to get a copy of a response after my MVC controller action has executed but from other questions on here I can't get this code working (even though this appeared to be a well answered problem) ...

public class Startup
{
   public void Configuration(IAppBuilder app)
   {
     app.Use(async (context, next) =>
     {
        var resultStream = context.Response.Body;
        context.Response.Body = new MemoryStream();

        // allow the response to be written in future request lifecycle events
        await next.Invoke();

        // fetch the repsonse
        context.Response.Body.Seek(0, SeekOrigin.Begin);
        var headers = context.Response.Headers;
        var body = new StreamReader(context.Response.Body).ReadToEnd();

        // ... other code omitted for question clarity

        // write the response to the client
        context.Response.Body.Seek(0, SeekOrigin.Begin);
        await context.Response.Body.CopyToAsync(resultStream);
        context.Response.Body = resultStream;
      });
   }

   // ... other code omitted for question clarity
}

When I get to the second seek the variable "body" is empty.

Any ideas why this may be the case when the result after this is a page with content ?


Solution

  • So it turns out the problem here is to do with the fact that Owin and asp.net are not intertwined in the full lifecycle together as I had thought.

    In short, the request lifecycle looks something like ...

    1. Do Owin stuff (all owin middlewares)
    2. Do MVC stuff
    3. Do server stuff

    ... what I need is ...

    1. Do owin stuff
    2. Do MVC stuff
    3. Do more Owin stuff
    4. Do server stuff

    ... of course i'm hugely over simplifying the process here but i guess the short way to explain it is when you do ...

    app.Use((context, next) => { ... }).UsestageMarker(?);
    

    ... there is no stage marker for "response processing complete".

    Interestingly aspnet core gives us much more control as the tight integration with all the pieces throughout the request lifecycle are less dependent on predefined stages and more about you the user defining your own process for handling requests and constructing the response.

    In short ... in aspnet core I can do what i'm trying to do but this does not appear to be possible in owin with .net 4.6

    I did however a few references to using filters and handling "OnActionExectuted" which if you look you have a completely different Request and Response object than those given to you by owin middleware's pipeline (thus adding more evidence that these things are not in fact one single process but simply two that happen in an order).

    I have since spent the time looking at migrating my application to aspnet core ... which is proving to be more of a headache than i had anticipated, but i'm ever hopeful of the final result being cleaner and faster.