最近由于工作的关系,项目的ASP.NETmvc视图引擎是xslt的,公司的当然是异常的强大和健壮,怎奈我XSLT不太熟悉,至少没有熟悉到想html一样,所以第私底下连自己练习 先做个简单的视图引擎,至于为什么要用XSLT,自然是xslt+xml默认的解析也是异常的强大和健壮,还可以为项目奠定组件化,分布式,多线程并发等基础
自定义ASP.NETMVC视图引擎,只需要实现接口IView和继承VirtualPathProviderViewEngine
在重写VirtualPathProviderViewEngine 时 主要目的是规定请求和视图和模板视图的文件路径和类型
例如
===
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web.Mvc; using System.Web.Routing; namespace myview { public class MyViewEngine:VirtualPathProviderViewEngine { private string _AppPath = string.Empty; //#region 属性 Properties //public static FileSystemTemplateLoader Loader { get; private set; } //public static StringTemplateGroup Group { get; private set; } //#endregion public MyViewEngine() { ViewLocationFormats = new[]{ "/Views/{1}/{0}.aspx" }; } protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath) { return this.CreateView(controllerContext, partialPath, String.Empty); } protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath) { //还是在这个函数里根据规则匹配模板名称 // string masterPath =GetPath(controllerContext, MasterLocationFormats, "MasterLocationFormats", //masterName, controllerName, _cacheKeyPrefix_Master, useCache, out masterLocationsSearched); //base.FindView(controllerContext, viewPath, masterPath, true); //string controllername = controllerContext.RouteData.Values["controller"].ToString(); ///Views/Shared/{0}.xslt if (!string.IsNullOrEmpty(masterPath)) throw new Exception("此处不能指定试图的名称"); string actionname = controllerContext.RouteData.Values["action"].ToString(); masterPath = string.Format("/Views/Shared/{0}.xslt", actionname); return new xsltView(viewPath, masterPath); } } }
==
ViewLocationFormats 中主要是 视图的文件路径,因为采用XML(内存生成)+xslt(负责解析转换)因此 请求的类型不变采用ASP.NETmvc默认的
"/Views/{1}/{0}.aspx" 就行,把xslt作为模板就行了
坦白的说,对ASP.NETmvc 机制不是很了解,开始一直在纠结 IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
中masterPath的路径怎么一直为空,是配置有问题,还是逻辑有问题,纠结了一上午,最终下载了ASP.NETmvc源码查看一下,这这里还有其他函数用于寻找模板
GetPath(controllerContext, MasterLocationFormats, "MasterLocationFormats",
//masterName, controllerName, _cacheKeyPrefix_Master, useCache, out masterLocationsSearched)
所以干脆自己找模板,也变成强制性的路径 masterPath = string.Format("/Views/Shared/{0}.xslt", actionname);
这样 就行了
模板引擎还需要实现自己的IView,对模板进行解析
===
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web.Mvc; using System.Xml; using System.IO; using System.Xml.Xsl; using System.Web; namespace myview { public class xsltView:IView { // 视图文件的物理路径 private string _viewPhysicalPath; // 视图文件的物理路径 private string _xsltPhysicalPath; public xsltView(string viewPhysicalPath, string masterPhysicalPath) { _viewPhysicalPath = viewPhysicalPath; _xsltPhysicalPath = masterPhysicalPath; } void IView.Render(ViewContext viewContext, System.IO.TextWriter writer) { XslCompiledTransform transform = new XslCompiledTransform(); //xslt文件的路径 string XsltFileDir =System.Web.HttpContext.Current.Server.MapPath(_xsltPhysicalPath); try { transform.Load(XsltFileDir); } catch (Exception ex) { throw ex; } MemoryStream stream = new MemoryStream(); if (string.IsNullOrEmpty(System.Web.HttpContext.Current.Request.Params["debug"])) { try { transform.Transform(XmlReader.Create(new StringReader(viewContext.ViewData["xmlcontent"].ToString())), null, stream); } catch (Exception ex) { throw ex; } // transform.Transform(Server.MapPath("a.xml"), null, stream); stream.Position = 0; StreamReader reader = new StreamReader(stream, System.Text.Encoding.UTF8); // 呈现出解析后的内容 writer.Write(reader.ReadToEnd()); } else { writer.Write(viewContext.ViewData["xmlcontent"].ToString()); } } } }
===
这里主要是调用xml的方法进行转换,然后直接输出
最后还需要一件事情要做
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; using myview; namespace MvcApplication5 { // Note: For instructions on enabling IIS6 or IIS7 classic mode, // visit http://go.microsoft.com/?LinkId=9394801 public class MvcApplication : System.Web.HttpApplication { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults ); routes.MapRoute( "Default2", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults ); } protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RegisterRoutes(RouteTable.Routes); ViewEngines.Engines.Clear(); ViewEngines.Engines.Add(new myview.MyViewEngine()); } } }
==================================
在这里初始化视图引擎就行了
使用就更简单了
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace MvcApplication5.Controllers { public class HomeController : Controller { public ActionResult Index() { ViewData["Message"] = "Welcome to ASP.NET MVC!"; ViewData["xmlcontent"] = @"<result> <h1> aaa </h1> </result>"; return View(); } public ActionResult About() { return View(); } } }
===
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" > <xsl:output method="html" indent="yes" omit-xml-declaration="yes"/> <xsl:template match="/result"> <xsl:for-each select="h1"> <xsl:value-of select="."/> </xsl:for-each> </xsl:template> </xsl:stylesheet>
接下来就得自己给自己开小灶研究一下xslt 和具体的ASP.NETmvc框架同时也对比一下JAVA的MVC框架,以前asp.net没有开源 总是被人鄙视不懂底层,现在这段历史终于过去了,因为XML要在内存中生成,可以很好的练习以前linq to xml,真是一句多的