How To Render Razor View To String
This post is a continuation of the last post I wrote couple of days ago about How To Send E-mail In ASP.Net Core Using Mailkit.
From the last post, we were able to send a successful e-mail using MailKit with no problem. Therefore, in this post I’m going to cover how to use the RazorViewEngine to render Views, and get the string content to be used as an email template.
Since we’ll be using the same solution, let’s download it from github first and make sure it’s build properly.
Add HTML View Template
First we’ll need to add a new view called “Welcome” as shown below.
Next, we’ll use the following html as the template for the email. If you are planning on using this template for more than one type of emails, the best thing would be to create a layout and use that with the views. But since this is just to demonstrate how to render the view into a string to send the html content we’ll keep it simple with just welcome view.
Demystifying Email Design
|
|||||
|
Now that we have the view in place, make sure to add the action method for that view in the home controller class as shown below.
public IActionResult Welcome() { return View(); }
Add helper to render view into string
- Right click on the solution and add a new folder called “Helpers”
- Next, let’s add a new class called “ViewsToStringOutputHelper.cs” and copy and paste the following code snippet into it.
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.ViewEngines; using Microsoft.AspNetCore.Mvc.ViewFeatures; using System.IO; namespace SendEmailInAspNetCore.Helpers { public class ViewsToStringOutputHelper { public static string RenderRazorViewToString(Controller controller, string viewName, object model) { controller.ViewData.ModelState.Clear(); controller.ViewData.Model = model; using (var sw = new StringWriter()) { ViewEngineResult viewResult = null; var engine = controller.HttpContext.RequestServices.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine; viewResult = engine.FindView(controller.ControllerContext, viewName, false); var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw, new HtmlHelperOptions()); viewResult.View.RenderAsync(viewContext); return sw.GetStringBuilder().ToString(); } } } }
Render the view into a string
- Next, let’s modified the Contact action method to use the new helper to render the view into a string.
- First, I need a new variable for the email body string object and another flag to determine whether to use the email template or not
string emailBody = string.Empty; bool useEmailTemplate = false;
- Then, let’s add a new condition to determine if we should use the template or not as shown below
if (useEmailTemplate) { emailBody = ViewsToStringOutputHelper.RenderRazorViewToString(this, "Welcome", null); } else { emailBody = contactViewModel.Message + " Message was sent by: " + contactViewModel.Name + " E-mail: " + contactViewModel.Email; } message.Body = new TextPart(TextFormat.Html) { Text = emailBody };
Sending a new email using a rendered view to string template
- First, we’ll send an email with the useEmailTemplate flag set to false and then another with it set to true. As you can see below, the new html template indeed used in the second email.