005. Asp.Net RoutingとMVCの3:MVCでのルーティングの使用

25000 ワード

前回はControllerとActionのアクティブ化をリクエストしましたが、今回はMVCでのルーティングの使用についてお話しします.今回の2つの注目点:
  • レガシー:ModelBinder.BindModelのプロセス
  • MVCにおけるルーティングの使用
  • MVC 5のAction新特性
  • 一、ModelBinder.BindModelのプロセス
    MVCHander –>  ProcessRequest()xxxxxController\ControllerFactoryIController.Excute();ControllerBase.Excute().ExcuteCore()Controller.ExecuteCore()  { . GetActionName  ;  IActionInvoker.InvokeAction() }
    IActionInvoker.InvokeAction() {
    get methodInfo //sys
    処理パラメータ//BindModel
    methodInfo.invoke();//sys
    }
    MVCソースでは、ControllerActionInvoker.InvokeAction()BindModelが何をしたか見てみましょう.
       1:  
       2: public class DefaultModelBinder : IModelBinder
       3: {
       4:     /// <summary>
       5:     /// ControllerContext (      ,  Controller     ,         RequestContext)
       6:     /// MVC Model Bind,    ControllerContext  ,     (          )  。
       7:     /// </summary>
       8:     /// <param name="controllerContext"></param>
       9:     /// <param name="modelName"></param>
      10:     /// <param name="modelType"></param>
      11:     /// <returns></returns>
      12:     public object BindModel(ControllerContext controllerContext, string modelName, Type modelType)
      13:     {
      14:         //            (string),     :   
      15:         if (modelType.IsValueType || typeof(string) == modelType)
      16:         {
      17:             object instance;
      18:             //          ,   
      19:             if (GetValueTypeInstance(controllerContext, modelName, modelType, out instance))
      20:             {
      21:                 return instance;
      22:             };
      23:             return Activator.CreateInstance(modelType);
      24:         }
      25:  
      26:         //     ,      
      27:         //          ,      
      28:         object modelInstance = Activator.CreateInstance(modelType);
      29:         //           ,       ,       ,        
      30:         foreach (PropertyInfo property in modelType.GetProperties())
      31:         {
      32:             //    action         “    ”   
      33:             if (!property.CanWrite || (!property.PropertyType.IsValueType && property.PropertyType != typeof(string)))
      34:             {
      35:                 continue;
      36:             }
      37:             object propertyValue;
      38:             if (GetValueTypeInstance(controllerContext, property.Name, property.PropertyType, out propertyValue))
      39:             {
      40:                 property.SetValue(modelInstance, propertyValue, null);
      41:             }
      42:         }
      43:         return modelInstance;
      44:     }
      45:  
      46:     /// <summary>
      47:     ///             (string),(     :   )   。
      48:     ///     (  ,bool,      struct),  enum,     
      49:     /// </summary>
      50:     /// <param name="controllerContext"></param>
      51:     /// <param name="modelName"></param>
      52:     /// <param name="modelType"></param>
      53:     /// <param name="value"></param>
      54:     /// <returns></returns>
      55:     private bool GetValueTypeInstance(ControllerContext controllerContext, string modelName, Type modelType, out object value)
      56:     {
      57:         //HttpPost   ,          
      58:         var form = HttpContext.Current.Request.Form;
      59:         string key;
      60:         //form     
      61:         if (null != form)
      62:         {
      63:             //       AllKeys     “modelName”   。
      64:             key = form.AllKeys.FirstOrDefault(k => string.Compare(k, modelName, true) == 0);
      65:             if (key != null)
      66:             {
      67:                 //?   
      68:                 //value =  Convert.ChangeType(form[key]., modelType);
      69:                 var curKeyVal = form[key];
      70:                 value = Convert.ChangeType(curKeyVal, modelType);
      71:                 return true;
      72:             }
      73:         }
      74:         //HttpGet   ,        QueryString
      75:         key = controllerContext.RequestContext.RouteData.Values
      76:             //  !
      77:             //.Where(item => string.Equals(item.Key, modelName,StringComparison.InvariantCultureIgnoreCase))
      78:             .Where(item => string.Compare(item.Key, modelName, true) == 0)
      79:             //get   ,    key         
      80:             .Select(item => item.Key).FirstOrDefault();
      81:         if (null != key)
      82:         {
      83:             value = Convert.ChangeType(controllerContext.RequestContext.RouteData.Values[key], modelType);
      84:             return true;
      85:         }
      86:  
      87:         //http://msdn.microsoft.com/zh-cn/library/system.web.routing.routedata.datatokens.aspx
      88:         //RouteData.DataTokens   
      89:         // RouteData.Values        ,   key   。
      90:         //     RouteData.Values   ???
      91:         key = controllerContext.RequestContext.RouteData.DataTokens
      92:             .Where(item => string.Compare(item.Key, modelName, true) == 0)
      93:             .Select(item => item.Key).FirstOrDefault();
      94:         if (null != key)
      95:         {
      96:             value = Convert.ChangeType(controllerContext.RequestContext.RouteData.DataTokens[key], modelType);
      97:             return true;
      98:         }
      99:         value = null;
     100:         return false;
     101:     }
     102: }
     
    要約すると
    1、ControllerActionInvoker.InvokeAction()では、現在のMethodInfoのパラメータ配列を取得する(完全なMVCプロジェクトでは、InvokeActionの場合、各種フィルタの操作、ActionExecutedContext Action実行コンテキストの構築など)
    2.MethodInfoのパラメータ配列を循環し、IModelBinderを呼び出す.BindModel()はパラメータに値を割り当てます
    3、IModelBinder.BindModel()は、パラメータのタイプが、値タイプであると判断し、RouteDataから直接ルーティング値を取得し、対応するタイプに変換して出力して返します.
    4、参照タイプで、このタイプのデフォルトのコンストラクタを呼び出し、そのタイプをインスタンス化し、その公開属性を循環し、値タイプの付与方式を繰り返し、値出力を付与し、返す.
     
     
    二、MVCにおけるルーティングの使用
    MVCでは,ユーザがアクセスするアドレスはサーバに対応するファイルにマッピングされるのではなく,対応するControlに対応するActionMethodにマッピングされ,ActionMethodによってユーザがどのような情報を返すかが決定される.ユーザがアクセスするアドレスを対応するAction(もちろん対応するファイルであってもよい)に対応させる作業は、ルーティングシステムによって行われ、その多くの複雑な処理は、Netは自動的に完了し、開発者は伝える必要がある.Netユーザのアクセスアドレスと対応アクションの具体的なマッピング関係.MVCにおけるルーティングシステムは、(1)の2つのタスクを完了することができる.ユーザから受信したURLから対応するActionへのマッピングを処理する.(2). あるアクションをルーティングシステムのマッピング関係に基づいて動的にURLを生成する(ウェブサイトのプログラム構造が変更されると、そのURLも自動的に変更される).
     
    1、登録:
    MVCプロジェクトでのRouteConfig.RegisterRoutes()に登録されています.典型的なRouteConfigの内容は次のとおりです.
       1: public class RouteConfig
       2: {
       3:     public static void RegisterRoutes(RouteCollection routes)
       4:     {
       5:         routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
       6:  
       7:         Route myRoute1 = new Route("mytest/{controller}/{action}/{id}", new MvcRouteHandler());        
       8:         routes.Add("MyRoute1", myRoute1);
       9:  
      10:         //      ,  MapRoute  System.Web.Mvc.RouteCollectionExtensions
      11:         // RouteCollectionExtensions      
      12:         routes.MapRoute(
      13:             name: "Default",//  
      14:             url: "{controller11}/{action2123}/{id}",  //url             , 《Asp.Net Routing MVC   :    MVC   》  
      15:             //id = UrlParameter.Optional         
      16:             defaults: new { controller11 = "Home", action2123 = "Index", id = UrlParameter.Optional }
      17:         );
      18:     //    url
      19:     routes.MapRoute(
      20:             name: "DefaultNonExist",//  
      21:             url: "{controller11}/{action2123}/{id}",  //url             , 《Asp.Net Routing MVC   :    MVC   》  
      22:             //id = UrlParameter.Optional         
      23:             defaults: new { controller11 = "Home", action2123 = "IndexNonExist", id = UrlParameter.Optional }
      24:         );
      25:  
      26:  
      27:  
      28:         //   MVC5    ,      “      ”
      29:         routes.MapMvcAttributeRoutes();
      30:     }
      31: }
     
    2、受け取ったURLの処理
    2番目のパラメータのうち、「ABC{category}/{controller}/Page{page}/DEF」は、ルーティングシステムがここのパラメータに基づいて、ユーザが要求したURLとここのパラメータをマッチングし、2つのマッピングマッチング方式があります.
         (1).ダイナミックコンテンツは、{}に置かれている、すなわち、controllerなどのマッチングするパラメータ名であり、actionのコンテンツはcontroller、actionパラメータにマッチングされ、割り当てられます.次にcontroller,actionパラメータの値に基づいてcontrollerタイプを検索し,このcontrollerで対応するActionMethodを探す.
         (2).静的コンテンツ、{}以外のコンテンツは、mytest/...などのURLと比較されます.
    URLとこのパラメータの両方の比較比が一致した場合、完全一致となります.次に、対応するControllerとActionが処理を実行する.そうでなければ、成功したURL項目が一致していません.action 2123のように、デフォルトのパラメータでActionが一致し、デフォルトのパラメータが一致しない場合、例外が放出されます.
    同じURLの場合、重複するMapRouteが複数登録されている場合、最初の1つだけ有効になります.
     
     
    3、対応するActionをURLルーティングシステムに変換する第2の機能は、Actionを対応するURLに変換することを実現することである.
    1,リンク生成:@Html.ActionLink(「About thisアプリケーション」,「Index」,「Home」,new{id=「myAnchorID」,@class=「myCSSClass」)第4位的电脑可以向生成的链接提供属性.如果提供的电脑和卢丁系统的电脑不一致的话,QueryString:?=..生成される.2,生成URL文字列:生成URLのみを生成する文字列,也就是href後の内容@Html.Action()是与ActionLink相同的使用方法.三,MVC 5中的新规则特性1,Attribute规则是?你觉得有效Attribute规则怎么办?マイクロソフトはASP.NET MVC 5中,正如名字的那样,Attributeルーティン引入了由Attribute定义ルーティン的新ルーティン.当然,MVC 5以前也支持着定义鲁蒂恩格的方法,在1个项目中混合这个2个方式定义鲁蒂文。MVC 5中,可以与规则定义和Action一起。这是一个新的方法。1://MVC 5の新しいルーティング特性は、RouteConfigで2:[Route("{testId:int}/{testName})]3:public ActionResult About(int testId,string testName)4:{5:ViewBag.Message=string.Format(「Your application description page.test info:{0},{1}」,testId,testName);6:  7: return View(); 8:}2,URL OptionParameter和数据值疑问符"?"可以使用。选择1://オプションのプロパティルーティングパラメータおよびデフォルト2:[Route("{testId?}/{testName=JasonLiu}")] 3: public ActionResult About1(int? testId,string testName) 4: { 5: ViewBag.Message = string.Format("Your application description page.test info :{0},{1}", testId,testName); 6:  7: return View(); 8:}3,在路线节目辞和デフォルトルテイング相同的Controller中,所有动作一致的URL上有同样的接头辞.如果某种Action不想使用接尾辞的话,使用~无视她。可以指定现在的规则的数据值.1:[RoutePrefix("myhome")//このControllerのデフォルトルーティング接頭辞2:[Route("{action=index}")]//////このController対応ルーティングのデフォルトaction値3:[Route("{testName=JasonLiu}")]////上記のように4:public class HomeController:Controller 5:{6:{6:7:public ActionResultIndex()8:{9:returnView();10:}11:12:///MVC 5の新しい新しい新しい新しい新しい新しい新しい新しい新しいバージョン5:{6:12:7:ルーティング特性、Route Configに行く必要はありません13:[Route("{testId:int}/{testName})]14:public ActionResult About(int testId,string testName)15:{16:ViewBag.Message=string.Format(「Your application description page.test info:{0},{1}」,testId,testName);17:  18: return View(); 19:}20:21//オプションのプロパティルーティングパラメータおよびデフォルト値22:[Route("{testId?}/{testName=JasonLiu}")] 23: public ActionResult About1(int? testId, string testName) 24: { 25: ViewBag.Message = string.Format("Your application description page.test info :{0},{1}", testId, testName); 26:  27: return View(); 28: } 29:  30: [Route("~/contact")] 31: public ActionResult Contact() 32: { 33: ViewBag.Message = "Your contact page."34:35:return View();36:}37:}另外,规则制约等,遵守以往的通常规则定义和同样的规则.