为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

时间: 2024-10-06 12:08:50

为ASP.NET MVC 2.0添加Razor模板引擎 (on .NET4)的相关文章

返璞归真 asp.net mvc (9) - asp.net mvc 3.0 新特性之 View(Razor)

原文:返璞归真 asp.net mvc (9) - asp.net mvc 3.0 新特性之 View(Razor) [索引页][源码下载] 返璞归真 asp.net mvc (9) - asp.net mvc 3.0 新特性之 View(Razor) 作者:webabcd 介绍asp.net mvc 之 asp.net mvc 3.0 新特性之 View(Razor): Razor 的语法 Razor 与 Model Razor 与布局 示例1.Razor 概述RazorDemoControl

走进ASP.NET MVC 3.0中的Razor模板引擎

随着MVC3.0RTM版本的发布,最近将公司的项目从MVC2.0升级到MVC3.0.同时打算在MVC3中全面使用Razor模板引擎.现将Razor学习拿出来和大家分享,如果存在不足的地方欢迎您指出. 其实在使用<%= %>在html中调用C#代码时,内心总在埋怨.这个写法非常麻烦.麻烦在哪呢?其实就是闭合.比如: Asp.net: <script src="<%=Url.Content("~/Scripts/jquery-1.4.4.min.js")%

asp.net mvc 4.0的部署

只要服务器支持 .NET 4,那么就能够在上面生成和部署 ASP.NET MVC 3 应用程序. 方法一(正常方法):安装 ASP.NET MVC 3 到机器上,程序集会安装到 GAC 中,机器上所有的 Web 项目都可以引用/使用 GAC 中的这些程序集 方法二:把 ASP.NET MVC 3 的程序集复制到 Web 项目的 /bin 文件夹中,然后让此 Web 项目引用/使用程序集 方法二的做法在另一篇blog中(http://drew-prog.blogspot.com/2011/01/h

返璞归真 asp.net mvc (7) - asp.net mvc 3.0 新特性之 Controller

原文:返璞归真 asp.net mvc (7) - asp.net mvc 3.0 新特性之 Controller [索引页][源码下载] 返璞归真 asp.net mvc (7) - asp.net mvc 3.0 新特性之 Controller 作者:webabcd 介绍asp.net mvc 之 asp.net mvc 3.0 新特性之 Controller: Global Action Filter 可以在标记为 ChildActionOnly 的 Action 上使用 OutputCa

鲜为人知的ASP.NET MVC 2.0框架高效之谜

要想建立开发环境,你需要安装Visual Studio 2008/2010 Beta 2,以及SQL Express 2005(可免费从MSDN下载)和MVC 2.0框架.我把本文中的示例Web应用命名为"Employee Master Information". 使用该应用程序,你可以输入新员工数据,编辑现有员工数据,可以查看特定员工数据,和从数据库中给删除任意员工信息.该应用程序还使用了ASP.NET的Membership Provider来创建新用户和认证已有用户,客户端验证通过

返璞归真 asp.net mvc (8) - asp.net mvc 3.0 新特性之 Model

原文:返璞归真 asp.net mvc (8) - asp.net mvc 3.0 新特性之 Model [索引页][源码下载] 返璞归真 asp.net mvc (8) - asp.net mvc 3.0 新特性之 Model 作者:webabcd 介绍asp.net mvc 之 asp.net mvc 3.0 新特性之 Model: 通过 Data Annotations 与 jQuery 的结合实现服务端和客户端的双重验证 双重验证中,使客户端实现远程的异步验证 自定义 Data Anno

返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 Web API

原文:返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 Web API [索引页][源码下载] 返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 Web API 作者:webabcd 介绍asp.net mvc 之 asp.net mvc 4.0 新特性之 Web API 开发一个 CRUD 的 Demo,服务端用 Web API,并使其支持 jsonp 协议,客户端用 jQuery 示例1.自定义一个 JsonMe

一起谈.NET技术,鲜为人知的ASP.NET MVC 2.0框架高效之谜

要想建立开发环境,你需要安装Visual Studio 2008/2010 Beta 2,以及SQL Express 2005(可免费从MSDN下载)和MVC 2.0框架.我把本文中的示例Web应用命名为"Employee Master Information". 使用该应用程序,你可以输入新员工数据,编辑现有员工数据,可以查看特定员工数据,和从数据库中给删除任意员工信息.该应用程序还使用了ASP.NET的Membership Provider来创建新用户和认证已有用户,客户端验证通过

ASP.NET MVC 1.0浅析

为什么要用ASP.NET MVC 1.0?当我刚知道1.0发布的时候,经常这样问. 最近正在考虑是否在我们的企业级应用中使用ASP.NET MVC 1.0框架,因此会一直找使用它的理由,希 望大家在关注技术的同时,结合企业应用谈谈自己的看法. 1.MVC的组成 Models:访问数据库,装载数据.处理业务逻辑.在项目中体现为数据实体类加业务代理类. Views:显示数据,用户界面.在项目中体现为aspx页面,偶尔可以加上code-behind. Controller:按路由规则将请求的数据传送给