http://www.cnblogs.com/zeusro/p/RouteConfig.html
路由的核心類型基本定義於System.Web.dll中,路由機制同樣可應用與Web Forms,實現請求地址和物理文件的分離。
web form中使用路由器的示例
路由配置
protected void Application_Start(object sender, EventArgs e)
{
var defaults = new RouteValueDictionary { { "name", "*" }, { "id", "*" } };
//將物理文件路徑映射到一個路由模版上
RouteTable.Routes.MapPageRoute("", "employees/{name}/{id}","~/default.aspx",true,defaults);
}
頁面
public partial class Default : System.Web.UI.Page
{
protected string EmployeeId;
protected string EmployeeName;
protected void Page_Load(object sender, EventArgs e)
{
EmployeeId = this.RouteData.Values["id"] as string;
EmployeeName = this.RouteData.Values["name"] as string;
}
}
<form id="form1" runat="server">
<div>
EmployeeId:<%=EmployeeId %>
<br/>
EmployeeName:<%=EmployeeName %>
</div>
</form>
測試
訪問地址:http://localhost:65042/Default.aspx

訪問地址:http://localhost:65042/employees

訪問地址:http://localhost:65042/employees/張飛

訪問地址:http://localhost:65042/employees/張飛/001

訪問地址:http://localhost:65042/employees/張飛/001/sdfs
404報錯
ASP.NET路由注冊
RouteTable.Routes.MapPageRoute(
routeName : "myRoute",
routeUrl : "dirtest/{name}/{id}",
physicalFile : "~/default.aspx",
checkPhysicalUrlAccess : true,
defaults : new RouteValueDictionary { { "name", "*" }, { "id", "010" } },
constraints : new RouteValueDictionary { { "id", @"0\d{2,3}" }, { "httpMethod", new HttpMethodConstraint("GET") } },
dataTokens : new RouteValueDictionary { { "city", "hangzhou" } }
);
另一種注冊方式
Route route = new Route(
url:"dirtest/{name}/{id}",
defaults: new RouteValueDictionary { { "name", "*" }, { "id", "010" } },
constraints: new RouteValueDictionary { { "id", @"0\d{2,3}" }, { "httpMethod", new HttpMethodConstraint("GET") } },
dataTokens: new RouteValueDictionary { { "city", "hangzhou" } },
routeHandler:new PageRouteHandler("~/default.aspx",true)
);
RouteTable.Routes.Add("myRoute",route);
直接請求現存的物理文件
借用路由可以采用一個與路徑無關的URL訪問某個物理文件,但如果就是希望以物理地址的方式訪問對應的物理文件時。
RouteBase定義了一個布爾類型的屬性RouteExistingFiles,表示是否對現有物理文件實施路由。
注冊路由忽略地址
如果設置為RouteTable.Routes.RouteExistingFiles = true; 路由系統會對所有請求實施路由,但這同樣會帶來一些問題。
例如如果應用運行在集成模式下,則靜態資源的請求也會進入ASP.NET管道,於是針對靜態文件的請求也可能會被重定向。
通過Ignore方法來添加例外,Ignore方法的調用必需放在路由注冊之前。
RouteTable.Routes.RouteExistingFiles = true;
RouteTable.Routes.Ignore("content/{filename}.css/{*pathInfo}");
默認值
defaults 為路由模版中的兩個變量指定了默認值。
約束
constraints 可以為變量指定基於正則的約束,也可以指定一個RouteConstraint對象。
路由變量
在Route對象的DataTokens屬性中可添加路由變量
根據路由規則生成URL
通過RouteCollection的GetVirtualPath方法。
RequestContext requestContext = new RequestContext();
requestContext.HttpContext = new HttpContextWrapper(HttpContext.Current);
requestContext.RouteData = this.RouteData;
RouteValueDictionary values = new RouteValueDictionary { { "name", "劉備" }, { "id", "013" } };
Response.Write("<br>");
Response.Write(RouteTable.Routes.GetVirtualPath(requestContext, values).VirtualPath);
Response.Write("<br>");
Response.Write(RouteTable.Routes.GetVirtualPath(requestContext, null).VirtualPath);
Response.Write("<br>");
Response.Write(RouteTable.Routes.GetVirtualPath(null, null).VirtualPath);

