为ASP.NET MVC 2.0添加Razor模板引擎 (on .NET4)

根据ScottGu的博客记述( http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx),在未来不久将会发布一个ASP.NET MVC 3.0的Preview版本,在这个版本中可以使用多个内置的模板引擎,以它发布出来的截图来看,其中包括NHaml,Spark以及微软刚刚发布的ASP.NET Web Pages(Razor)。 ASP.NET Web Pages包含在Web Matrix中,提供了一种新的模板模式,其扩展名为 .vbhtml/.cshtml,可以使用类似以下语法来做视图显示: @{ var i = 11; } @(i+1) < br > @if (i%2==1){ < p >true </ p > }else{ < p >false </ p > } 输出结果为: 12 < br > < p >true </ p >

在不久之后Ms还会对此提供Visual Studio 高亮及智能感知支持。

这种模板如此简捷,如果能用在现有的ASP.NET MVC 2.0上做为一个模板引擎是不错的。

首先我们要安装ASP.NET Web Pages,下载地址:http://bbs.eice.com.cn/showtopic-409.aspx ,当然直接安装WebMatrix也是可以。

安装之后在IIS中就会添加对cshtml及vbhtml的支持。

安装后程序集文件会被复制到Program Files\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\Assemblies目录下。

其中包括

Microsoft.Data.dll Microsoft.Web.Infrastructure.dll Microsoft.Webpages.Compilation.dll Microsoft.Webpages.Configuration.dll Microsoft.Webpages.dll Microsoft.Webpages.Helpers.dll Microsoft.Webpages.Helpers.Toolkit.dll

下面我们就动手对ASP.NET MVC程序添加一个Razor的模板引擎:

首先建立一个ASP.NET MVC的项目,然后对其中的Web.Config的system.web/compilation/assemblies节点上添加内容:

< add assembly= "Microsoft.WebPages.Compilation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> < add assembly= "Microsoft.Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> < add assembly= "Microsoft.WebPages.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> < add assembly= "Microsoft.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />


并对system.web/compilation/buildProviders添加内容:

< add extension= ".cshtml" type= "Microsoft.WebPages.Compilation.InlinePageBuildProvider" />

 

并引用相应的

Microsoft.Data.dll Microsoft.Webpages.dll Microsoft.Webpages.Helpers.dll Microsoft.Webpages.Compilation.dll

几个文件

准备工作做好了,下面就来实现相应的模板引擎,我们先来实现一个IView对象:

public class WebPageView : IView { public WebPageView( string viewPath) : this(viewPath, null) { } public WebPageView( string viewPath, string masterPath) { if ( string.IsNullOrEmpty(viewPath)) { throw new ArgumentException(" viewPath can't null", " viewPath"); } this.ViewPath = viewPath; this.MasterPath = masterPath ?? string.Empty; } public virtual void Render(ViewContext viewContext, TextWriter writer) { if (viewContext == null) { throw new ArgumentNullException(" viewContext"); } WebPage page = WebPage.CreateInstanceFromVirtualPath( this.ViewPath); //load cshtml file if (page == null) { throw new InvalidOperationException(" cshtml file not exists"); } else { this.RenderViewPage(viewContext, page); } } private void RenderViewPage(ViewContext context, WebPage page) { if (! string.IsNullOrEmpty( this.MasterPath)) { page.LayoutPage = this.MasterPath; } page.VirtualPath = this.ViewPath; page.ExecutePageHierarchy(CreatePageContext(context) , context.HttpContext.Response.Output, null); //execute cshtml file } internal static WebPageContext CreatePageContext(ViewContext content) { var pc = new WebPageContext(); var t = pc.GetType(); t.InvokeMember(" HttpContext", BindingFlags.SetProperty | BindingFlags.NonPublic | BindingFlags.Instance , null, pc, new[] { content.HttpContext }); t.InvokeMember(" ViewContext", BindingFlags.SetProperty | BindingFlags.NonPublic | BindingFlags.Instance , null, pc, new[] { content }); return pc; } /// <summary>Gets or sets the master path.</summary> /// <returns>The master path.</returns> public string MasterPath { get; private set; } /// <summary>Gets or sets the view path.</summary> /// <returns>The view path.</returns> public string ViewPath { get; private set; } }

 

然后我们再来实现一个IViewEngine对象:

/// <summary> /// WebPage View Engine /// </summary> class WebPageEngine : VirtualPathProviderViewEngine { public WebPageEngine() { // how to find the template path base.MasterLocationFormats = new string[] { " ~/Views/{1}/{0}.cshtml", " ~/Views/Shared/{0}.cshtml" }; base.AreaMasterLocationFormats = new string[] { " ~/Areas/{2}/Views/{1}/{0}.cshtml", " ~/Areas/{2}/Views/Shared/{0}.cshtml" }; base.ViewLocationFormats = new string[] { " ~/Views/{1}/{0}.cshtml", " ~/Views/Shared/{0}.cshtml" }; base.AreaViewLocationFormats = new string[] { " ~/Areas/{2}/Views/{1}/{0}.cshtml", " ~/Areas/{2}/Views/Shared/{0}.cshtml" }; base.PartialViewLocationFormats = base.ViewLocationFormats; base.AreaPartialViewLocationFormats = base.AreaViewLocationFormats; } protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath) { return new WebPageView(partialPath, null); } protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath) { return new WebPageView(viewPath, masterPath); } }

 

这样我们就实现了Razor的模板引擎了,我们只要在Global.asax中将模板引擎添加进去:

protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RegisterRoutes(RouteTable.Routes); ViewEngines.Engines.Clear(); ViewEngines.Engines.Add( new WebPageEngine()); }

 

并且将Global的基类改为WebPageHttpApplication:

public class MvcApplication : WebPageHttpApplication { //... }

这样整个程序就可以工作了

我们在Views/Home下添加一个Index.cshtml:

@Html.ActionLink(" Home"," index"," User") <br> @ViewData[" Message"]

 

这样在我们访问/Home/Index的时候就可以得到ASP.NET MVC默认工程的HomeController.Index所生成的页面了:

<a href="/User">Home</a>
<br>
欢迎使用 ASP.NET MVC!

 

可见在这个模板引擎中,先天对ASP.NET MVC有良好的支持,本身已经集成了Helper、ViewData等诸多ASP.NET MVC的特性。

让我们期待ASP.NET MVC 3.0及Razor对VS的支持吧

8189E6B8-FBE4-4F01-8F9F-5687C0EA9F59

你可能感兴趣的:(mvc,net,asp,引擎,Razor)