DCSIMG
March 2011 - Posts - I Love C#
Sign in | Join | Help

I Love C#

Eyal Vardi

March 2011 - Posts

ASP.NET MVC 3.0 Internals

פורסם בתאריך Mar 28 2011, 04:22 PM על ידי Vardi

ASP.NET MVC 3.0 Internals

בפוסט זה אני רוצה לכתוב על איך עובד ה- ASP.NET MVC 3.0 ואיפה אפשר להרחיב ולשנות את הטכנולוגיה.

אני מחלק את הפוסט לארבעה חלקים:

1. החיבור בין ASP.NET ל- ASP.NET MVC

2. Controller Extensibility

3. Model Extensibility

4. View Extensibility

1. החיבור בין ASP.NET ל- ASP.NET MVC.

ה- MVC חי בתוך ה- ASP.NET וכדי לשנות את סדר הפעולות שקורות ב- ASP.NET הוא משתמש במנגנון ה- Routing שנוסף בדוט-נט 4, הוא רושם אוביקט Route ל- RouteTable.

clip_image002

ב- Global.asax.cs אנחנו יכולים לראות את הקוד הבא:

routes.MapRoute(

    "Default",                    // Route name

    "{controller}/{action}/{id}", // URL with parameters

    new                           // Parameter defaults

    {

       controller = "Home",

       action     = "Index",

       id         = UrlParameter.Optional

    }

);

המתודה MapRoute היא Extension Method תפקידה ליצור אוביקט Route שמקשר בין ה- "{controller}/{action}/{id}" ל- MvcRouteHandler. אם מסתכלים בתוך הקוד של המתודה MapRoute נמצא את השורות הבאות:

var route = 
     new Route( url , new MvcRouteHandler() )
     {
        Defaults    = new RouteValueDictionary(defaults),
        Constraints = new RouteValueDictionary(constraints),
        DataTokens  = new RouteValueDictionary()
     };
 
ה- MvcRouteHandler מממש את הממשק IRouteHandler שתפקידו לספק HttpHandler.

clip_image003

ה- MvcRouteHandler מחזיר מהמתודה GetHttpHandler את המחלקה MvcHandler.

clip_image004

התפקיד של MvcHandler ליצור מחלקה שמממשת את הממשק IControllerFactory וליצר בעזרתו את IController.

clip_image005

אם ברצוננו לתת מימוש אחר ל- IControllerFactory או לכל אחד מהממשקים שאני אכתוב עליהם, אנחנו יכולים לעשות את זה ע"י מימוש של IDependencyResolver ורישומו ב- Global.asax.

clip_image006

DependencyResolver.SetResolver( new MyDependencyResolver() );

התשתית של MVC כל פעם שהיא צריכה מימוש של ממשק היא קוראת ל- GetService ונותנת את ה-Type כארגומנט. אם אין לכם מימוש שאתם רוצים להחזיר אז מחזירים Null ואז התשתית בוחרת את מימוש ברירת המחדל של ה- MVC.

לסיכום חלק ראשון:

image

1. הוספנו Route אוביקט שכאשר התנאי מתקיים הוא מפעיל את GetHttpHandler מתודה של MvcRouteHandler.

2. המתודה מחזירה MvcHandler שכאשר הוא מופעל הוא פונה ל- Dependency Resolver ומבקש מימוש ל- IControllerFactory.

3. ה- IControllerFactory יוצר Controller.

2. Controller Extensibility

כאשר מדברים על נקודות הרחבה של Controller מדברים על Filters. ה- Filters מחלקים את ביצוע ה- Action לשש נקודות שאפשר להרחיב.

clip_image009

אפשר לשתול את ה-Filters במספר דרכים.

1. Attribute, אפשר ללהרחיב את ActionFilterAttribute.

clip_image010

2. לרשום אותם ישירות ל- GlobalFilters.Filters.

3. להרחיב את המחלקה Controller.

clip_image011

4. לממש את IFilterProvider, ולרשום את המימוש דרך FilterProvider או ע"י DependencyResolver.

3. Model Extensibility

כאן אנחנו יכולים לטפל במספר נושאים:

1. איך להמיר בקשת HTTP למחלקה של דוט-נט.

2. איך לבצע בדיקת אימות (Data Validation).

הממשק IModelBinder עושה את העבודה.

clip_image012

כמו שרואים ע"פ חתימת המתודה תפקידו של ממשק זה ליצר אוביקט שהוא הארגומט במתודה של ה-Action. את המידע על סוג האוביקט ועל הנתונים שהגיעו מהבקשה נמצא ב- bindingContext.

clip_image013

כמו שאתם רואים ה-bindingContext מספק לנו את כל המידע הרלוונטי כדי לבנות ולאתחל את האובייקט שלנו.

איך רושמים מחלקה שמממשת את הממשק IModelBinder?

1. ע"י ה-Attribute ModelBinderAttribute

2. ע"י ModelBinders.Binders

3. ע"י DependencyResolver

4. ע"י מימוש של IModelBinderProvider ורישומו דרך ModelBinderProviders או ע"י DependencyResolver.

4. View Extensibility

התפקיד של ההרחבות של ה-View הוא למצוא את המקום הפיזי של הקובץ ולהחזיר מהקובץ View מחלקה ViewEngineResult. הממשק IViewEngine אחראי על פעולות אלו.

clip_image014

ה-Mvc מספק שתי מימושים עיקריים לממשק זה.

clip_image016

אם נסתכל על RazorViewEngine המתודה CreatView יוצרת IView והמתודה FindView אורזת את ה-IView ב- ViewEngineResult.

clip_image017

ה-Mvc מספק גם מימושים ל-IView.

clip_image018

בתוך המתודה RenderView משתמשים במחלקות עזר שמממשות את הממשק IviewDataContainer.

clip_image019

הכל מתחיל ברישום המחלקה שמממשת את IViewEngine ע"י ViewEngines או ע"י DependencyResolver.

All the extension points:

1.      Routing

a.      Add Route object with IRouteHandler.

b.      Custom MvcHandler

 

2.      IDependencyResolver

 

3.      Controller 

a.      IControllerFactory

b.      IControllerActivator

c.      IController

d.     Filters

                                                    i.     IAuthorizationFilter

                                                   ii.     IActionFilter

                                                  iii.     IResultFilter

                                                  iv.     IExceptionFilter

 

4.      Model

a.      IModelBinder

b.      IModelBinderProvider

c.      ModelMetadataProvider

d.      IValueProvider

e.      ModelValidatorProvider

 

5.      View

a.      IViewEngine

b.     IViewPageActivator

c.      IView

d.     IViewDataContainer

מקווה שעזרתי לכם להבין טוב יותר את ה-MVC ולשפר את התשתיות שתבנו. ממליץ בחום להוריד את הקוד של MVC מהאתר של CodePlex ולעבור עליו.