MVC路由
MapPageRoute方法和Ignore方法的調用可以完成針對某個物理文件的路由。返回的RouteData中的RouteHander屬性會返回一個PageRouteHandler對象。PageRouteHandler對象最終會創建一個針對映射.aspx文件的Page對象來處理請求。
而MVC為RouteCollection增加了一系列擴展方法,定義在System.Web.Mvc.RouteCollectionExtensions中。新增了兩組方法 MapRoute和IgnoreRoute。
MapRoute方法的幾個重載中都不能直接操作DataTokens,但可以往DataTokens中添加命名空間列表。當存在多個同名的Controller類型時,在激活Controller類型時會因為無法確定Controller的類型而拋出異常。DataTokens中得Namespaces成員用於設置優先級。
MapRoute方法返回的RouteData中的RouteHander屬性會返回一個MvcRouteHandler對象。
UrlParameter.Optional
將變量的默認值設置為UrlParameter.Optional,則只有請求URL中真正包含具體變量值的情況下生成的RouteData的Values屬性中才會包含相應的路由變量。
基於Area的路由映射
通過Area可以從功能上將應用划分為幾個較小的單元。每個Area相當於一個獨立的子系統。它們具有一套包含Models,Views,Controllers在內的目錄結構和配置文件。每個路由結構一般也會具有各自獨立的路由規則,通過AreaRegistration類型進行注冊。
protected void Application_Start()
{
//針對所有Area的注冊
AreaRegistration.RegisterAllAreas();
}
RegisterAllAreas方法執行時,所有被當前Web應用直接或間接引用的程序集都會被加載(如果尚未被加載),ASP.NET MVC會從中找到所有繼承自AreaRegistration的類型,並通過反射創建相應的對象。針對每個被創建出來的AreaRegistration對象,一個作為Area注冊上下文的AreaRegistrationContext對象會被創建出來,作為參數調用AreaRegistration對象的RegisterArea方法對相應的Area的路由進行注冊。
AreaRegistrationContext對象的State屬性的值來自AreaRegistration.RegisterAllAreas方法指定的參數state。
public class adminAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "admin";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
name: "admin_default",
url: "admin/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
當存在相同的Controller類型名時,如域Area中也定義了一個Home控制器,則全局路由器會因為重復匹配而報錯。需要對其設置優先匹配的命名空間。
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new string[] { "WebApplication1.Controllers.*" }
);
}
AreaRegistration注冊的路由對象
由AreaRegistration注冊的路由對象生成的RouteData的不同之處主要表現在DataTokens屬性上,默認多出兩個變量:
- area: 標記Area的名稱
- UseNamespaceFallback: 當MapRoute方法顯式地指定了命名空間或者對應的AreaRegistration定義在某個命名空間下,則UseNamespaceFallback為False,反之則被設置為True。如果MapRoute方法顯式地指定了命名空間,則AreaRegistration類型所在的命名空間也會被忽略。
MVC中生成URL的快捷方式
MVC則定義了兩個幫助類: HtmlHelper 和UrlHelper,通過調用它們的ActionLink/RouteLink 和Action/RouteUrl方法生成Url。從本質上講,最終依賴於RouteCollection對象的GetVirtualPathData方法。
Action、ActionLink
UrlHelper.Action(……)返回相對地址或絕對地址,HtmlHelper.ActionLink(……) 則不僅僅返回一個Url,而是生成一個鏈接(<a>……</a>)。
調用的是GetVirtualPathData(RequestContext requestContext,RouteValueDictionary values)方法。 也就是使用路由表中第一個匹配的Route對象來生成URL或者鏈接。
RouteUrl、RouteLink
UrlHelper.RouteUrl(……)方法和HtmlHelper.RouteLink (……) 方法則可以針對注冊的某個具體的Route對象來生成URL或者鏈接。也即是調用GetVirtualPathData(RequestContext requestContext,string name,RouteValueDictionary values)方法。
特性路由
特性路由是對現有路由系統的擴展,提供了一種針對某個具體Controller類型或Action方法的路由注冊方式。從而可以對路由規則進行細粒度的設計。
特性路由(Attribute Route)就是利用標注在Controller類型或Action方法上的特性來提供路由規則的路由注冊方式。
注冊
默認情況下特性路由功能是關閉的,需要調用RouteCollection的擴展方法MapMvcAttributeRoutes來開啟。
這個方法的調用要放在路由注冊之前。
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
RouteTable.Routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
public class MoviesController : Controller
{
// GET: Movies
public ActionResult Index()
{
return View();
}
[HttpGet]
[Route("movies/{id}")]
public ActionResult GetMoviesById(string id)
{
ViewBag.id = id;
return View();
}
[HttpGet]
[Route("movies/starring/{starring}")]
[Route("movies/starring/{starring}/{genre}")]
[Route("movies/director/{director}/{genre}")]
public ActionResult FindMovies(string starring, string director, string genre)
{
ViewBag.starring = starring;
ViewBag.director = director;
ViewBag.genre = genre;
return View();
}
}
默認情況下使用特性類型RouteAttribute,它實現了接口IRouteInfoProvider。

