最近由于工作的关系,项目的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,真是一句多的