2

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 ?

War
  • 8,539
  • 4
  • 46
  • 98
  • Does `UseMvc()` immediately follow your middleware `.Use()` call? – Rudi Visser Jun 02 '18 at 13:09
  • 1
    That looks like an ASP.NET Core middleware rather than an OWIN one. – Camilo Terevinto Jun 02 '18 at 13:14
  • @RudiVisser it does not, also this is not .Net core it's .Net 4.6 – War Jun 02 '18 at 13:44
  • @War Then `next` does not refer to your controller execution which is the only way that this could work? EDIT: FullFx or not I'd assume the approach is similar. What's the next Middleware in your pipeline? It *must* be the MVC middleware or else you're not going to get your controller's result. EDIT2: Actually maybe not, as you'll be waiting for the whole pipeline to complete.. Hmm – Rudi Visser Jun 02 '18 at 13:44
  • I have no idea what next refers to ... owin is a complex pipeline .. but my understanding is that if if you invoke and await next then you invoke the whole pipeline not just the next middleware item in the pipeline. I am seeing my controller action get hit between await next and the first seek call though. – War Jun 02 '18 at 13:48
  • The context is empty because you have not passed it along to the next middleware in the pipeline. `await next.Invoke(context);` – Nkosi Jun 02 '18 at 17:23

1 Answers1

1

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.

War
  • 8,539
  • 4
  • 46
  • 98