あなたをオープンソースに連れて行きます-ASP.NET_MVC(二)

6505 ワード

前の記事では全体的にASPを紹介しています.NET MVCのリクエスト処理フローは、「ルーティング」、「コントローラ」、「ビュー」および「モデル」に大別され、以下、フロー順に展開される.
一、ルート
ルーティングといえば、実際にはASP.NETのコアルーティングエンジンとMVCルーティング.コアルーティングエンジンはオープンソースではありません(マイクロソフトは手を残しています).ブラウザから送られてきたURLを解析し、コントローラを割り当てます.
ここでは、IrouteHandlerインタフェースを明示的に実装したMvcRouteHandlerというMVCルーティングを解析します.GetHttpHandlerメソッドはMvcHandlerオブジェクトを返し、MvcHandlerはIHttpHandlerインタフェースを実装しているので、次のようなProcessRequestメソッドが含まれています.
      
  protected internal virtual voidProcessRequest(HttpContextBase httpContext)
        {
            IController controller;
            IControllerFactory factory;
            ProcessRequestInit(httpContext, outcontroller, out factory);
 
            try
            {
               controller.Execute(RequestContext);
            }
            finally
            {
               factory.ReleaseController(controller);
            }
        }

コードセグメント1
このプロセスリクエストの方法は、皆さんも顔見知りだと思いますよね?いいですね.ASPにいます.NET WebFormの開発では、一般的なハンドラ、すなわち.ashxファイル、このファイルのクラスはIHttpHandlerインタフェースを実現し、ProcessRequestメソッドもあります.
さて、このProcessRequestメソッドは、ルーティングがコントローラに位置決めされた後に実行されるコア操作です.つまりcontroller.Execute(RequestContext)文の実行により、HTML応答の生成とブラウザへの返信が発生します.簡単でしょう?私たちはここで最も核心的で、最も骨格的な部分に言及しただけで、細部には触れていません.枝葉末節に邪魔されないようにしています.次にコントローラを分析します.
二、コントローラ
コードセグメント1のcontrollerは、インタフェースIControllerの一例であり、インタフェースIControllerは簡単であり、次のような方法しかありません.
<pre name="code" class="csharp">    public interface IController
    {
        void Execute(RequestContextrequestContext);
    }
 
  
 

代码段 2

Controller的实例化是由【ProcessRequestInit(httpContext, out controller, out factory)】这个语句完成的,下面我们看一下ProcessRequestInit这个方法中实例化Controller的部分,不考虑细节,直奔主题。

   

     private voidProcessRequestInit(HttpContextBase httpContext, out IController controller, outIControllerFactory factory)
        {
            // If request validation hasalready been enabled, make it lazy. This allows attributes like [HttpPost](which looks
            // at Request.Form) to workcorrectly without triggering full validation.
            // Tolerate null HttpContext fortesting.
            HttpContext currentContext =HttpContext.Current;
            if (currentContext != null)
            {
                bool?isRequestValidationEnabled =ValidationUtility.IsValidationEnabled(currentContext);
                if (isRequestValidationEnabled== true)
                {
                   ValidationUtility.EnableDynamicValidation(currentContext);
                }
            }
 
            AddVersionHeader(httpContext);
            RemoveOptionalRoutingParameters();
 
            // Get the controller type
            string controllerName =RequestContext.RouteData.GetRequiredString("controller");
 
            // Instantiate the controller andcall Execute
            factory =ControllerBuilder.GetControllerFactory();
            controller =factory.CreateController(RequestContext, controllerName);
            if (controller == null)
            {
                throw newInvalidOperationException(
                    String.Format(
                        CultureInfo.CurrentCulture,
                       MvcResources.ControllerBuilder_FactoryReturnedNull,
                        factory.GetType(),
                        controllerName));
            }
        }

コードセグメント3
コードセグメント3の「コントローラ=factory.CreateController(RequestContext,controller Name)」文は、ルーティングシステムによって位置決めされたコントローラ情報(すなわち、Controllerフォルダで定義された各コントローラクラス)に基づいて、反射によってコントローラオブジェクトを作成するコントローラをインスタンス化する場所である.もちろん、コントローラ工場、検証の要求など、実装の詳細はたくさんありますが、脈絡を明確に保つために、ここで省略します.後述します.
IControllerインタフェースはMVCにいくつかの内蔵実装クラスがあり、ControllerBaseおよびIAsyncControllerを含むが、ControllerはControllerBaseのサブクラスであり、最も一般的なコントローラベースクラスである.
実際には、IControllerを自分で実現することができます.例えば、
publicclass MyController : IController
{
public voidExecute(RequestContext requestContext)
{
requestContext.HttpContext.Response.Write(“Hello”);
}
}

コードセグメント4
どうですか.SoEasy!大きなRazorエンジンなどを使わなくてもいいです.しかし、このようにすると非常に強い結合を招き、HTMLを自分で解析する必要があります.これは疲れた仕事です.
MVCのControllerクラスがどのように実現されているかを見てみましょう.ControllerはControllerBaseクラスに継承され、ControllerBaseはExecuteメソッド(コードセグメント5)を実装し、ControllerはControllerBaseのExecuteCoreメソッド(コードセグメント6)を書き換えた.
      
  protected virtual voidExecute(RequestContext requestContext)
        {
            if (requestContext == null)
            {
                throw newArgumentNullException("requestContext");
            }
            if (requestContext.HttpContext ==null)
            {
                throw newArgumentException(MvcResources.ControllerBase_CannotExecuteWithNullHttpContext,"requestContext");
            }
 
            VerifyExecuteCalledOnce();
            Initialize(requestContext);
 
            using(ScopeStorage.CreateTransientScope())
            {
                ExecuteCore();
            }
        }

コードセグメント5
        
protected override void ExecuteCore()
        {
            // If code in this method needs tobe updated, please also check the BeginExecuteCore() and
            // EndExecuteCore() methods ofAsyncController to see if that code also must be updated.
 
            PossiblyLoadTempData();
            try
            {
                string actionName =GetActionName(RouteData);
                if(!ActionInvoker.InvokeAction(ControllerContext, actionName))
                {
                   HandleUnknownAction(actionName);
                }
            }
            finally
            {
                PossiblySaveTempData();
            }
        }

コードセグメント6
ExecuteCoreメソッドを見てみましょう.そのコア文は「if(!ActionInvoker.InvokeAction(ControllerContext,actionName)」です.この文は特定のActionを実行する場所で、その文が実行されるとHTTP応答がブラウザに返されます.ここではActionInvokerを使いました.ActionInvokeActionメソッドで、ActionInvokerはIActionInvokerインタフェースの例であり、このインタフェースの定義もかなり簡単で、以下のようにします.
    public interface IActionInvoker
    {
        bool InvokeAction(ControllerContextcontrollerContext, string actionName);
    }

コードセグメント7
MVCに内蔵されているIActionInvoker実装クラスには、ControllerActionInvokerとIAsyncActionInvokerがあり、後者は非同期クラスであるが、それにかかわらずControllerActionInvokerを重点的に分析する.
ControllerActionInvokerのInvokeActionメソッドの実装は複雑で、約90行のコードがあります.今日は少し疲れたので、明日続けます.