解读ASP.NET 5 & MVC6系列教程(11):Routing路由(4)

基于Attribute的Routing功能一直是MVC所期待的功能,在Web API已经通过RoutePrefix(Controller上使用)和Route(Action上使用)来实现了。该特性在MVC 6中进行了重写和增强,并且由于MVC和Web API合二而一了,所以在这两种Controller上都可以使用该特性。

举例来说:

[Route("bookhome")] public class HomeController : Controller { public IActionResult Index() { return View(); } [Route("about")] public IActionResult About() { ViewBag.Message = "Your application description page."; return View(); } [Route("contactus")] public IActionResult Contact() { ViewBag.Message = "Your contact page."; return View(); } }

在上述Controller上定义一个bookhome前缀,并且在About和Contact上又分别定义了action名称,所以上述3个Action的访问地址则是如下这种形式:

/bookhome /bookhome/about /bookhome/contactus

在这里,我们需要注意,Controller和Action使用的Attribute都是Route,同时,在这些路由模板字符串中,依然可以使用内联参数,比如,我们可以定义类似这样的路由:

[Route("products/{productId:int}")]

Controller和Action标记位

另外,针对Route的模板字符串,不仅支持内联参数,还支持Controller和Action的标记位,即不用写死该Controller或Action的名称,使用一个[controller]或[action]的字符即可表示该Controller或Action的名称。比如,我们可以在Controller上定义这样的一个路由(Action上什么都不定义):

[Route("book/[controller]/[action]")]

这样访问首页的地址就变成了:/book/Home/Index。

Web API的等价Route定义

在Web API中,我们一般还要定义GET、POST这样的请求方式,为了方便,新版的HTTPGET等一系列方法都集成了Route功能,直接在构造函数传入Route模板即可,示例如下:

[HttpGet("products/{productId:int}")]

上述Route的定义,即表明,既要符合products/{productId:int}的路由规则,又要是GET请求。

其实HTTPGET这一系列Attribute也可以在普通的MVC Controller上使用,因为在MVC6中,MVC Controller和Web API Controller本身就是同一个东西,只不过MVC的返回类型都是IActionResult而已。Route定义,不仅仅支持GET请求,还支持POST等其它类型的请求,即不限制请求方式。在HttpXXX系列特性中,也是支持内联参数和[controller]、[action]标记位的,大可放心使用。目前可用的特性类有:HttpGet、HttpPost、HttpPut、HttpDelete、HttpPatch。

非要重要Route定义规则

基于Attribute的Route定义很方便,但也很危险,具体规则和危险性如下。

规则1:Controller上定义了Route特性很危险

一旦在Controller上定义了Route特性,该Controller下的所有路由规则都不受其它规则控制了,比如,如果你定义了类似这样的

[Route("book")] public class HomeController : Controller { public IActionResult Index() { return View(); } public IActionResult About() { ViewBag.Message = "Your application description page."; return View(); } }

那么,上述2个Action你都再也没办法访问了,因为默认的action的名称根本就不会起作用,即/book/index和/book/about这两个路径无法路由到对应的Action方法上。而且/book也访问不了,因为有两个以上的Action,系统无法定位到其中一个Action上。

所以要让上述Action能访问,必须要在其中一个Action上定义再Route,例如:

[Route("book")] public class HomeController : Controller { public IActionResult Index() { return View(); } [Route("about")] public IActionResult About() { ViewBag.Message = "Your application description page."; return View(); } }

这样,就可以通过/book/about来访问About方法了,而访问/book则可以访问默认的index方法了,因为该index方法是默认唯一一个没有定义路由的方法,所以他就是/book路由规则的默认Action。如果,有3个Action的话,则必须要至少给两个Action定义Route,示例如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wjysgd.html