當使用RouteAttribute時,需要提供一個路由模版來對Template這個只讀屬性進行初始化。而如果需要用這個路由特性注冊的路由對象來生成URL,還需要為它提供一個Name,以便可以從路由表中把它提取出來。
為特性路由的變量添加約束
路由變量基本都會直接綁定到目標Action方法相應的參數上,由於這些變量值在請求URL中以字符串的形式體現,所以被綁定參數必需支持源自字符串的類型轉換。
為了確保參數綁定的正常進行,需要對路由變量在數據類型上進行約束。這些約束可以直接以內聯的形式定義在路由模版里。
[HttpGet]
[Route("movies/{id:range(20,50)}")]
public ActionResult GetMoviesById(int id)
對於路由系統來說,約束通過RouteContraint對象來表示,所有RouteContraint類型均實現了IRouteContraint接口。
特性路由的這些以內聯形式定義在路由模版中的約束,它們的約束類型也是實現了IRouteContraint接口。
| 約束 | 描述 | 用法 | 類型 |
| bool | 類型匹配 (布爾類型) | {x:bool} | BoolRouteContraint |
| datetime | 類型匹配 (DateTime類型) | {x:datetime} | DateTimeRouteContraint |
| decimal | 類型匹配 (Decimal類型) | {x:decimal} | DecimalRouteContraint |
| double | 類型匹配 (Double類型) | {x:double} | DoubleRouteContraint |
| float | 類型匹配 (Float類型) | {x:float} | FloatRouteContraint |
| guid | 類型匹配 (Guid類型) | {x:guid} | GuidRouteContraint |
| int | 類型匹配 (32位整數) | {x:int} | IntRouteContraint |
| long | 類型匹配 (64位整數) | {x:long} | LongRouteContraint |
| alpha | 字符組成(必須有拉丁字母組成) | {x:alpha} | AlphaRouteContraint |
| regex | 字符組成(必須與指定的正則匹配) | {x:regex(^\d{3}-\d{3}-\d{4}$)} | RegexRouteContraint |
| max | 值范圍(小於或等於指定的最大值) | {x:max(20)} | MaxRouteContraint |
| min | 值范圍(大於或等於指定的最小值) | {x:max(20)} | MinRouteContraint |
| range | 值范圍(在指定的最大值和最小值之間) | {x:range(20,50)} | RangeRouteContraint |
| maxlength | 字符串長度(小於或等於指定的最大長度) | {x:maxlength(20)} | MaxLengthRouteContraint |
| minlength | 字符串長度(大於或等於指定的最小長度) | {x:minlength(20)} | MinlengthRouteContraint |
| length | 字符串長度(等於指定的長度或者在指定的范圍內) | {x:length(6)} | LengthRouteContraint |
為路由變量設置缺省值
1.將對應的參數定義為可缺省參數,路由模版里使用“?”
[HttpGet]
[Route("movies/language/{language?}")]
public ActionResult GetMoviesByLanguage(string language = "en")
{
return View();
}
2.將默認值定義在路由模版中
[HttpGet]
[Route("movies/language/{language=en}")]
public ActionResult GetMoviesByLanguage(string language)
{
return View();
}
設置模版前綴
使用RoutePrefixAttribute類型的特性,它只有一個只讀屬性Prefix,表示目標Controller所有Action方法共享的URL前綴。這個屬性只能應用在Controller類型上,且只能有一個。

