I use the following middleware to replace the response content:
app.Use(async (context, next) => {
var body = context.Response.Body;
using (var updatedBody = new MemoryStream()) {
context.Response.Body = updatedBody;
await next();
context.Response.Body = body;
updatedBody.Seek(0, SeekOrigin.Begin);
var newContent = new StreamReader(updatedBody).ReadToEnd();
// Replace content here ...
await context.Response.WriteAsync(newContent);
}
});
This works fine. However now say I have the following action method:
public IActionResult Image() {
return PhysicalFile(@"C:\myimage.jpg", "image/jpeg");
}
When it tries to display this image it won't load, but if I remove the middleware then it does.
Please note that I am using ASP.NET Core 3.
Here's the solution I have come up with:
app.Use(async (context, next) => {
var body = context.Response.Body;
using (var updatedBody = new MemoryStream()) {
context.Response.Body = updatedBody;
try {
await next();
} catch {
throw;
} finally {
context.Response.Body = body;
}
if (context.Response.StatusCode == 200 && context.Response.ContentType != null && context.Response.ContentType.Contains("text/html", StringComparison.InvariantCultureIgnoreCase)) {
updatedBody.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(updatedBody)) {
var newContent = reader.ReadToEnd();
// Replace content here
await context.Response.WriteAsync(newContent);
}
} else {
if (updatedBody.Length > 0)
await context.Response.Body.WriteAsync(updatedBody.ToArray());
}
}
});
This article helped thanks to @CodeCaster's suggestion. As an added bonus I have fixed an issue where it breaks the developer exception page by wrapping a try/catch around the call to the delegate.