Asp.net Mvc自定义后端模板,重写视图引擎,自定义视图引擎

虽然有很多前端模板库,但是前端模板都是后期再渲染呈现,而后端模板是在服务端渲染之前执行替换操作,可以避免页面闪屏,自定义的后端的方式,也更适合后端开发人员。

对于Asp.net Mvc,  后端html修改,可以在视图引擎里修改html,MVC默认视图引擎为RazorViewEngine, RazorViewEngine继承自基类BuildManagerViewEngine, 它有两个重载的函数CreatePartialView和CreateView:

#region 程序集 System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// D:\development\WebMvc\SecurityDemo\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll
#endregion

namespace System.Web.Mvc
{
    //
    // 摘要:
    //     表示一个用于呈现使用 ASP.NET Razor 语法的网页的视图引擎。
    public class RazorViewEngine : BuildManagerViewEngine
    {
        //
        // 摘要:
        //     初始化 System.Web.Mvc.RazorViewEngine 类的新实例。
        public RazorViewEngine();
        //
        // 摘要:
        //     使用视图页激活器初始化 System.Web.Mvc.RazorViewEngine 类的新实例。
        //
        // 参数:
        //   viewPageActivator:
        //     视图页激活器。
        public RazorViewEngine(IViewPageActivator viewPageActivator);

        //
        // 摘要:
        //     使用指定的控制器上下文和分部路径创建分部视图。
        //
        // 参数:
        //   controllerContext:
        //     控制器上下文。
        //
        //   partialPath:
        //     分部视图的路径。
        //
        // 返回结果:
        //     分部视图。
        protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath);
        //
        // 摘要:
        //     使用指定的控制器上下文以及视图和母版视图的路径来创建视图。
        //
        // 参数:
        //   controllerContext:
        //     控制器上下文。
        //
        //   viewPath:
        //     视图的路径。
        //
        //   masterPath:
        //     母版视图的路径。
        //
        // 返回结果:
        //     视图。
        protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath);
    }
}

这两个函数返回对象类型都继承自IView接口,那我们分装一个类,只要继承自IView接口就可以,定义一个类RazorViewPlus(视图类)并继承自RazorView类(RazorView实际上也继承自IView接口,它是RazorViewEngine默认使用的类型,所以用它更好)。

RazorViewPlus.cs

using Microsoft.Ajax.Utilities;
using Microsoft.VisualBasic;
using RazorEnginePlus.Extend;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web.Mvc;
using System.Web.UI;

namespace RazorEnginePlus
{
    public class RazorViewPlus : RazorView
    {
     
        public RazorViewPlus(ControllerContext controllerContext, string viewPath, string layoutPath, bool runViewStartPages, IEnumerable viewStartFileExtensions) : base(controllerContext, viewPath, layoutPath, runViewStartPages, viewStartFileExtensions)
        {
        }

        public RazorViewPlus(ControllerContext controllerContext, string viewPath, string layoutPath, bool runViewStartPages, IEnumerable viewStartFileExtensions, IViewPageActivator viewPageActivator) : base(controllerContext, viewPath, layoutPath, runViewStartPages, viewStartFileExtensions, viewPageActivator)
        {
        }
    
