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;

        }
    }

 

 

posted @ 2016-12-17 21:17  cola可乐  阅读(145)  评论(0)    收藏  举报