目录
  • 一、介绍
  • 二、mvc生命周期详述
    • view的初始化和渲染呈现
  • 三、结束

    一、介绍

    我们做开发的,尤其是做微软技术栈的,有一个方向是跳不过去的,那就是mvc开发。我相信大家,做asp.net mvc 开发有的有很长时间,当然,也有刚进入这个行业的。无论如何,如果有人问你,你知道asp.net mvc的生命周期吗?你知道它的来世今生吗?你知道它和 asp.net webform 有什么区别吗?估计,这些问题,有很多人会答不上来,或者说不清楚。今天,我就把我的理解写出来,也是对我自己学习的一次回顾和总结吧。当然,由于本人能力有限,在写的过程中也可能会有一些错误,希望大家多多包涵,当然,更希望大家能不灵赐教,我们共同进步。

    在开始之前,我们先来说说,asp.net web form 和 asp.net mvc 有什么区别,这里说的区别,当然是本质区别,不是适用语法那个层次的。其实,说起来,asp.net web form 和 asp.net mvc 它们两个没有本质区别,使用的都是asp.net web form 的管道处理模型,asp.net mvc 也是通过扩展 ihttpmodule 和 ihttphandler 来实现的,都是基于 asp.net 的 httpapplication 的管道处理模型扩展的,在这个层面来说,它们是一样的。当然,大家不要抬杠,我说的本质区别都是在这个方面,不同意的勿喷。

    有人会问,asp.net mvc  和 asp.net webapi 它们会有什么不同吗?好像 webapi 能做的,webmvc都可以完成,第一眼看上去,好像是这样,但是它们有着本质的不同。webapi 的处理管道是重新写过的,不是基于 httpapplication 管道扩展的。asp.net web api 类似专人做专事,它的管道处理模型更高效,并且有了 restfull 的概念。当然,大家如何向了解更细的内容,就需要看源码了。或再说回来,到了 net core 时代,二者又融合管道了。

    二、mvc生命周期详述

    1、我们既然要说 asp.net mvc的生命周期,为了给大家一个整体印象,俗话说,文不如图,我就贴一张图,按着箭头走,相信大家也会不能理解。

    2、上图很简单,大家按着箭头走,也能理解的差不多。以下是按着我的理解,划分了4个模块。

    (1)、路由模块

    routebase 是对路由规则的抽象,也就是说,一个 routebase 对象,也就代表了一个条 路由规则。在 asp.net mvc 中,有一个唯一的子类实现就是 route ,它同样也是路由规则的代表。我们有了路由规则,一定会把这个规则存放在一个地方,这个地方保存了很多路由规则,这个地方就是 routecollection,中文叫“路由集合”,因为这个集合里面包含的就是 routebase 对象。

    routecollection 就是路由集合,用于保存路由规则对象,它的定义形式:

    [typeforwardedfrom("system.web.routing, version=3.5.0.0, culture=neutral, publickeytoken=31bf3856ad364e35")]
          public class routecollection : collection<routebase>
          {
              private class readlockdisposable : idisposable
              {
                  private readerwriterlockslim _rwlock;
    
                  public readlockdisposable(readerwriterlockslim rwlock)
                  {
                      this._rwlock = rwlock;
                  }
    
                  void idisposable.dispose()
                  {
                      this._rwlock.exitreadlock();
                  }
              }
                ......
    
    

    routetable 就是路由表,其实它和 routecollection 是一样的。       

    public class routetable
        {
            private static routecollection _instance = new routecollection();
    
            public static routecollection routes
            {
                get
                {
                    return routetable._instance;
                }
            }
        }
    
    

    在asp.net mvc处理管线中的第一站就是路由模块。当请求到达路由模块后,asp.net mvc 框架就会根据 routetable 中配置的路由模板来匹配当前请求以获得对应的 controller 和 action 信息。具体的匹配过程就是有urlroutingmodule(system.web.routing.urlroutingmodule)来实现的。如果遇到一个匹配的规则,就会立刻跳出下面的配置。也就是说,配置过程是有顺序的,如果有一个匹配,后面就算有匹配的也不会执行的。

    namespace system.web.routing
    {
        [typeforwardedfrom("system.web.routing, version=3.5.0.0, culture=neutral, publickeytoken=31bf3856ad364e35")]
        public class urlroutingmodule : ihttpmodule
        {
            private static readonly object _contextkey = new object();
    
            private static readonly object _requestdatakey = new object();
    
            private routecollection _routecollection;
    
            public routecollection routecollection
            {
                get
                {
                    if (this._routecollection == null)
                    {
                        this._routecollection = routetable.routes;
                    }
                    return this._routecollection;
                }
                set
                {
                    this._routecollection = value;
                }
            }
    
            protected virtual void dispose()
            {
            }
    
            protected virtual void init(httpapplication application)
            {
                if (application.context.items[urlroutingmodule._contextkey] != null)
                {
                    return;
                }
                application.context.items[urlroutingmodule._contextkey] = urlroutingmodule._contextkey;
                application.postresolverequestcache += new eventhandler(this.onapplicationpostresolverequestcache);
            }
    
            private void onapplicationpostresolverequestcache(object sender, eventargs e)
            {
                httpapplication httpapplication = (httpapplication)sender;
                httpcontextbase context = new httpcontextwrapper(httpapplication.context);
                this.postresolverequestcache(context);
            }
    
            [obsolete("this method is obsolete. override the init method to use the postmaprequesthandler event.")]
            public virtual void postmaprequesthandler(httpcontextbase context)
            {
            }
    
            public virtual void postresolverequestcache(httpcontextbase context)
            {
                routedata routedata = this.routecollection.getroutedata(context); 第一步匹配路由规则
                if (routedata == null)
                {
                    return;
                }
                iroutehandler routehandler = routedata.routehandler; 第二步:如有匹配,就找到routehandler对象,该类型的实例是:mvcroutehandler。
                if (routehandler == null)
                {
                    throw new invalidoperationexception(string.format(cultureinfo.currentculture, sr.getstring("urlroutingmodule_noroutehandler"), new object[0]));
                }
                if (routehandler is stoproutinghandler)
                {
                    return;
                }
                requestcontext requestcontext = new requestcontext(context, routedata);
                context.request.requestcontext = requestcontext;
                ihttphandler httphandler = routehandler.gethttphandler(requestcontext);第三步,根据 routehandler 对象,找到最终处理请求的 ihttphandler 的对象,该类型是 mvchandler
                if (httphandler == null)
                {
                    throw new invalidoperationexception(string.format(cultureinfo.currentuiculture, sr.getstring("urlroutingmodule_nohttphandler"), new object[]
                    {
                        routehandler.gettype()
                    }));
                }
                if (!(httphandler is urlauthfailurehandler))
                {
                    context.remaphandler(httphandler);第四步,有找到的 ihttphandler 处理请求。
                    return;
                }
                if (formsauthenticationmodule.formsauthrequired)
                {
                    urlauthorizationmodule.reporturlauthorizationfailure(httpcontext.current, this);
                    return;
                }
                throw new httpexception(401, sr.getstring("assess_denied_description3"));
            }
    
            void ihttpmodule.dispose()
            {
                this.dispose();
            }
    
            void ihttpmodule.init(httpapplication application)
            {
                this.init(application);
            }
        }
    }
    
    

    (2)、controller 创建模块

    经过了路由模块,生成了 routedata 路由数据,它包含了根据路由规则匹配的 controller 和 action。有了路由数据,需要有处理器来处理请求,这个任务就交给了 routedata 的 routehandler 属性,它的类型是 iroutehandler,它的值就是mvcroutehandler,mvcroutehandler 调用 gethttphandler 获取处理请求的 ihttphandler 对象,在 mvc 框架中就是 mvchandler,详细代码如下:

    namespace system.web.mvc
    {
    /// <summary>selects the controller that will handle an http request.</summary>
    public class mvchandler : ihttpasynchandler, ihttphandler, irequiressessionstate
    {
    private struct processrequeststate
    {
    internal iasynccontroller asynccontroller;
    internal icontrollerfactory factory;
    internal requestcontext requestcontext;
    internal void releasecontroller()
    {
    this.factory.releasecontroller(this.asynccontroller);
    }
    }
    [compilergenerated]
    [serializable]
    private sealed class <>c
    {
    public static readonly mvchandler.<>c <>9 = new mvchandler.<>c();
    public static begininvokedelegate<mvchandler.processrequeststate> <>9__20_0;
    public static endinvokevoiddelegate<mvchandler.processrequeststate> <>9__20_1;
    public static func<keyvaluepair<string, object>, bool> <>9__26_0;
    internal iasyncresult <beginprocessrequest>b__20_0(asynccallback asynccallback, object asyncstate, mvchandler.processrequeststate innerstate)
    {
    iasyncresult result;
    try
    {
    result = innerstate.asynccontroller.beginexecute(innerstate.requestcontext, asynccallback, asyncstate);
    }
    catch
    {
    innerstate.releasecontroller();
    throw;
    }
    return result;
    }
    internal void <beginprocessrequest>b__20_1(iasyncresult asyncresult, mvchandler.processrequeststate innerstate)
    {
    try
    {
    innerstate.asynccontroller.endexecute(asyncresult);
    }
    finally
    {
    innerstate.releasecontroller();
    }
    }
    internal bool <removeoptionalroutingparameters>b__26_0(keyvaluepair<string, object> entry)
    {
    return entry.value == urlparameter.optional;
    }
    }
    private static readonly object _processrequesttag = new object();
    internal static readonly string mvcversion = mvchandler.getmvcversionstring();
    /// <summary>contains the header name of the asp.net mvc version.</summary>
    public static readonly string mvcversionheadername = "x-aspnetmvc-version";
    private controllerbuilder _controllerbuilder;
    internal controllerbuilder controllerbuilder
    {
    get
    {
    if (this._controllerbuilder == null)
    {
    this._controllerbuilder = controllerbuilder.current;
    }
    return this._controllerbuilder;
    }
    set
    {
    this._controllerbuilder = value;
    }
    }
    /// <summary>gets or sets a value that indicates whether the mvc response header is disabled.</summary>
    /// <returns>true if the mvc response header is disabled; otherwise, false.</returns>
    public static bool disablemvcresponseheader
    {
    get;
    set;
    }
    /// <summary>gets a value that indicates whether another request can use the <see cref="t:system.web.ihttphandler" /> instance.</summary>
    /// <returns>true if the <see cref="t:system.web.ihttphandler" /> instance is reusable; otherwise, false.</returns>
    protected virtual bool isreusable
    {
    get
    {
    return false;
    }
    }
    /// <summary>gets the request context.</summary>
    /// <returns>the request context.</returns>
    public requestcontext requestcontext
    {
    get;
    private set;
    }
    /// <summary>gets a value that indicates whether another request can use the <see cref="t:system.web.ihttphandler" /> instance.</summary>
    /// <returns>true if the <see cref="t:system.web.ihttphandler" /> instance is reusable; otherwise, false.</returns>
    bool ihttphandler.isreusable
    {
    get
    {
    return this.isreusable;
    }
    }
    /// <summary>initializes a new instance of the <see cref="t:system.web.mvc.mvchandler" /> class.</summary>
    /// <param name="requestcontext">the request context.</param>
    /// <exception cref="t:system.argumentnullexception">the <paramref name="requestcontext" /> parameter is null.</exception>
    public mvchandler(requestcontext requestcontext)
    {
    if (requestcontext == null)
    {
    throw new argumentnullexception("requestcontext");
    }
    this.requestcontext = requestcontext;
    }
    /// <summary>adds the version header by using the specified http context.</summary>
    /// <param name="httpcontext">the http context.</param>
    protected internal virtual void addversionheader(httpcontextbase httpcontext)
    {
    if (!mvchandler.disablemvcresponseheader)
    {
    httpcontext.response.appendheader(mvchandler.mvcversionheadername, mvchandler.mvcversion);
    }
    }
    /// <summary>called by asp.net to begin asynchronous request processing.</summary>
    /// <returns>the status of the asynchronous call.</returns>
    /// <param name="httpcontext">the http context.</param>
    /// <param name="callback">the asynchronous callback method.</param>
    /// <param name="state">the state of the asynchronous object.</param>
    protected virtual iasyncresult beginprocessrequest(httpcontext httpcontext, asynccallback callback, object state)
    {
    httpcontextbase httpcontext2 = new httpcontextwrapper(httpcontext);
    return this.beginprocessrequest(httpcontext2, callback, state);
    }
    /// <summary>called by asp.net to begin asynchronous request processing using the base http context.</summary>
    /// <returns>the status of the asynchronous call.</returns>
    /// <param name="httpcontext">the http context.</param>
    /// <param name="callback">the asynchronous callback method.</param>
    /// <param name="state">the state of the asynchronous object.</param>
    protected internal virtual iasyncresult beginprocessrequest(httpcontextbase httpcontext, asynccallback callback, object state)
    {
    icontroller controller;
    icontrollerfactory factory;
    this.processrequestinit(httpcontext, out controller, out factory);
    iasynccontroller asynccontroller = controller as iasynccontroller;
    if (asynccontroller != null)
    {
    begininvokedelegate<mvchandler.processrequeststate> arg_51_0;
    if ((arg_51_0 = mvchandler.<>c.<>9__20_0) == null)
    {
    arg_51_0 = (mvchandler.<>c.<>9__20_0 = new begininvokedelegate<mvchandler.processrequeststate>(mvchandler.<>c.<>9.<beginprocessrequest>b__20_0));
    }
    begininvokedelegate<mvchandler.processrequeststate> begindelegate = arg_51_0;
    endinvokevoiddelegate<mvchandler.processrequeststate> arg_71_0;
    if ((arg_71_0 = mvchandler.<>c.<>9__20_1) == null)
    {
    arg_71_0 = (mvchandler.<>c.<>9__20_1 = new endinvokevoiddelegate<mvchandler.processrequeststate>(mvchandler.<>c.<>9.<beginprocessrequest>b__20_1));
    }
    endinvokevoiddelegate<mvchandler.processrequeststate> enddelegate = arg_71_0;
    mvchandler.processrequeststate invokestate = new mvchandler.processrequeststate
    {
    asynccontroller = asynccontroller,
    factory = factory,
    requestcontext = this.requestcontext
    };
    synchronizationcontext synchronizationcontext = synchronizationcontextutil.getsynchronizationcontext();
    return asyncresultwrapper.begin<mvchandler.processrequeststate>(callback, state, begindelegate, enddelegate, invokestate, mvchandler._processrequesttag, -1, synchronizationcontext);
    }
    action action = delegate
    {
    try
    {
    controller.execute(this.requestcontext);
    }
    finally
    {
    factory.releasecontroller(controller);
    }
    };
    return asyncresultwrapper.beginsynchronous(callback, state, action, mvchandler._processrequesttag);
    }
    /// <summary>called by asp.net when asynchronous request processing has ended.</summary>
    /// <param name="asyncresult">the asynchronous result.</param>
    protected internal virtual void endprocessrequest(iasyncresult asyncresult)
    {
    asyncresultwrapper.end(asyncresult, mvchandler._processrequesttag);
    }
    private static string getmvcversionstring()
    {
    return new assemblyname(typeof(mvchandler).assembly.fullname).version.tostring(2);
    }
    /// <summary>processes the request by using the specified http request context.</summary>
    /// <param name="httpcontext">the http context.</param>
    protected virtual void processrequest(httpcontext httpcontext)
    {
    httpcontextbase httpcontext2 = new httpcontextwrapper(httpcontext);
    this.processrequest(httpcontext2);
    }
    /// <summary>processes the request by using the specified base http request context.</summary>
    /// <param name="httpcontext">the http context.</param>
    protected internal virtual void processrequest(httpcontextbase httpcontext)
    {
    icontroller controller;
    icontrollerfactory controllerfactory;
    this.processrequestinit(httpcontext, out controller, out controllerfactory);
    try
    {
    controller.execute(this.requestcontext);
    }
    finally
    {
    controllerfactory.releasecontroller(controller);
    }
    }
    private void processrequestinit(httpcontextbase httpcontext, out icontroller controller, out icontrollerfactory factory)
    {
    httpcontext current = httpcontext.current;
    if (current != null)
    {
    bool? flag = validationutility.isvalidationenabled(current);
    bool flag2 = true;
    if (flag.getvalueordefault() == flag2 & flag.hasvalue)
    {
    validationutility.enabledynamicvalidation(current);
    }
    }
    this.addversionheader(httpcontext);
    this.removeoptionalroutingparameters();
    string requiredstring = this.requestcontext.routedata.getrequiredstring("controller");
    factory = this.controllerbuilder.getcontrollerfactory();
    controller = factory.createcontroller(this.requestcontext, requiredstring);
    if (controller == null)
    {
    throw new invalidoperationexception(string.format(cultureinfo.currentculture, mvcresources.controllerbuilder_factoryreturnednull, new object[]
    {
    factory.gettype(),
    requiredstring
    }));
    }
    }
    private void removeoptionalroutingparameters()
    {
    idictionary<string, object> arg_2f_0 = this.requestcontext.routedata.values;
    func<keyvaluepair<string, object>, bool> arg_2f_1;
    if ((arg_2f_1 = mvchandler.<>c.<>9__26_0) == null)
    {
    arg_2f_1 = (mvchandler.<>c.<>9__26_0 = new func<keyvaluepair<string, object>, bool>(mvchandler.<>c.<>9.<removeoptionalroutingparameters>b__26_0));
    }
    arg_2f_0.removefromdictionary(arg_2f_1);
    }
    /// <summary>enables processing of http web requests by a custom http handler that implements the <see cref="t:system.web.ihttphandler" /> interface.</summary>
    /// <param name="httpcontext">an <see cref="t:system.web.httpcontext" /> object that provides references to the intrinsic server objects (for example, request, response, session, and server) that are used to service http requests.</param>
    void ihttphandler.processrequest(httpcontext httpcontext)
    {
    this.processrequest(httpcontext);
    }
    /// <summary>called by asp.net to begin asynchronous request processing using the base http context.</summary>
    /// <returns>the status of the asynchronous call.</returns>
    /// <param name="context">the http context.</param>
    /// <param name="cb">the asynchronous callback method.</param>
    /// <param name="extradata">the data.</param>
    iasyncresult ihttpasynchandler.beginprocessrequest(httpcontext context, asynccallback cb, object extradata)
    {
    return this.beginprocessrequest(context, cb, extradata);
    }
    /// <summary>called by asp.net when asynchronous request processing has ended.</summary>
    /// <param name="result">the asynchronous result.</param>
    void ihttpasynchandler.endprocessrequest(iasyncresult result)
    {
    this.endprocessrequest(result);
    }
    }
    }
    httpruntime 调用 ihttphandler 类型的调用 processrequest() 方法,用于处理请求。
    protected internal virtual void processrequest(httpcontextbase httpcontext)
    {
    icontroller controller;
    icontrollerfactory controllerfactory;
    this.processrequestinit(httpcontext, out controller, out controllerfactory);创建 icontrollerfactory,并创建 icontroller 对象。
    try
    {
    controller.execute(this.requestcontext);执行controller,背后就是调用相应的 action 方法。
    }
    finally
    {
    controllerfactory.releasecontroller(controller);
    }
    }

    核心处理请求的方法是processrequestinit(),用于创建 icontroller 和 icontrollerfactory 实例。icontrollerfactory 的实际类型是:defaultcontrollerfactory,该类型用于创建 icontroller  类型的实例。

    private void processrequestinit(httpcontextbase httpcontext, out icontroller controller, out icontrollerfactory factory)
    {
    httpcontext current = httpcontext.current;
    if (current != null)
    {
    bool? flag = validationutility.isvalidationenabled(current);
    bool flag2 = true;
    if (flag.getvalueordefault() == flag2 & flag.hasvalue)
    {
    validationutility.enabledynamicvalidation(current);
    }
    }
    this.addversionheader(httpcontext);
    this.removeoptionalroutingparameters();
    string requiredstring = this.requestcontext.routedata.getrequiredstring("controller");
    factory = this.controllerbuilder.getcontrollerfactory();
    controller = factory.createcontroller(this.requestcontext, requiredstring);
    if (controller == null)
    {
    throw new invalidoperationexception(string.format(cultureinfo.currentculture, mvcresources.controllerbuilder_factoryreturnednull, new object[]
    {
    factory.gettype(),
    requiredstring
    }));
    }
    }

    以上加红的代码就是创建 icontroller 的实例的逻辑。icontroller 实例创建完成后,判断是否实现了 iasynccontroller 接口,如果是,就异步执行 controller 方法的调用,否则就同步执行。

    protected internal virtual iasyncresult beginprocessrequest(httpcontextbase httpcontext, asynccallback callback, object state)
    {
    icontroller controller;
    icontrollerfactory factory;
    this.processrequestinit(httpcontext, out controller, out factory);
    iasynccontroller asynccontroller = controller as iasynccontroller; 判读是否是需要异步执行
    if (asynccontroller != null)异步执行
    {
    begininvokedelegate<mvchandler.processrequeststate> arg_51_0;
    if ((arg_51_0 = mvchandler.<>c.<>9__20_0) == null)
    {
    arg_51_0 = (mvchandler.<>c.<>9__20_0 = new begininvokedelegate<mvchandler.processrequeststate>(mvchandler.<>c.<>9.<beginprocessrequest>b__20_0));
    }
    begininvokedelegate<mvchandler.processrequeststate> begindelegate = arg_51_0;
    endinvokevoiddelegate<mvchandler.processrequeststate> arg_71_0;
    if ((arg_71_0 = mvchandler.<>c.<>9__20_1) == null)
    {
    arg_71_0 = (mvchandler.<>c.<>9__20_1 = new endinvokevoiddelegate<mvchandler.processrequeststate>(mvchandler.<>c.<>9.<beginprocessrequest>b__20_1));
    }
    endinvokevoiddelegate<mvchandler.processrequeststate> enddelegate = arg_71_0;
    mvchandler.processrequeststate invokestate = new mvchandler.processrequeststate
    {
    asynccontroller = asynccontroller,
    factory = factory,
    requestcontext = this.requestcontext
    };
    synchronizationcontext synchronizationcontext = synchronizationcontextutil.getsynchronizationcontext();
    return asyncresultwrapper.begin<mvchandler.processrequeststate>(callback, state, begindelegate, enddelegate, invokestate, mvchandler._processrequesttag, -1, synchronizationcontext);
    }
    action action = delegate//同步执行。
    {
    try
    {
    controller.execute(this.requestcontext);
    }
    finally
    {
    factory.releasecontroller(controller);
    }
    };
    return asyncresultwrapper.beginsynchronous(callback, state, action, mvchandler._processrequesttag);
    }

    (3)、action 执行模块,通过 controlleractioninvoker 调用 invokeaction() 执行其方法。action 方法的执行也有2个版本,一个是异步版本,一个是同步版本。由于 actioninvoker 实现了 iasyncactioninvoker 接口,所以也是以已方式执行。该类型是 asynccontrolleractioninvoker。

    a、当controller对象被创建之后,紧接着就会执行controler 对象的 execute(),其实背后就是调用 invokeaction() 方法:

    public virtual bool invokeaction(controllercontext controllercontext, string actionname)
    {
    if (controllercontext == null)
    {
    throw new argumentnullexception("controllercontext");
    }
    if (string.isnullorempty(actionname) && !controllercontext.routedata.hasdirectroutematch())
    {
    throw new argumentexception(mvcresources.common_nullorempty, "actionname");
    }
    controllerdescriptor controllerdescriptor = this.getcontrollerdescriptor(controllercontext);
    actiondescriptor actiondescriptor = this.findaction(controllercontext, controllerdescriptor, actionname);
    if (actiondescriptor != null)
    {
    filterinfo filters = this.getfilters(controllercontext, actiondescriptor); 获取所有过滤器,全局的、控制器的和方法的
    try
    {
    authenticationcontext authenticationcontext = this.invokeauthenticationfilters(controllercontext, filters.authenticationfilters, actiondescriptor);认证过滤器的执行。
    if (authenticationcontext.result != null)
    {
    authenticationchallengecontext authenticationchallengecontext = this.invokeauthenticationfilterschallenge(controllercontext, filters.authenticationfilters, actiondescriptor, authenticationcontext.result);
    this.invokeactionresult(controllercontext, authenticationchallengecontext.result ?? authenticationcontext.result);
    }
    else
    {
    authorizationcontext authorizationcontext = this.invokeauthorizationfilters(controllercontext, filters.authorizationfilters, actiondescriptor);授权过滤器的执行。
    if (authorizationcontext.result != null)
    {
    authenticationchallengecontext authenticationchallengecontext2 = this.invokeauthenticationfilterschallenge(controllercontext, filters.authenticationfilters, actiondescriptor, authorizationcontext.result);
    this.invokeactionresult(controllercontext, authenticationchallengecontext2.result ?? authorizationcontext.result);
    }
    else
    {
    if (controllercontext.controller.validaterequest)
    {
    controlleractioninvoker.validaterequest(controllercontext);
    }
    idictionary<string, object> parametervalues = this.getparametervalues(controllercontext, actiondescriptor); 获取方法执行参数。
    actionexecutedcontext actionexecutedcontext = this.invokeactionmethodwithfilters(controllercontext, filters.actionfilters, actiondescriptor, parametervalues); 执行action,同时执行执行方法前后的 iacctionfilter
    authenticationchallengecontext authenticationchallengecontext3 = this.invokeauthenticationfilterschallenge(controllercontext, filters.authenticationfilters, actiondescriptor, actionexecutedcontext.result);
    this.invokeactionresultwithfilters(controllercontext, filters.resultfilters, authenticationchallengecontext3.result ?? actionexecutedcontext.result); 执行 actionresult,同时执行方法前后的 iresultfilter
    }
    }
    }
    catch (threadabortexception)
    {
    throw;
    }
    catch (exception exception)
    {
    exceptioncontext exceptioncontext = this.invokeexceptionfilters(controllercontext, filters.exceptionfilters, exception);
    if (!exceptioncontext.exceptionhandled)
    {
    throw;
    }
    this.invokeactionresult(controllercontext, exceptioncontext.result);//异常过滤器的执行。
    }
    return true;
    }
    return false;
    }
    

    b、当选择完合适的action后,接着就是 modelbinder(默认是system.web.mvc.defaultmodelbinder),它会从http请求的参数中提取数据并实现类型转换,数据校验(例如是否必填,数据格式等)以及是否自动装配到action方法的参数中system.web.mvc.defaultmodelbinder

    protected virtual idictionary<string, object> getparametervalues(controllercontext controllercontext, actiondescriptor actiondescriptor)
    {
    dictionary<string, object> dictionary = new dictionary<string, object>(stringcomparer.ordinalignorecase);
    parameterdescriptor[] parameters = actiondescriptor.getparameters();
    for (int i = 0; i < parameters.length; i++)
    {
    parameterdescriptor parameterdescriptor = parameters[i];
    dictionary[parameterdescriptor.parametername] = this.getparametervalue(controllercontext, parameterdescriptor);
    }
    return dictionary;
    }
    protected virtual object getparametervalue(controllercontext controllercontext, parameterdescriptor parameterdescriptor)
    {
    type parametertype = parameterdescriptor.parametertype;
    imodelbinder arg_92_0 = this.getmodelbinder(parameterdescriptor);
    ivalueprovider valueprovider = controllercontext.controller.valueprovider;
    string modelname = parameterdescriptor.bindinginfo.prefix ?? parameterdescriptor.parametername;
    predicate<string> propertyfilter = controlleractioninvoker.getpropertyfilter(parameterdescriptor);
    modelbindingcontext bindingcontext = new modelbindingcontext
    {
    fallbacktoemptyprefix = parameterdescriptor.bindinginfo.prefix == null,
    modelmetadata = modelmetadataproviders.current.getmetadatafortype(null, parametertype),
    modelname = modelname,
    modelstate = controllercontext.controller.viewdata.modelstate,
    propertyfilter = propertyfilter,
    valueprovider = valueprovider
    };
    return arg_92_0.bindmodel(controllercontext, bindingcontext) ?? parameterdescriptor.defaultvalue;
    }
    

    c、authentication filter是mvc5中新增的一个filter,它会先于authorization filter执行,目的是对访问用户的认证。在mvc5之前,认证和授权都是通过authorization filter来实现的,但现在这2个操作就分开来了,各自管各自喽。

    authenticationcontext authenticationcontext = this.invokeauthenticationfilters(controllercontext, filters.authenticationfilters, actiondescriptor);
    if (authenticationcontext.result != null)
    {
    authenticationchallengecontext authenticationchallengecontext = this.invokeauthenticationfilterschallenge(controllercontext, filters.authenticationfilters, actiondescriptor, authenticationcontext.result);
    this.invokeactionresult(controllercontext, authenticationchallengecontext.result ?? authenticationcontext.result);
    }
    

    d、action filters有2个方法onactionexecuting和onactionexecuted分别在action执行前后执行。我们也可以通过实现iactionfilter接口来实现你个性化的过滤机制

    protected virtual actionexecutedcontext invokeactionmethodwithfilters(controllercontext controllercontext, ilist<iactionfilter> filters, actiondescriptor actiondescriptor, idictionary<string, object> parameters)
    {
    actionexecutingcontext precontext = new actionexecutingcontext(controllercontext, actiondescriptor, parameters);
    func<actionexecutedcontext> seed = () => new actionexecutedcontext(controllercontext, actiondescriptor, false, null)
    {
    result = this.invokeactionmethod(controllercontext, actiondescriptor, parameters)
    };
    return filters.reverse<iactionfilter>().aggregate(seed, (func<actionexecutedcontext> next, iactionfilter filter) => () => controlleractioninvoker.invokeactionmethodfilter(filter, precontext, next))();
    }
    

    e、接下来就是执行我们平时在action方法中写的代码了(根据请求相应结果)

    protected virtual actionresult invokeactionmethod(controllercontext controllercontext, actiondescriptor actiondescriptor, idictionary<string, object> parameters)
    {
    object actionreturnvalue = actiondescriptor.execute(controllercontext, parameters);
    return this.createactionresult(controllercontext, actiondescriptor, actionreturnvalue);
    }

    (4)、actionresult 执行模块。

    a、在 actionresult 执行前后,仍然会有一个filter(iresultfilter),同样的,通过实现 iresultfilter 接口你可以定制自己的过滤逻辑。

    namespace system.web.mvc
    {
    /// <summary>defines the methods that are required for a result filter.</summary>
    public interface iresultfilter
    {
    /// <summary>called before an action result executes.</summary>
    /// <param name="filtercontext">the filter context.</param>
    void onresultexecuting(resultexecutingcontext filtercontext);
    /// <summary>called after an action result executes.</summary>
    /// <param name="filtercontext">the filter context.</param>
    void onresultexecuted(resultexecutedcontext filtercontext);
    }
    }
    

     b、actionresult 就是把处理的用户请求结果返回。因此 viewresult, partialviewresult, redirecttorouteresult, redirectresult, contentresult, jsonresult, fileresult and emptyresult就是具体的返回类型。

    c、上面的返回类型可以大致分为2类:viewresult 和非viewresult。对于需要生成html页面给客户端的划到viewresult,而其他的例如返回文本,json数据等则划分到非viewresult,对于非viewresult直接返回就可以了。

    view的初始化和渲染呈现

    a、对于 viewresult 最终是由合适的 view engine 通过调用 iview 的 render() 方法来渲染的:

    namespace system.web.mvc
    {
    /// <summary>defines the methods that are required for a view engine.</summary>
    public interface iviewengine
    {
    /// <summary>finds the specified partial view by using the specified controller context.</summary>
    /// <returns>the partial view.</returns>
    /// <param name="controllercontext">the controller context.</param>
    /// <param name="partialviewname">the name of the partial view.</param>
    /// <param name="usecache">true to specify that the view engine returns the cached view, if a cached view exists; otherwise, false.</param>
    viewengineresult findpartialview(controllercontext controllercontext, string partialviewname, bool usecache);
    /// <summary>finds the specified view by using the specified controller context.</summary>
    /// <returns>the page view.</returns>
    /// <param name="controllercontext">the controller context.</param>
    /// <param name="viewname">the name of the view.</param>
    /// <param name="mastername">the name of the master.</param>
    /// <param name="usecache">true to specify that the view engine returns the cached view, if a cached view exists; otherwise, false.</param>
    viewengineresult findview(controllercontext controllercontext, string viewname, string mastername, bool usecache);
    /// <summary>releases the specified view by using the specified controller context.</summary>
    /// <param name="controllercontext">the controller context.</param>
    /// <param name="view">the view.</param>
    void releaseview(controllercontext controllercontext, iview view);
    }
    }
    
    namespace system.web.mvc
    {
    /// <summary>defines the methods that are required for a view.</summary>
    public interface iview
    {
    /// <summary>renders the specified view context by using the specified the writer object.</summary>
    /// <param name="viewcontext">the view context.</param>
    /// <param name="writer">the writer object.</param>
    void render(viewcontext viewcontext, textwriter writer);
    }
    }
    

     b、整个处理过程是由 iviewengine 来实现的。asp.net mvc 默认提供 webform(.aspx)和 razor(.cshtml) 模板引擎,你可以通过实现 iviewengine 接口来实现自己的 viewengine,然后在application_start方法中做如下注册:

    protected void application_start()
    {
    //移除所有的view引擎包括webform和razor
    viewengines.engines.clear();
    //注册你自己的view引擎
    viewengines.engines.add(new customviewengine()); 
    }

    c、最后,html helpers将帮我们生成 input 标签,基于ajax的 form 等等。

    (5)、作为总结,将每个节点主要的代码类贴出来。

    这就是整个流程的代码节点,有些是同步执行,有些是异步执行,把握关键点,我这里只是谢了一个大概。

    urlroutingmodule—–routecollection.getroutedata(context)—–>iroutehandler routehandler = routedata.routehandler——》ihttphandler httphandler = routehandler.gethttphandler(requestcontext)—–》context.remaphandler(httphandler)——->mvchandler——->processrequest()——>processrequestinit()——–》icontroller——>controller.execute(this.requestcontext)——–>controlleractioninvoker——->involeaction()———>involeactionmethod()——->involeactionreslt()

    三、结束

    今天就到这里了,东西虽然不多,但是也写了2个多小时。今天就算自己有学习了一边,大家一定要好好的把握这个流程,对于解决程序中的问题,扩展框架都有很大的好处。我们作为程序员的,应该要知道其一,也要知道其二。没事,看看源码,我们对框架和我们自己的代码有更深的了解。当然,这样做也是有代价的,需要更多的时间去支持,我相信我们的付出是值得。不忘初心,继续努力。老天不会辜负努力的人。

    到此这篇关于详解asp.net mvc的整个生命周期的文章就介绍到这了,更多相关asp.net mvc 生命周期内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!