[RoutePrefix("movies")]
public class MoviesController : Controller
{
[HttpGet]
[Route("{id:range(20,50)}")]
public ActionResult GetMoviesById(int id)
{
ViewBag.id = id;
return View();
}
[HttpGet]
[Route("starring/{starring}")]
[Route("starring/{starring}/{genre}")]
[Route("director/{director}/{genre}")]
public ActionResult FindMovies(string starring, string director, string genre)
{
ViewBag.starring = starring;
ViewBag.director = director;
ViewBag.genre = genre;
return View();
}
[HttpGet]
[Route("~/actors/{criteria}")] //使用“~”為前綴,屏蔽掉Controller類型上的前綴“movies”
public ActionResult FindActors(string criteria)
{
return View();
}
}
設置Area名
使用RouteAreaAttribute類型的特性,它由兩個屬性AreaName和AreaPrefix,默認情況下使用AreaName做模版前綴,如果希望具有一個不同於Area名稱的前綴,則要通過設置AreaPrefix屬性來實現。
如果沒有使用字符“~”前綴,特性路由的完整格式為{AreaPrefix}/{RoutePrefix}/{Template} 或者{AreaName}/{RoutePrefix}/{Template} 。

[RouteArea("MoviesArea")]//[RouteArea()]
[RoutePrefix("movies")]
public class MoviesController : Controller
{
[HttpGet]
[Route("{id:range(20,50)}")]
public ActionResult GetMoviesById(int id)
{
ViewBag.id = id;
return View();
}
[HttpGet]
[Route("starring/{starring}")]
[Route("starring/{starring}/{genre}")]
[Route("director/{director}/{genre}")]
public ActionResult FindMovies(string starring, string director, string genre)
{
ViewBag.starring = starring;
ViewBag.director = director;
ViewBag.genre = genre;
return View();
}
[HttpGet]
[Route("~/admin/actors/{criteria}")] //使用“~”為前綴,屏蔽掉Controller類型上的前綴“movies”
public ActionResult FindActors(string criteria)
{
return View();
}
}
直接應用到Controller上的RouteAttribute
[RouteArea("vedio")]
[RoutePrefix("movies")]
[Route("{action}/{id}", Name = "FindMovies")]
public class MoviesController : Controller
{
public ActionResult Index(string id)
{
throw new NotImplementedException();
}
}
自定義約束
內聯表達式約束的解析
約束是以內聯表達式的形式定義在路由模版里的,ASP.NET MVC通過一個實現IInlineConstraintResolver接口的對象來完成約束從字符串表達式到RouteConstraint對象之間的轉換。
系統提供的這個解析類型是DefaultInlineConstraintResolver。
public class MyInlineConstraintResolver : IInlineConstraintResolver
{
public IDictionary<string, Type> ConstraintMap { get; private set; }
public MyInlineConstraintResolver()
{
this.ConstraintMap = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
this.ConstraintMap.Add("bool", typeof(BoolRouteConstraint));
this.ConstraintMap.Add("datetime", typeof(DateTimeRouteConstraint));
this.ConstraintMap.Add("decimal", typeof(DecimalRouteConstraint));
this.ConstraintMap.Add("double", typeof(DoubleRouteConstraint));
this.ConstraintMap.Add("float", typeof(FloatRouteConstraint));
this.ConstraintMap.Add("guid", typeof(GuidRouteConstraint));
this.ConstraintMap.Add("int", typeof(IntRouteConstraint));
this.ConstraintMap.Add("long", typeof(LongRouteConstraint));
this.ConstraintMap.Add("minlength",typeof(MinLengthRouteConstraint));
this.ConstraintMap.Add("maxlength",typeof(MaxLengthRouteConstraint));
this.ConstraintMap.Add("length", typeof(LengthRouteConstraint));
this.ConstraintMap.Add("min", typeof(MinRouteConstraint));
this.ConstraintMap.Add("max", typeof(MaxRouteConstraint));
this.ConstraintMap.Add("range", typeof(RangeRouteConstraint));
this.ConstraintMap.Add("alpha", typeof(AlphaRouteConstraint));
this.ConstraintMap.Add("regex", typeof(RegexRouteConstraint));
}
public IRouteConstraint ResolveConstraint(string inlineConstraint)
{
string[] split = inlineConstraint.Split('(');
string type = split[0];
string argumentList = split.Length > 1 ? split[1].Trim().TrimEnd(')') : "";
Type constraintType;
if (this.ConstraintMap.TryGetValue(type, out constraintType))
{
split = string.IsNullOrEmpty(argumentList)? new string[0] : argumentList.Split(',');
ConstructorInfo[] constructors =(from c in constraintType.GetConstructors()
where c.GetParameters().Count() == split.Length
select c).ToArray();
if (constructors.Length != 1)
{
throw new InvalidOperationException("找不到與指定參數匹配的構造函數");
}
ConstructorInfo constructor = constructors[0];
ParameterInfo[] parameters = constructor.GetParameters();
object[] arguments = new object[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
{
arguments[i] = Convert.ChangeType(split[i],parameters[i].ParameterType);
}
return (IRouteConstraint)constructor.Invoke(arguments);
}
return null;
}
}
static void Main(string[] args)
{
string[] inlineConstraints = new string[]{
"bool","datetime", "decimal","double","float","guid","int",
"long","alpha", @"regex(^\d{3}-\d{7}$)","max(50)","min(10)","range(10,50)","maxlength(50)","minlength(10)","length(10,50)"};
MyInlineConstraintResolver constraintResolver = new MyInlineConstraintResolver();
IDictionary<string, IRouteConstraint> constraints = inlineConstraints.ToDictionary(inlineConstraint => inlineConstraint, inlineConstraint => constraintResolver.ResolveConstraint(inlineConstraint));
Console.WriteLine("{0,-24}{1}", "Expression", "RouteConstraint");
foreach (var item in constraints)
{
Console.WriteLine("{0,-24}{1}", item.Key,
item.Value.GetType().Name);
}
Console.ReadKey();
}
自定義針對Culture的約束
約束類型的定義
public class CultureRouteConstraint : IRouteConstraint
{
private static IList<string> allCultures;
static CultureRouteConstraint()
{
allCultures = CultureInfo.GetCultures(CultureTypes.AllCultures).Select(culture => culture.Name).ToList();
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
object culture;
if (values.TryGetValue(parameterName, out culture))
{
return allCultures.Any(c => string.Compare(c, culture.ToString(),true) == 0);
}
return false;
}
}
應用自定義的約束
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
DefaultInlineConstraintResolver constraintResolver = new DefaultInlineConstraintResolver();
constraintResolver.ConstraintMap.Add("culture", typeof(CultureRouteConstraint));
routes.MapMvcAttributeRoutes(constraintResolver);
//其他操作
}
使用
public class ResourcesController : Controller
{
[Route("resources/{name}/{culture:culture=zh-cn}")]
public string GetString(string name, string culture)
{
CultureInfo currentUICulture = CultureInfo.CurrentUICulture;
CultureInfo currentCulture = CultureInfo.CurrentCulture;
try
{
Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = new CultureInfo(culture);
return Resources.ResourceManager.GetString(name.ToLower());
}
finally
{
Thread.CurrentThread.CurrentUICulture = currentUICulture;
Thread.CurrentThread.CurrentCulture = currentCulture;
}
}
}
特性路由注冊的路由對象
路由對象的創建
特性路由主要涉及3種類型的特性:
- 以RouteAttribute為代表的RouteInfoProvider特性
- 設置路由模版前綴的RoutePrefixAttribute特性
- 設置所在Area名稱的RouteAreaAttribute特性
針對應用到Controller和Action上的這些特性,ASP.NET MVC的路由系統最終會為之創建相應的路由對象(VS調試中發現RouteTable細節上有了一些變化,下面的部分描述不對了)。
- 特性路由的路由模版經過格式化(拼接前綴、去除約束、默認值、“?”等)后轉換為路由對象的模版。
- 路由模版中的變量約束及[HttpGet] 被解析后添加到路由對象的Contraint屬性表示的約束集合中。
- 路由模版中的變量默認值及目標Controller和Action名稱保存到Defaults屬性中。
- 如果RouteAttribute是加在Action上的,則DataTokens屬性中具有一個名為“TargetActionMethod”的成員,它的值代表目標Action方法的MethodInfo對象。
- 如果RouteAttribute是加在Controller上的,則DataTokens屬性中具有一個名為“MS_DirectControllerRoute”的成員,它的值為描述目標Controller類型的ControllerDescriptor對象。
- RouteAreaAttribute特性除了改變最終的路由模版外,還會在DataTokens屬性中額外添加兩個成員:“Namespaces”、“UseNamespaceFallback”。
當我們調用MapMvcAttributeRoutes方法時,ASP.NET MVC 會提取注冊到當前DependencyResolver上的用於激活目標Controllerde的ControllerFactory,如果沒有沒有對ControllerFactory進行顯式注冊或者顯式注冊的並不是一個DefaultControllerFactory對象,它會創建一個DefaultControllerFactory對象。這個DefaultControllerFactory對象會解析出所有合法有效的Controller類型,並對它們實施緩存。ASP.NET MVC 利用它得到所有合法有效的Controller類型后,針對每個類型得到對應的ControllerDescriptor對象(默認通過AsyncControllerActionInvoker對象獲得,后者會緩存Controller類型與對應的ControllerDescriptor之間的映射關系以避免ControllerDescriptor的頻繁創建)。
在得到所有Controller類型的ControllerDescriptor對象后,會遍歷描述Action方法的每個ActionDescriptor對象,並利用它提取應用在對應Action方法上的RouteInfoProvider特性。利用這個RouteInfoProvider特性及所在Controller類型上應用的RoutePrefixAttribute和RouteAreaAttribute特性提供的路由規則創建最終的Route對象。這個對象最終被添加到全局路由表中。
被特性路由標記的Controller、Action在特性路由功能開啟后, 將不能再通過普通路由對象的Url模版來訪問
public class HomeController : Controller
{
[Route("movies")] //不能再通過home/about訪問
public ActionResult About()
{
return View();
}
}
Controller的激活和Action方法的選擇
因為路由對象的屬性DataTokens中的成員在路由解析匹配成功時,會直接拷貝到解析生成的RouteData的DataTokens屬性中。
DefaultControllerFactory在激活目標Controller實例前必須先解析出目標Controller的類型。在正常情況下,它會根據路由解析得到的Controller名稱來匹配。但是如果它能夠從RouteData中提取到描述目標Controller的ControllerDescriptor或者描述目標Action方法的MethodInfo對象,就可以根據它們直接得到Controller類型。
ControllerDescriptor內的FindAction方法可以根據提供的ControllerContext從候選的Action方法中選擇與當前請求匹配度最高的那一個。對於默認使用的ReflectedControllerDescriptor來說,當FindAction方法被執行時,它會先從提供的ControllerContext中提取RouteData對象,如果能夠從中獲取描述目標Action方法的MethodInfo對象,返回得ActionDescriptor對象會直接依據此MethodInfo對象來創建。
public interface IControllerFactory
{
IController CreateController(RequestContext requestContext, string controllerName);
SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName);
void ReleaseController(IController controller);
}
public abstract class ControllerDescriptor : ICustomAttributeProvider, IUniquelyIdentifiable
{
protected ControllerDescriptor();
public virtual string ControllerName { get; }
public abstract Type ControllerType { get; }
public virtual string UniqueId { get; }
public abstract ActionDescriptor FindAction(ControllerContext controllerContext, string actionName);
public abstract ActionDescriptor[] GetCanonicalActions();
public virtual object[] GetCustomAttributes(bool inherit);
public virtual object[] GetCustomAttributes(Type attributeType, bool inherit);
public virtual IEnumerable<FilterAttribute> GetFilterAttributes(bool useCache);
public virtual bool IsDefined(Type attributeType, bool inherit);
}
public abstract class ActionDescriptor : ICustomAttributeProvider, IUniquelyIdentifiable
{
protected ActionDescriptor();
public abstract string ActionName { get; }
public abstract ControllerDescriptor ControllerDescriptor { get; }
public virtual string UniqueId { get; }
public abstract object Execute(ControllerContext controllerContext, IDictionary<string, object> parameters);
public virtual object[] GetCustomAttributes(bool inherit);
public virtual object[] GetCustomAttributes(Type attributeType, bool inherit);
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Please call System.Web.Mvc.FilterProviders.Providers.GetFilters() now.", true)]
public virtual FilterInfo GetFilters();
public abstract ParameterDescriptor[] GetParameters();
public virtual ICollection<ActionSelector> GetSelectors();
public virtual bool IsDefined(Type attributeType, bool inherit);
}
