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

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

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

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

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

可以知道如果传统的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));
        }
View Code

我们可以清楚的看到,先对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" %>
View Code

取而代之则是什么都没有,这一时让我们需要重写基类的童鞋们摸不着头脑,好了那让我们用同样的思路进行一下分析,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);
        }
View Code

正如我们猜想的在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方法。

 

posted @ 2017-08-15 11:54  浅苍蓝  阅读(2086)  评论(1编辑  收藏  举报