Search code examples
asp.net-mvcviewrazor

Can I use an ASP.Net MVC Razor view to generate an nicely formatted HTML Body as the input for an email sent from the server?


I'd like to make use of the Model Binding / Rendering capabilities of a Razor View to generate the HTML Body Content for an email I'm sending from my ASP.NET MVC Application.

Is there a way to render a view to a string instead of returning it as the ActionResult of a GET request?

To illustrate I'm looking for something that will do the following...

    public ActionResult SendEmail(int id)
    {
        EmailDetailsViewModel emailDetails = EmailDetailsViewModel().CreateEmailDetails(id);

        // THIS IS WHERE I NEED HELP...
        // I want to pass my ViewModel (emailDetails) to my View (EmailBodyRazorView) but instead of Rending that to the Response stream I want to capture the output and pass it to an email client.
        string htmlEmailBody = View("EmailBodyRazorView", emailDetails).ToString();

        // Once I have the htmlEmail body I'm good to go.  I've got a utilityt that will send the email for me.
        MyEmailUtility.SmtpSendEmail("stevejobs@apple.com", "Email Subject", htmlEmailBody);

        // Redirect another Action that will return a page to the user confirming the email was sent.
        return RedirectToAction("ConfirmationEmailWasSent");
    }

Solution

  • If you just need to render the view into a string try something like this:

    public string ToHtml(string viewToRender, ViewDataDictionary viewData, ControllerContext controllerContext)
    {
        var result = ViewEngines.Engines.FindView(controllerContext, viewToRender, null);
    
        using (var output = new StringWriter())
        {
            var viewContext = new ViewContext(controllerContext, result.View, viewData, controllerContext.Controller.TempData, output);
            result.View.Render(viewContext, output);
            result.ViewEngine.ReleaseView(controllerContext, result.View);
    
            return output.ToString();
        }
    }
    

    You'll need to pass in the name of the view and the ViewData and ControllerContext from your controller action.