        protected override void RenderView(ViewContext viewContext, TextWriter writer, object instance)
        {
            StringWriter stringWriter = new StringWriter();
            HtmlTextWriter tw = new HtmlTextWriter(stringWriter);
            base.RenderView(viewContext, tw, instance);
            string html = stringWriter.ToString();
        
            //模板替换
            Regex regx = new Regex("[\\s\\S]*?", RegexOptions.IgnoreCase);
            MatchCollection matchList = regx.Matches(html); //这里已捕获到了
            for (int i = 0; i < matchList.Count; i++) {
                var ls_tmpl = matchList[i].Value;
                if (!string.IsNullOrEmpty(ls_tmpl)) {
                    var ls_id = "";
                    Regex regxtmplid = new Regex("\\s+?id\\s*?=\\s*?\"\\s*?[\\S]+?\\s*?\"", RegexOptions.IgnoreCase);
                    MatchCollection matchTmplId = regxtmplid.Matches(ls_tmpl);
                    if (matchTmplId.Count > 0) {
                        ls_id = matchTmplId[0].Value;
                        if (!string.IsNullOrEmpty(ls_id)) {
                            ls_id = new Regex("[\\s\\S]*?\\s+?id\\s*?=\\s*?\"", RegexOptions.IgnoreCase).Replace(ls_id, "");
                            ls_id = ls_id.Replace(" ", "").Replace("\"", "");
                        }

                        //找到模板指定的区域
                        if (!string.IsNullOrEmpty(ls_id)) {
                            Regex regxPartial = new Regex("[\\s\\S]*?", RegexOptions.IgnoreCase);
                            MatchCollection matchScriptTmpl = regxPartial.Matches(html);
                            if (matchScriptTmpl.Count <= 0) {
                                regxPartial = new Regex("[\\s\\S]*?", RegexOptions.IgnoreCase);
                                matchScriptTmpl = regxPartial.Matches(html);
                            }
                            if (matchScriptTmpl.Count > 0) {
                                var ls_partial = matchScriptTmpl[0].Value;
                                Regex regxPartialRp1 = new Regex("", RegexOptions.IgnoreCase);
                                Regex regxPartialRp2 = new Regex("", RegexOptions.IgnoreCase);
                                ls_partial = regxPartialRp1.Replace(ls_partial, "");
                                ls_partial = regxPartialRp2.Replace(ls_partial, "");


                                Regex regxTag = new Regex("[\\s\\S]*?", RegexOptions.IgnoreCase);
                                html = regxTag.Replace(html, ls_partial);

                            }
                        }
                    }
                }
            }


            //移除模板代码
            Regex regTmplRemove1 = new Regex("[\\s\\S]*?", RegexOptions.IgnoreCase);
            html = regTmplRemove1.Replace(html, "");
            Regex regTmplRemove2 = new Regex("[\\s\\S]*?", RegexOptions.IgnoreCase);
            html = regTmplRemove2.Replace(html, "");

            //输出到页面
            writer.Write(html);
        }
    }
}

视图类RazorViewPlus最终还是要用在视图引擎里,我们自定义一个EngineCore类并继承自RazorViewEngine类,重写CreateView方法,CreatePartialView是创建分部视图,一般没必要改,修改后的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;

namespace RazorEnginePlus
{
    public class EngineCore : RazorViewEngine
    {
        protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
        {
            return base.CreateView(controllerContext, partialPath, string.Empty);
        }
        /// 
        /// 根据指定路径返回一个实现了 IView 接口的对象
        /// 
        protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
        {
            //var physicalPath = controllerContext.HttpContext.Server.MapPath(viewPath);
            //return new BaseView(physicalPath);
            return new RazorViewPlus(controllerContext, viewPath, masterPath, true, base.FileExtensions, base.ViewPageActivator);
            //return base.CreateView(controllerContext, viewPath, masterPath);
        }
    }
}

最后一步,使用我们重写的视图引擎,找到你的MVC项目更目录下的Global.asax文件,在Application_Start函数里面的最前面添加下面代码:

//移除默认视图引擎
            var orgRazorEngine = ViewEngines.Engines.SingleOrDefault(ve => ve is RazorViewEngine);
            if (orgRazorEngine != null)
            {
                ViewEngines.Engines.Remove(orgRazorEngine);
            }
            //也可以先清空引擎集合
            //ViewEngines.Engines.Clear();
            //添加自定义的视图引擎到引擎集合中
            ViewEngines.Engines.Add(new EngineCore());

html页面代码:

 


       

最终输出到页面的html:

aaaa

你可能感兴趣的:(C#.Net开发,Asp.net,Mvc)