After all partial views are rendered and all styles are inlined my RESTful service is sending them via email. I implemented this feature with a MailerMiddleware
.
This middleware dumps the response body and uses it as the body of the email. I pass the recipients and the subject via the HttpContext.Items
property from the controller to the middleware. It uses the <system.net>
element in the app.config
for sending emails.
public class MailerMiddleware
{
private readonly RequestDelegate _next;
private readonly IEmailClient _emailClient;
public MailerMiddleware(RequestDelegate next, IEmailClient emailClient)
{
_next = next;
_emailClient = emailClient;
}
public async Task Invoke(HttpContext context)
{
if (context.Request.Method == "POST")
{
var bodyBackup = context.Response.Body;
using (var memory = new MemoryStream())
{
context.Response.Body = memory;
await _next(context);
memory.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(memory))
{
var recipients = (string)context.Items["Recipients"];
var subject = (string)context.Items["Subject"];
var body = await reader.ReadToEndAsync();
memory.Seek(0, SeekOrigin.Begin);
var restoreBody = memory.CopyToAsync(bodyBackup);
var sendEmail = _emailClient.SendAsync(new Email<EmailSubject, EmailBody>
{
To = recipients,
Subject = new PlainTextSubject(subject),
Body = new ParialViewEmailBody(body),
});
await Task.WhenAll(restoreBody, sendEmail);
}
}
}
else
{
await _next(context);
}
}
}
Inside the action method:
[HttpPost("TestReport")] [ActionName("TestReport")] public IActionResult PostTestReport([FromBody] TestReportBody body) { HttpContext.Items["Recipients"] = "example@email.com"; // todo use body HttpContext.Items["Subject"] = "Test email"; // todo use body return PartialView(body); }
This solution is working great but is there anything that could still be done better?