强类型Razor视图作为电子邮件模板引擎



我知道有几个类似的问题可以解决这个话题,但我对答案不满意。

我想充分利用Razor View引擎,它可以将强类型视图与布局页面和局部视图一起使用。我想在视图的顶部声明模型,然后传入该模型。太简单了!在将动态模型传递到视图之前,不需要显式构建它们编辑:我想在Web应用程序的外部,在可以构造电子邮件正文的类库中执行此操作。这里真正的问题是使用Razor View Engine,它不是一个网络应用程序。

这背后的想法是,如果我有一个User对象,上面有20个属性,并且我的欢迎电子邮件的第一个版本只使用名称,但后来我想编辑模板以使用它们的CityStateEmail地址,那么我希望能够更新Razor视图,而不必添加代码、重新编译和重新部署。

我看到RazorEngine,我喜欢它的想法和简单性,但一切都是动态类型。我的问题是,我将从数据库中提取作为模型的数据。由于必须将事物推到动态类型中,我无法在View中获得所有属性。

我还看到了MvcMailer,这在理论上也很好,但它也遇到了同样的问题,即传递到视图中的所有数据模型都是动态的,并且不是强类型的。

我已经开始构建我自己的版本,这将需要几个web命名空间,如System.web.Mvc、System.web.Razor和System.web.WebPages,我对此很满意。问题是缺少HttpContext、ControllerContext和RouteData。。。。我正试着模仿它。我目前正试图研究DisplayMode,并找出如何在真实的Web上下文之外模拟这些模式。

有更好的方法吗?如果您要建议前面提到的两个框架中的一个,请注意我的问题,并告诉我是否有解决方案。

第2版:在玩了RazorEngine之后,强类型模型不一定像我想象的那样是一个大问题。我现在所希望的是能够使用布局页面和局部视图。我可以用被替换的字符串占位符来解决这个问题,但可能效率不高,也不太灵活。

假设您试图从控制器的操作方法中实现这一点,这里有一个简单的方法

此方法将为您提供强类型视图的输出:

public static string RenderViewToString(this Controller controller, string viewName, object model)
{
controller.ViewData.Model = model;
try
{
using (StringWriter sw = new StringWriter())
{
ViewEngineResult viewResult = ViewEngines.Engines.FindView(controller.ControllerContext, viewName, null);
ViewContext viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(controller.ControllerContext, viewResult.View);
return sw.ToString();
}
}
catch(Exception ex)
{
return ex.ToString();
}
}

然后,在控制器方法中,您所需要做的就是使用视图和模型的名称调用此方法。

public ActionResult Mail()
{
// whatever you use to get your User object
var model = new User();
var output = this.RenderViewToString("~/Views/User/Email.cshtml", model)
}

这将允许您模拟强类型视图的渲染,包括其关联布局,并将输出收集为字符串,然后可以使用该字符串通过电子邮件发送。

答案是,传入的对象是否是动态的似乎并不重要。我可以传递我的强类型对象,它将被原样接受,而无需使其成为动态对象或重建动态对象。

我的初步测试表明,这应该很好,效果很好。

试用Actionmailer.net:https://bitbucket.org/swaj/actionmailer.net/wiki/Home

我一直很成功地使用它。

查看RazorMachine。它类似于RazorEngine,但适用于布局。

最新更新