I'm developing an ASP.NET MVC application that will send the user a confirmation email. For the email itself, I'd like to create a view and then render that view and send it using the .NET mail objects.
How can I do this using the MVC framework?
I'm developing an ASP.NET MVC application that will send the user a confirmation email. For the email itself, I'd like to create a view and then render that view and send it using the .NET mail objects.
How can I do this using the MVC framework?
You basically need to use IView.Render
. You can get the view by using ViewEngineCollection.FindView
(ViewEngines.Engines.FindView
for the defaults). Render the output to a TextWriter
and make sure you call ViewEngine.ReleaseView
afterwards. Sample code below (untested):
StringWriter output = new StringWriter();
string viewName = "Email";
string masterName = "";
ViewEngineResult result = ViewEngines.Engines.FindView(ControllerContext, viewName, masterName);
ViewContext viewContext = new ViewContext(ControllerContext, result.View, viewData, tempData);
result.View.Render(viewContext, output);
result.ViewEngine.ReleaseView(ControllerContext, result.View);
string viewOutput = output.ToString();
I'll leave viewData / tempData to you.
As per my comment on Richard's answer, this code did work, but it always resulted in a 'Cannot redirect after HTTP headers have been sent' error.
After a lot of digging around Google and being frustrated, I finally found some code that seems to do the trick, on this article:
http://mikehadlow.blogspot.com/2008/06/mvc-framework-capturing-output-of-view_05.html
This guy's method is to create his own HttpContext.
Rather than use the MVCContrib BlockRenderer I simply replace the current HttpContext with a new one that hosts a Response that writes to a StringWriter.
This method works perfectly (a minor difference is that I had to create a separate Action for rendering my partial view, but no drama there).
This worked for me:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
namespace Profiteer.WebUI.Controllers
{
public class SampleController : Controller
{
public ActionResult Index()
{
RenderViewAsHtml(RouteData.Values["controller"].ToString(),
RouteData.Values["action"].ToString());
return View();
}
private void RenderViewAsHtml(string controllerName, string viewName)
{
var vEngine = (from ve in ViewEngineCollection
where ve.GetType() == typeof(RazorViewEngine)
select ve).FirstOrDefault();
if (vEngine != null)
{
var view =
vEngine.FindView(
ControllerContext,
viewName, "_Layout", false).View as RazorView;
if (view != null)
{
var outPath =
Server.MapPath(
string.Format("~/Views/{0}/{1}.html",
controllerName, viewName));
using (var sw = new StreamWriter(outPath, false))
{
var viewContext =
new ViewContext(ControllerContext,
view,
new ViewDataDictionary(),
new TempDataDictionary(),
sw);
view.Render(viewContext, sw);
}
}
}
}
}
}