Introduction
With Owin Pipeline, you can easily get response body stream inside your custom middleware class, but not in case of MVC, because the MVC framework doesn't stream response body through the owin pipeline. In this tip, we will use a simple trick to get MVC response body inside your custom middleware class.
Background
First of all, let's make a helper class that will manage streams by copying the output stream into a memory stream.
internal class StreamHelper: Stream
{
private Stream InnerStream;
public MemoryStream CapturedData { get; private set; }
public StreamHelper(Stream inner)
{
InnerStream = inner;
CapturedData = new MemoryStream();
}
public override bool CanRead
{
get { return InnerStream.CanRead; }
}
public override bool CanSeek
{
get { return InnerStream.CanSeek; }
}
public override bool CanWrite
{
get { return InnerStream.CanWrite; }
}
public override void Flush()
{
InnerStream.Flush();
}
public override long Length
{
get { return InnerStream.Length; }
}
public override long Position
{
get { return InnerStream.Position; }
set { CapturedData.Position = InnerStream.Position = value; }
}
public override int Read(byte[] buffer, int offset, int count)
{
return InnerStream.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
CapturedData.Seek(offset, origin);
return InnerStream.Seek(offset, origin);
}
public override void SetLength(long value)
{
CapturedData.SetLength(value);
InnerStream.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
CapturedData.Write(buffer, offset, count);
InnerStream.Write(buffer, offset, count);
}
}
Now inside our Middleware
class, we can capture response body by using our StreamHelper
as a filter for HttpResponse
.
public class DebugMiddleware : OwinMiddleware
{
OwinMiddleware _next;
public DebugMiddleware(OwinMiddleware next) : base(next)
{
_next = next;
}
public async override Task Invoke(IOwinContext context)
{
HttpResponse httpResponse = HttpContext.Current.Response;
StreamHelper outputCapture = new StreamHelper(httpResponse.Filter);
httpResponse.Filter = outputCapture;
IOwinResponse owinResponse = context.Response;
Stream owinResponseStream = owinResponse.Body;
owinResponse.Body = new MemoryStream();
await Next.Invoke(context);
if (outputCapture.CapturedData.Length == 0)
{
owinResponse.Body.Position = 0;
await owinResponse.Body.CopyToAsync(owinResponseStream);
}
else
{
outputCapture.CapturedData.Position = 0;
outputCapture.CapturedData.CopyTo(owinResponse.Body);
}
owinResponse.Body.Seek(0, SeekOrigin.Begin);
var responseBody = new StreamReader(owinResponse.Body).ReadToEnd();
Debug.WriteLine(responseBody);
}
Example Proejct
https://github.com/pashkovdenis/Using-Owin-Middleware-for-MVC-Response-Logging-Example