ASP.NET MVC三個重要的描述物件
ASP.NET MVC應用的請求都是針對某個Controller的某個Action方法,所以對請求的處理最終體現在對目標Action方法的執行。而Action方法具有相應的引數,所以在方法執行之前必須根據相應的規則從請求中提取相應的資料並將其轉換為Action方法引數列表,我們將這個過程稱為Model繫結。在ASP.NET MVC應用程式設計介面中,Action方法某個引數的後設資料透過ParameterDescriptor表示,而兩個相關的型別ControllerDescriptor和ActionDescriptor則用於描述Controller和Action方法。[本文已經同步到《How ASP.NET MVC Works?》中]
一、ControllerDescriptor
ControllerDescriptor包含了用於描述某個Controller的後設資料資訊。如下面的程式碼片斷所示,ControllerDescriptor具有三個屬性,其中ControllerName和ControllerType分別表示Controller的名稱和型別,前者來源於路由資訊;字串型別的UniqueId表示ControllerDescriptor的唯一標識,該標識由自身的型別、Controller的型別以及Controller的名稱三者派生。
1: public abstract class ControllerDescriptor : ICustomAttributeProvider
2: {
3: public virtual object[] GetCustomAttributes(bool inherit);
4: public virtual object[] GetCustomAttributes(Type attributeType, bool inherit);
5: public virtual bool IsDefined(Type attributeType, bool inherit);
6: public virtual IEnumerableGetFilterAttributes(bool useCache);
7:
8: public abstract ActionDescriptor FindAction(ControllerContext controllerContext, string actionName);
9: public abstract ActionDescriptor[] GetCanonicalActions();
10:
11: public virtual string ControllerName { get; }
12: public abstract Type ControllerType { get; }
13: public virtual string UniqueId { get; }
14: }
15:
16: public interface ICustomAttributeProvider
17: {
18: object[] GetCustomAttributes(bool inherit);
19: object[] GetCustomAttributes(Type attributeType, bool inherit);
20: bool IsDefined(Type attributeType, bool inherit);
21: }
ControllerDescriptor實現了ICustomAttributeProvider介面,意味著我們可以透過呼叫GetCustomAttributes和GetCustomAttributes方法獲取應用在Controller型別上的所有自定義特性或者給定型別的特性,也可以呼叫IsDefined方法判斷指定的自定義特性型別是否應用在對應的Controller型別上。
另一個方法GetFilterAttributes用於獲取應用在Controller上的所有篩選器特性(繼承自抽象類FilterAttribute)。篩選器是一種基於AOP的設計,它使我們可以一些基於橫切關注點相關邏輯的執行動態的注入到Action方法的執行前後,我們會在“Action方法的執行”中對篩選器進行詳細地介紹。
ControllerDescriptor的FindAction方法根據指定的Controller上下文和名稱得到相應的Action方法,返回的是用於描述Action方法的ActionDescriptor物件。而GetCanonicalActions得到當前Controller的所有Action方法,返回型別為ActionDescriptor陣列。
二、ReflectedControllerDescriptor
在ASP.NET MVC應用程式設計介面中定義了抽象類ControllerDescriptor的唯一繼承型別ReflectedControllerDescriptor。顧名思義,ReflectedControllerDescriptor透過反射的機制解析用於描述Controller的後設資料。如下面的程式碼片斷所示,表示Controller型別的ControllerType屬性在建構函式中指定。ReflectedControllerDescriptor透過反射的方式獲取應用在Controller型別上的相關特性以提供針對ICustomAttributeProvider介面的實現。
1: public class ReflectedControllerDescriptor : ControllerDescriptor
2: {
3: public ReflectedControllerDescriptor(Type controllerType);
4:
5: public override object[] GetCustomAttributes(bool inherit);
6: public override object[] GetCustomAttributes(Type attributeType, bool inherit);
7: public override IEnumerableGetFilterAttributes(bool useCache);
8: public override bool IsDefined(Type attributeType, bool inherit);
9:
10: public override ActionDescriptor FindAction( ControllerContext controllerContext, string actionName);
11: public override ActionDescriptor[] GetCanonicalActions();
12:
13: public sealed override Type ControllerType { get; }
14: }
對於GetCanonicalActions方法返回的用於描述所有Action方法的ActionDescriptor陣列,僅限於公有例項方法,但是從.Controller中繼承下來的方法除外。當我們呼叫FindAction方法根據Action名稱獲取對應ActionDescriptor的時候,在默情況下會將方法名稱視為Action名稱進行匹配。如果方法上應用了具有如下定義的ActionNameSelectorAttribute特性,會傳入相應的引數呼叫其IsValidName方法,如果該返回值為True,目標方法會被認為是匹配的Action方法。
1: [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
2: public abstract class ActionNameSelectorAttribute : Attribute
3: {
4: public abstract bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo);
5: }
顧名思義,抽象類ActionNameSelectorAttribute是一個用於輔助選擇目標Action方法的特性,在ASP.NET MVC應用程式設計介面中具有一個型別為ActionNameAttribute的繼承者。ActionNameAttribute特性應用於Action方法透過引數值指定一個Action別名,在實現的IsValidName方法中會比較指定的別名是否和當前的Action名稱相匹配。如果具有不同 的Action選擇規則,我們也可以透過自定義ActionNameSelectorAttribute特性的方式來實現。
1: [AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=true)]
2: public sealed class ActionNameAttribute : ActionNameSelectorAttribute
3: {
4: public ActionNameAttribute(string name);
5: public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo);
6: public string Name { get; }
7: }
對於FindAction方法,如果找不到與指定Action名稱的Action方法,則返回Null,而最終會導致一個狀態碼為404的HttpException異常的丟擲;如果具有多個匹配的Action方法,則直接丟擲AmbiguousMatchException異常。也就是說對於每一次請求,要求有且只有一個匹配的Action方法。
三、ReflectedAsyncControllerDescriptor
ReflectedAsyncControllerDescriptor型別為ReflectedControllerDescriptor的非同步版本。如下面的程式碼片斷所示,ReflectedAsyncControllerDescriptor和ReflectedControllerDescriptor具有類似的成員定義,實際上除了FindAction和GetCanonicalActions兩個方法,其他方法的實現邏輯(即對應用在Controller型別上的相關特性的解析)與ReflectedControllerDescriptor完全一致。
1: public class ReflectedAsyncControllerDescriptor : ControllerDescriptor
2: {
3: public ReflectedAsyncControllerDescriptor(Type controllerType);
4:
5: public override object[] GetCustomAttributes(bool inherit);
6: public override object[] GetCustomAttributes(Type attributeType, bool inherit);
7: public override IEnumerableGetFilterAttributes( bool useCache);
8: public override bool IsDefined(Type attributeType, bool inherit);
9:
10: public override ActionDescriptor FindAction( ControllerContext controllerContext, string actionName);
11: public override ActionDescriptor[] GetCanonicalActions();
12:
13: public sealed override Type ControllerType { get; }
14: }
ReflectedAsyncControllerDescriptor的GetCanonicalActions總是返回一個空的ActionDescriptor陣列。對於繼承自AsyncController的Controller型別,一個非同步Action方法由兩個匹配的方法({ActionName}Async和{ActionName}Completed)構成,ReflectedAsyncControllerDescriptor在根據指定的Action名稱對方法成員進行匹配的時候會自動忽略掉方法名稱的“Async”和“Completed”字尾。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/200/viewspace-2810174/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- ASP.NET + MVC5 入門完整教程三 (上) --- 第一個 MVC 專案_lingshuangcanxue-CSDN 部落格_asp.net mvcASP.NETMVCGC
- 建立一個ASP.NET MVC 5專案ASP.NETMVC
- ASP.NET MVC路由ASP.NETMVC路由
- 【備忘】ASP.NET MVC 5 升級到 ASP.NET Core MVC 的部分變化ASP.NETMVC
- ASP.NET MVC下使用AngularJs語言(三):ng-optionsASP.NETMVCAngularJS
- ASP.NET MVC 反射例子ASP.NETMVC反射
- 通過呼叫多個操作建立 ASP.NET MVC 檢視ASP.NETMVC
- ASP.Net MVC過濾器ASP.NETMVC過濾器
- ASP.NET MVC – 安全簡介ASP.NETMVC
- ASP.NET MVC – 模型簡介ASP.NETMVC模型
- 將”ListControl”引入ASP.NET MVCASP.NETMVC
- asp.net core mvc 分頁ASP.NETMVC
- CSS三個非常重要的特性分享!CSS
- 自己寫一個mvc框架吧(三)MVC框架
- Spring MVC 獲取三個域(request請求域,session 會話域,application 應用域)物件的方式SpringMVCSession會話APP物件
- ASP.NET Core MVC 之模型(Model)ASP.NETMVC模型
- ASP.NET MVC – 檢視簡介ASP.NETMVC
- ASP.NET Core MVC 之路由(Routing)ASP.NETMVC路由
- ASP.NET MVC Razor檢視引擎ASP.NETMVC
- ASP.NET MVC技能體系圖ASP.NETMVC
- asp.net mvc 錯誤頁面ASP.NETMVC
- ASP.NET MVC獲取上傳的路徑ASP.NETMVC
- Asp.net MVC 4 模型的資料註釋ASP.NETMVC模型
- ASP.NET MVC隨想錄——鋒利的KATANAASP.NETMVC
- ASP.NET Core MVC 之佈局(Layout)ASP.NETMVC
- ASP.NET Core MVC 之檢視(Views)ASP.NETMVCView
- ASP.NET MVC – 控制器簡介ASP.NETMVC
- 微信掃碼支付(Asp.Net MVC)ASP.NETMVC
- ASP.NET MVC 匯入Excel檔案ASP.NETMVCExcel
- 從 MVC 到使用 ASP.NET Core 6.0 的最小 APIMVCASP.NETAPI
- Asp.net Core MVC 程式的國際化處理ASP.NETMVC
- Kubernetes中分散式儲存Rook-Ceph的使用:一個ASP.NET Core MVC的案例分散式ASP.NETMVC
- 清晰的工作描述對職場性別平等至關重要
- Linux磁碟管理,這三個命令很重要!Linux
- Android最全螢幕適配的幾個重要概念(三)Android
- 【ASP.NET Core】動態對映MVC路由ASP.NETMVC路由
- ASP.NET CORE MVC用時分析工具MiniProfilerASP.NETMVC
- ASP.NET MVC+LayUI視訊上傳ASP.NETMVCUI