aspp.netMVC自定义视图引擎
采用xslt作为ASP.NETmvc的视图引擎有几个好处
1彻底的实现视图和逻辑的分离(采用ASPX你无法控制别人在ASPX里面是否写逻辑代码)
2彻底的实现强类型的MODEL(自己定义视图引擎只是先一种数据方式)
3借助MODEL序列化为XML,进行XSLT转换,实现页面个性定制
4xslt的基本语法可以完成一部分JS的工作,而这正是页面基本控件布局和展示所需要的
5xslt的自定义函数可以进行有效的扩展
以前的流不是很了解折腾了一周总算是明白了
一个典型的目录如下
文件的结构也是比较清晰的
实现仅需要实现一个借口和集成一个类
代码如下
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; 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) { if (!string.IsNullOrEmpty(masterPath)) throw new Exception("此处不能指定试图的名称"); string actionname = controllerContext.RouteData.Values["action"].ToString(); string controllername = controllerContext.RouteData.Values["controller"].ToString(); masterPath = string.Format("/Views/Shared/{0}/{1}.xslt",controllername ,actionname); return new xsltView(viewPath, masterPath); } } }
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 fs = new MemoryStream(); XmlReaderSettings redset = new XmlReaderSettings(); redset.ProhibitDtd = true; XsltArgumentList myarg = new XsltArgumentList(); myarg.AddExtensionObject("myfn:utils", new MyXslExtension()); System.Xml.Serialization.XmlSerializer xmlser = new System.Xml.Serialization.XmlSerializer(viewContext.ViewData.Model.GetType()); xmlser.Serialize(fs, viewContext.ViewData.Model); fs.Position = 0; if (string.IsNullOrEmpty(System.Web.HttpContext.Current.Request.Params["debug"])) { fs.Flush(); MemoryStream stream = new MemoryStream(); XmlReader viewxmlreader = XmlReader.Create(fs, redset); try { transform.Transform(viewxmlreader, myarg, stream); viewxmlreader.Close(); fs.Close(); fs.Dispose(); } 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()); stream.Close(); reader.Close(); reader.Dispose(); } else { StreamReader reader2 = new StreamReader(fs, System.Text.Encoding.UTF8); writer.Write(reader2.ReadToEnd()); fs.Close(); fs.Dispose(); reader2.Close(); reader2.Dispose(); } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace myview { class MyXslExtension { public string FormatName(string firstName, string name) { return name + ", " + firstName; } public string GetLink() { return "http://www.cnblogs.com/qqloving/"; } } }
<?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" xmlns:utils="myfn:utils" exclude-result-prefixes="msxsl"> <xsl:output method="html" encoding="utf-8" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" omit-xml-declaration="yes" /> <xsl:template match="/"> <div style=" border-style:solid; border-width:1px;"> <table class="style1"> <xsl:for-each select="*"> <tr> <td> 0 <xsl:value-of select="@Name"/> <!--一 @表示匹配当前的属性 --> </td> <td>1 <xsl:value-of select="."/> <!--一 .表示匹配当前的值 --> </td> <td>2 <xsl:value-of select="node()"/> <!--一 node()表示获取当前的值 --> </td> <td> 3 <xsl:value-of select="name()"/> <!--一 name()表示获取当前节点的名称 --> </td> <td> 4 <xsl:value-of select="utils:GetLink()"/> <!--一 name()表示获取当前节点的名称 --> </td> </tr> </xsl:for-each> </table> </div> </xsl:template> </xsl:stylesheet>
using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Security; using System.Xml.Serialization; namespace MvcApplication5.Models { [Serializable] public class ChangePasswordModel { public string OldPassword { get; set; } public string NewPassword { get; set; } public string ConfirmPassword { get; set; } } }public ActionResult Index() { ChangePasswordModel MYMODEL = new ChangePasswordModel(); MYMODEL.ConfirmPassword = "123"; MYMODEL.NewPassword = "456"; MYMODEL.OldPassword = "345"; return View(MYMODEL); }
test