我认为如果我可以将新的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/
答案 0 :(得分:17)
这是一些丑陋丑陋的代码,除了让它正常工作外,没有经过测试而被黑客攻击。
由于我们没有处理服务器上的实际视图,我们必须添加自己的路径提供程序来告诉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)]));
}
}
}
此类将您的模板作为构造函数参数,并将其添加到静态字典中,然后由上面的VirtualPathProvider
读取。然后调用Render
,您可以选择传入模型。这会将完全限定的模型类型添加到@inherits
,并将其添加到文件内容中。
public class RazorViewEngineRender {
internal static Dictionary<string, string> strings { get; set; }
string guid;
static RazorViewEngineRender() {
strings = new Dictionary<string, string>();
}
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文件中,您必须将以下内容添加到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”}并且它正在抛出错误。我不确定为什么,也不太了解它。
这很有趣,谢谢你提出这个问题。
答案 1 :(得分:5)
Razor的设计考虑了独立操作。关于该模式的文档还不多(因为它仍处于开发阶段),但请查看Andrew Nurse撰写的这篇博文:http://vibrantcode.com/blog/2010/7/22/using-the-razor-parser-outside-of-aspnet.html