Justin
Justin

Reputation: 10907

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("[email protected]", "Email Subject", htmlEmailBody);

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

Upvotes: 21

Views: 14514

Answers (7)

Ryan Tofteland
Ryan Tofteland

Reputation: 913

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.

Upvotes: 28

Fabio Maulo
Fabio Maulo

Reputation: 466

Still working outside a web app with the last MVC FullFW

http://fabiomaulo.blogspot.com/2011/08/parse-string-as-razor-template.html

You can create a worker consuming queue rendering and sending emails outside the web. Few code lines, you don't need another package over Razor.

Upvotes: 0

toddmo
toddmo

Reputation: 22466

Based on Ryan's answer, I did an extension method:

public static string RenderViewToString(this Controller source, string viewName)
{
  var viewEngineResult = ViewEngines.Engines.FindView(source.ControllerContext, viewName, null);
  using (StringWriter output = new StringWriter())
  {
    viewEngineResult.View.Render(new ViewContext(source.ControllerContext, viewEngineResult.View, source.ViewData, source.TempData, output), output);
    viewEngineResult.ViewEngine.ReleaseView(source.ControllerContext, viewEngineResult.View);
    return output.ToString();
  }
}

To call from inside a controller action (example usage):

  [AllowAnonymous]
  public class ErrorController : Controller
  {
    // GET: Error
    public ActionResult Index(System.Net.HttpStatusCode id)
    {
      Exception ex = null; // how do i get the exception that was thrown?
      if (!Debugger.IsAttached)
        Code.Email.Send(ConfigurationManager.AppSettings["BugReportEmailAddress"], 
          $"Bug Report: AgentPortal: {ex?.Message}", 
          this.RenderViewToString("BugReport"));
      Response.StatusCode = (int)id;
      return View();
    }
  }

Upvotes: 0

Konstantin Smolyakov
Konstantin Smolyakov

Reputation: 755

There is also Essential Mail: Razor package from NuGet. It is build over RazorEngine and provides simple interface for email rendering.

Email message template looks something like

@inherits Essential.Templating.Razor.Email.EmailTemplate
@using System.Net;
@{
    From = new MailAddress("[email protected]");
    Subject = "Email Subject";
}
@section Html 
{
   <html>
      <head>
          <title>Example</title>
      </head>
      <body>
          <h1>HTML part of the email</h1>
      </body>
   </html>
}
@section Text 
{
    Text part of the email.
}

The project is hosted on GitHub: https://github.com/smolyakoff/essential-templating/wiki/Email-Template-with-Razor

Upvotes: 1

davehauser
davehauser

Reputation: 5962

Another one would be ActionMailer.Net: https://bitbucket.org/swaj/actionmailer.net/wiki/Home

From the website: An MVC 3-based port of the Rails ActionMailer library to ASP.NET MVC. The goal is to make it easy and relatively painless to send email from your application.

NuGet: Install-Package ActionMailer

Upvotes: 3

CD..
CD..

Reputation: 74176

Try MvcMailer: http://www.codeproject.com/KB/aspnet/MvcMailerNuGet.aspx

Upvotes: 4

Darin Dimitrov
Darin Dimitrov

Reputation: 1039438

You may checkout Postal for using views for sending emails.

Upvotes: 10

Related Questions