分享

asp.net mvc webform和razor的page基类区别

 浅浅苍蓝 2017-08-15
 

接触过asp.net mvc的都知道,在传统的webform的模式下,page页面的基类是这样声明的:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="ViewPage" %>

如果是partial view的话,则是这样声明的:

<%@ Control Language="C#" Inherits="ViewUserControl<dynamic>" %>

可以知道如果传统的view的话是继承于ViewPage这个类,如果是partialView的话则是继承于ViewUserControl这个类。

为了证明我们的分析是否正确,我们看一下asp.net mvc的源码,在源码中有一个WebFormView类,这个就是支持我们传统的web form的基类,我们来看一下它的RenderView是怎么实现的,顺便这里提一下,WebFormView继承于BuildManagerCompiledView,这个我们以后讨论。

protected override void RenderView(ViewContext viewContext, TextWriter writer, object instance) { ViewPage viewPage = instance as ViewPage; if (viewPage != null) { RenderViewPage(viewContext, viewPage); return; } ViewUserControl viewUserControl = instance as ViewUserControl; if (viewUserControl != null) { RenderViewUserControl(viewContext, viewUserControl); return; } throw new InvalidOperationException( String.Format( CultureInfo.CurrentCulture, MvcResources.WebFormViewEngine_WrongViewBase, ViewPath)); }

我们可以清楚的看到,先对object instance判断是否是ViewPage类型,如果为空则判断是否是ViewUserControl类型,如果两者都不是则抛出异常,由此我们可以得知,传统的webform主要由这两个基类组成。在传统的asp.net webform是怎么的情况,还需要大家自己去论证。

好了,我们对asp.net mvc webform进行了分析,以后如果要重写基类的话,只要根据具体的需要对ViewPage和ViewUserControl进行重写就行了。

那么自从asp.net mvc 3.0以后微软推出一个新的视图引擎razor以后,他的基类结构是否发生变化?

事实的确是这样的,当我们使用Razor引擎的时候,我们创建的.cshtml文件没有了之前类似webform的头部声明:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="ViewPage" %>

取而代之则是什么都没有,这一时让我们需要重写基类的童鞋们摸不着头脑,好了那让我们用同样的思路进行一下分析,razor的头部声明没有,不代表他不继承于基类,既然省略那么说明一个很直接的原因就是他们的view和partialview的头部声明应该是一样的,所以微软干脆就省去不写了。那为了论证我们的猜想是否正确,我们看一下源码。

同样在源码中有一个RazorView类,这个和WebFormView是对应着的,他同样也继承于BuildManagerCompiledView类,同理让我们来看一下他的RenderView方法是如何实现的。

protected override void RenderView(ViewContext viewContext, TextWriter writer, object instance) { if (writer == null) { throw new ArgumentNullException("writer"); } WebViewPage webViewPage = instance as WebViewPage; if (webViewPage == null) { throw new InvalidOperationException( String.Format( CultureInfo.CurrentCulture, MvcResources.CshtmlView_WrongViewBase, ViewPath)); } // An overriden master layout might have been specified when the ViewActionResult got returned. // We need to hold on to it so that we can set it on the inner page once it has executed. webViewPage.OverridenLayoutPath = LayoutPath; webViewPage.VirtualPath = ViewPath; webViewPage.ViewContext = viewContext; webViewPage.ViewData = viewContext.ViewData; webViewPage.InitHelpers(); if (VirtualPathFactory != null) { webViewPage.VirtualPathFactory = VirtualPathFactory; } if (DisplayModeProvider != null) { webViewPage.DisplayModeProvider = DisplayModeProvider; } WebPageRenderingBase startPage = null; if (RunViewStartPages) { startPage = StartPageLookup(webViewPage, RazorViewEngine.ViewStartFileName, ViewStartFileExtensions); } webViewPage.ExecutePageHierarchy(new WebPageContext(context: viewContext.HttpContext, page: null, model: null), writer, startPage); }

正如我们猜想的在RenderView方法中只看到一个WebViewPage的类,那么就说明Razor引擎的View和PartialView的基类进行了合并,其实我们可以通过扩展名也可以得知,因为razor的扩展名不管是view和partialview都是.cshtml,和之前webform的模式已经不同。

既然razor进行了合并,那么他们的头部声明肯定都是一样的,所以微软就省去了这个环节。

那么razor该如何重写基类呢,如果声明页面头部继承关系呢?

同样我们继承于WebViewPage基类,然后在自己的view或者partialview的头部进行如下声明:

@inherits CustomWebViewPage

或者

@inherits CustomWebViewPage<CustomModel>

这样就可以实现同的自定义实现了,不过这里需要提一点,由于WebViewPage是一个abstract类型的类,所以不能直接实例化,那么一点继承的话,里面必须需要实现一个Excute方法。如果你声明的CustomWebViewPage也是一个abstract类型,则不需要重写,调用默认的实现就可以,但是如果不是则要自己去实现自定义的excute方法。

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多