asp.net mvc 使用nvelocity替代razor(一)
写在前面:这并不是我的原创代码,很多都是从KoobooCms源码上摘抄下来的。
项目背景:
现在做的这套系统需要一个CMS功能,项目经理跟我说Razor是不安全的(前端可以任意调用后端代码),于是乎让我用Nvelocity去替代原有的Razor引擎。并给了KoobooCMS的源码,让我仿照来写。写这篇博客也是为了记录下我这一个星期的工作,整理一下思路。俗话说的好,好记性不如烂笔头。
具体实现思路:
1. mvc路由的配置(统一的控制器)
2.构建自己的ViewResult
3.创建的模板引擎(NVelocityTemplateEngine)
4.创建NVelocityView
具体实现代码(只粘贴模板引擎的)
1.NVelocityViewEngine.cs
public class NVelocityViewEngine : VirtualPathProviderViewEngine, IViewEngine { public static NVelocityViewEngine Default = null; private static readonly IDictionary DEFAULT_PROPERTIES = new Hashtable(); private readonly VelocityEngine _engine; static NVelocityViewEngine() { DEFAULT_PROPERTIES.Add("file.resource.loader.class", "SailfishNet.CMS.Site.TemplateEngines.NVelocityEngines.FileResourceLoaderEx\\,SailfishNet.CMS"); DEFAULT_PROPERTIES.Add(RuntimeConstants.ENCODING_DEFAULT, "UTF-8"); DEFAULT_PROPERTIES.Add(RuntimeConstants.OUTPUT_ENCODING, "UTF-8"); DEFAULT_PROPERTIES.Add(RuntimeConstants.INPUT_ENCODING, "UTF-8"); Default = new NVelocityViewEngine(); } public NVelocityViewEngine() : this(DEFAULT_PROPERTIES) { } public NVelocityViewEngine(IDictionary properties) { base.MasterLocationFormats = new string[] { "~/Views/{1}/{0}.vm", "~/Views/Shared/{0}.vm" }; base.AreaMasterLocationFormats = new string[] { "~/Areas/{2}/Views/{1}/{0}.vm", "~/Areas/{2}/Views/Shared/{0}.vm" }; base.ViewLocationFormats = new string[] { "~/Views/{1}/{0}.vm", "~/Views/Shared/{0}.vm" }; base.AreaViewLocationFormats = new string[] { "~/Areas/{2}/Views/{1}/{0}.vm", "~/Areas/{2}/Views/Shared/{0}.vm" }; base.PartialViewLocationFormats = base.ViewLocationFormats; base.AreaPartialViewLocationFormats = base.AreaViewLocationFormats; base.FileExtensions = new string[] { "vm" }; if (properties == null) properties = DEFAULT_PROPERTIES; ExtendedProperties props = new ExtendedProperties(); foreach (string key in properties.Keys) { props.AddProperty(key, properties[key]); } _engine = new VelocityEngine(); _engine.Init(props); } protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath) { Template viewTemplate = _engine.GetTemplate(viewPath); Template masterTemplate = _engine.GetTemplate(masterPath); NVelocityView view = new NVelocityView(controllerContext, viewTemplate, masterTemplate); return view; } protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath) { Template viewTemplate = _engine.GetTemplate(partialPath); NVelocityView view = new NVelocityView(controllerContext, viewTemplate, null); return view; } public Template GetTemplate(string viewPath) { viewPath = viewPath.TrimStart('~').TrimStart('/').Replace("cshtml", "vm"); if (string.IsNullOrEmpty(viewPath)) { return null; } return _engine.GetTemplate(AppDomain.CurrentDomain.SetupInformation.ApplicationBase.Replace("\\", "/") + viewPath); } }
2.NVelocityView
public class NVelocityView : IViewDataContainer, IView { private ControllerContext _controllerContext; private readonly Template _masterTemplate; private readonly Template _viewTemplate; private ViewDataDictionary _viewData; public Template ViewTemplate { get { return _viewTemplate; } } public Template MasterTemplate { get { return _masterTemplate; } } public ViewDataDictionary ViewData { get { if (_viewData == null) { return _controllerContext.Controller.ViewData; } return _viewData; } set { _viewData = value; } } public NVelocityView(ControllerContext controllerContext, string viewPath, string masterPath) : this(controllerContext, NVelocityViewEngine.Default.GetTemplate(viewPath), NVelocityViewEngine.Default.GetTemplate(masterPath)) { } public NVelocityView(ControllerContext controllerContext, Template viewTemplate, Template masterTemplate) { _controllerContext = controllerContext; _viewTemplate = viewTemplate; _masterTemplate = masterTemplate; } public void Render(ViewContext viewContext, TextWriter writer) { this.ViewData = viewContext.ViewData; bool hasLayout = _masterTemplate != null; VelocityContext context = CreateContext(viewContext); if (hasLayout) { StringWriter sw = new StringWriter(); _viewTemplate.Merge(context, sw); context.Put("childContent", sw.GetStringBuilder().ToString()); _masterTemplate.Merge(context, writer); } else { _viewTemplate.Merge(context, writer); } } private VelocityContext CreateContext(ViewContext context) { Hashtable entries = new Hashtable(StringComparer.InvariantCultureIgnoreCase); Hashtable listlabels = context.HttpContext.Items["listLabel"] as Hashtable ?? new Hashtable();
foreach (var label in listlabels.Keys) { entries.Add(label, listlabels[label]); } Hashtable contextLables = context.HttpContext.Items["contextLabel"] as Hashtable ?? new Hashtable(); foreach (var label in contextLables.Keys) { entries.Add(label, contextLables[label]); } Hashtable commonLabels = context.HttpContext.Items["commonLabel"] as Hashtable ?? new Hashtable(); foreach (var label in commonLabels.Keys) { entries.Add(label, commonLabels[label]); } entries["Site"] = context.HttpContext.Items["Site"]; entries["ViewBag"] = context.Controller.ViewBag; entries["viewdata"] = context.ViewData; entries["tempdata"] = context.TempData; entries["routedata"] = context.RouteData; entries["controller"] = context.Controller; entries["httpcontext"] = context.HttpContext; entries["viewbag"] = context.ViewData; return new VelocityContext(entries); } }
3.NVelocityTemplateEngine
public class NVelocityTemplateEngine : ITemplateEngines.ITemplateEngines { public string Name { get { return "NVelocity"; } } public string GetFileExtensionForLayout() { return "vm"; } public string GetFileExtensionForView() { return "vm"; } public IViewEngine GetViewEngine() { return NVelocityViewEngine.Default; } public IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath) { return new NVelocityView(controllerContext, viewPath, masterPath); } }
4.FrontViewResult
public class FrontViewResult : ViewResult { private IViewEngine viewEngine; public FrontViewResult(ControllerContext controllerContext, string fileExtension, string viewVirtualPath) : this(controllerContext, fileExtension, viewVirtualPath, "") { } public FrontViewResult(ControllerContext controllerContext, string fileExtension, string viewVirtualPath, string masterVirtualPath) { var templateEngine = new NVelocityTemplateEngine(); this.View = templateEngine.CreateView(controllerContext, viewVirtualPath, masterVirtualPath); this.viewEngine = templateEngine.GetViewEngine(); } public override void ExecuteResult(ControllerContext context) { #if Page_Trace Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); #endif base.ExecuteResult(context); #if Page_Trace stopwatch.Stop(); context.HttpContext.Response.Write(string.Format("ExecuteResult, {0}ms.</br>", stopwatch.ElapsedMilliseconds)); #endif } protected override ViewEngineResult FindView(ControllerContext context) { return new ViewEngineResult(View, viewEngine); } }
5。控制器调用
public class PageController : AbpController { [PageExecutionFilter(Order = 5)] [PageDataFilter(Order = 10)] public ActionResult Entry() { ViewResult viewResult = new FrontViewResult(ControllerContext, Path.GetExtension(Page_Context.Current.Template), "~/" + Page_Context.Current.Template); if (viewResult != null) { viewResult.ViewData = this.ViewData; viewResult.TempData = this.TempData; } return viewResult; } }
浙公网安备 33010602011771号