以不同的方式使用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