Question

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?

Was it helpful?

Solution 2

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).

OTHER TIPS

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.

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);
                    }
                }
            }
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top