以不同的方式使用Razor视图引擎

我认为如果我可以使用新的MVC Razor View引擎作为邮件合并技术会很有趣。 它仍然可以是MVC网站的一部分,而不必是独立的控制台应用程序。

例:

string myTemplate = "Hello @Name, How are you today?"; ViewModel.Name = "Billy Boy"; string output = RazorViewEngineRender( myTemplate, ViewModel ); 

那么string output = "Hello Billy Boy, How are you today?"

主要的是我希望模板是从字符串而不是视图或部分视图驱动的。

有谁知道这是否可能?

更新:

Ben和Matt在codeplex上做了一个项目: http: //razorengine.codeplex.com/

警告

这是一些丑陋的丑陋代码,除了让它正常工作之外,它还没有经过测试而被黑客攻击。

的VirtualPathProvider

由于我们不处理服务器上的实际视图,因此我们必须添加自己的路径提供程序来告诉MVC从何处获取动态生成的模板。 应该有更多的测试,比如检查字符串Dictionary以查看是否已添加视图。

 public class StringPathProvider : VirtualPathProvider { public StringPathProvider() : base() { } public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart) { return null; } public override bool FileExists(string virtualPath) { if (virtualPath.StartsWith("/stringviews") || virtualPath.StartsWith("~/stringviews")) return true; return base.FileExists(virtualPath); } public override VirtualFile GetFile(string virtualPath) { if (virtualPath.StartsWith("/stringviews") || virtualPath.StartsWith("~/stringviews")) return new StringVirtualFile(virtualPath); return base.GetFile(virtualPath); } public class StringVirtualFile : System.Web.Hosting.VirtualFile { string path; public StringVirtualFile(string path) : base(path) { //deal with this later this.path = path; } public override System.IO.Stream Open() { return new System.IO.MemoryStream(System.Text.ASCIIEncoding.ASCII.GetBytes(RazorViewEngineRender.strings[System.IO.Path.GetFileName(path)])); } } } 

渲染类

此类将您的模板作为构造函数参数,并将其添加到静态Dictionary,然后由上面的VirtualPathProvider读取。 然后调用Render ,您可以选择传入模型。 这会将完全限定的模型类型添加到@inherits并将其添加到文件内容之前。

 public class RazorViewEngineRender { internal static Dictionary strings { get; set; } string guid; static RazorViewEngineRender() { strings = new Dictionary(); } public RazorViewEngineRender(string Template) { guid = Guid.NewGuid().ToString() + ".cshtml"; strings.Add(guid, Template); } public string Render() { return Render(null); } public string Render(object ViewModel) { //Register model type if (ViewModel == null) { strings[guid] = "@inherits System.Web.Mvc.WebViewPage\r\n" + strings[guid]; } else { strings[guid] = "@inherits System.Web.Mvc.WebViewPage<" + ViewModel.GetType().FullName + ">\r\n" + strings[guid]; } CshtmlView view = new CshtmlView("/stringviews/" + guid); System.Text.StringBuilder sb = new System.Text.StringBuilder(); System.IO.TextWriter tw = new System.IO.StringWriter(sb); ControllerContext controller = new ControllerContext(); ViewDataDictionary ViewData = new ViewDataDictionary(); ViewData.Model = ViewModel; view.Render(new ViewContext(controller, view, ViewData, new TempDataDictionary(), tw), tw); //view.ExecutePageHierarchy(); strings.Remove(guid); return sb.ToString(); } } 

Global.asax中

在global.asax文件中,您必须将以下内容添加到Application_Start

 System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProvider(new Controllers.StringPathProvider()); 

调用代码

 string Template = "Hello, @Model.Name"; Models.User user = new Models.User() { Name = "Billy Boy" }; RazorViewEngineRender view = new RazorViewEngineRender(Template); string Results = view.Render(user); //pass in your model 

笔记

适用于键入的模型。 我试图传递一个新的{Name =“Billy Boy”}并且它正在抛出错误。 我不确定为什么,也没有真正深入研究它。

这很有趣,谢谢你提出这个问题。

Razor的设计考虑了独立操作。 目前还没有关于该模式的文档(因为它仍在开发中),但请查看Andrew Nurse 撰写的这篇博文: http : //vibrantcode.com/blog/2010/7/22/using-the-剃刀解析器外的-aspnet.html