问题

ASP.NET Core 2.0的路由引擎是如何工作的?

答案

创建一个空项目,为Startup类添加MVC服务和请求中间件:

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
} public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMvc(routes =>
{
routes.MapRoute(
name: "goto_one",
template: "one",
defaults: new { controller = "Home", action = "PageOne" }); routes.MapRoute(
name: "goto_two",
template: "two/{id?}",
defaults: new { controller = "Home", action = "PageTwo" }); routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}

创建一个控制器HomeController,来演示常规路由:

public class HomeController : Controller
{
public IActionResult Index()
{
return Content("Home/Index");
} public IActionResult PageOne()
{
return Content("Home/One");
} [HttpGet]
public IActionResult PageTwo()
{
return Content("(GET) Home/Two");
} [HttpPost]
public IActionResult PageTwo(int id)
{
return Content($"(POST) Home/Two: {id}");
}
}

创建一个控制器WorkController,来演示特性路由:

[Route("work")]
public class WorkController : Controller
{
public IActionResult Index()
{
return Content("Work/Index");
} [Route("one")]
public IActionResult PageOne()
{
return Content("Work/One");
} [HttpGet("two")]
public IActionResult PageTwo()
{
return Content("(GET) Work/Two");
} [HttpPost("two/{id?}")]
public IActionResult PageTwo(int id)
{
return Content($"(POST) Work/Two: {id}");
}
}

讨论

ASP.NET Core的路由引擎可以将传入的请求映射到控制器和它们的方法中。这是通过向请求管道中添加路由中间件实现的,具体来说是使用IRouteBuilder将URL规则(模板)映射到一个控制器的方法。

路由模板

路由模板可以使用字面值和标记(标识路由参数)。在匹配一个路由时,字面值会严格匹配URL中的文本,而标记会被替换掉。
为了匹配一个模板,模板中必须包含控制器和方法标记以便定位控制器方法(这是MVC的核心信息)。模板中的其它标记被映射为方法的参数(通过模型绑定实现)。
当添加一个路由映射时,可以为标记提供缺省值。当模板中不包含控制器和方法标记时会很有用。模板也可以包含对应于方法参数的可选标记。
让我们来看一个示例模板:

contact/{controller=Home}/{action=Index}/{id?}

注意如下几点:

  1. 标记包含中大括号中。这里有三个标记,分别是controller,action和id。
  2. 模板中包含一个字面值contact,它会匹配URL中的文本。
  3. 已经为controller(Home)和action(Index)提供了默认值。
  4. 可选标记通过问号来声明。

下面的URL会匹配这个模板:

  • /contact/Home/Index/1: 所有标记都有值。
  • /contact/Home/Index: 忽略了可选标记。
  • /contact/Home: 忽略了action标记,将使用默认值Index。
  • /contact: 忽略了controller和action标记,将分别使用其默认值Home和Index。

常规路由

常规路由为URL路径建立一个约定, 例如给定一个模板:

  1. 第一个标记映射到控制器
  2. 第二个标记映射到方法
  3. 第三个标记映射到可选的方法参数id

你也可以从模板中省略控制器和方法,只要你为它们提供缺省值就行了。比如下面的路由会映射到地址/one,因为通过defaults提供了所需的控制器和方法标记:

routes.MapRoute(
name: "goto_one",
template: "one",
defaults: new { controller = "Home", action = "PageOne" });

注:请将此特定路由添加到通用路由之前,因为路由是按照定义的顺序执行的,一旦某个路由匹配成功,则整个匹配流程就会终结。

由于路由中间件只使用了控制器和方法标记来映射到一个控制器方法,因此同一个控制器中放置多个同名的的方法将会抛出异常。为了解决这个问题,可以使用方法上的IActionConstraint特性(比如HttpGet,HttpPost等特性):

[HttpGet("two")]
public IActionResult PageTwo()
{
return Content("(GET) Work/Two");
} [HttpPost("two/{id?}")]
public IActionResult PageTwo(int id)
{
return Content($"(POST) Work/Two: {id}");
}

====start by sanshi=========================

为了观察控制器中同名方法出现的异常,我们首先需要修改Configure()方法,添加开发时异常处理中间件:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseMvc(routes => ....);
}

修改HomeController:

public IActionResult PageTwo()
{
return Content("(GET) Home/Two");
}
public IActionResult PageTwo(int id)
{
return Content($"(POST) Home/Two: {id}");
}

看似很正常的重载函数,但是放到控制器中会抛出异常。

在浏览器地址栏敲入:http://localhost:65415/Home/PageTwo,观看到异常页面:

  

====end by sanshi=========================  

特性路由

特性路由通过直接为控制器和方法提供路由模板来实现。
我们可以使用[Route]或者[HttpGet](或者其他动词)特性来指定模板。这些模板可以包含字面值和标记(不能包含控制器和方法标记)。
运行时,控制器的特性模板和方法的特性模板会被合并到一起,比如,在WorkController中,PageOne方法可以通过/work/one访问:

[Route("work")]
public class WorkController : Controller
{
[Route("one")]
public IActionResult PageOne()
{
return Content("Work/One");
}
}

源代码下载

原文:https://tahirnaushad.com/2017/08/20/asp-net-core-mvc-routing/

[译]ASP.NET Core 2.0 路由引擎的更多相关文章

  1. [译]ASP.NET Core 2.0 路由引擎之网址生成

    问题 如何在ASP.NET Core 2.0中由路由引擎来生成网址? 答案 新建一个空项目,修改Startup.cs文件,添加MVC服务和中间件: public void ConfigureServi ...

  2. [译]ASP.NET Core 2.0 视图引擎

    问题 如何在ASP.NET Core 2.0中使用Razor引擎来创建视图? 答案 新建一个空项目,修改Startup.cs,添加MVC服务和请求中间件: public void ConfigureS ...

  3. [译]ASP.NET Core 2.0 系列文章目录

    基础篇 [译]ASP.NET Core 2.0 中间件 [译]ASP.NET Core 2.0 带初始参数的中间件 [译]ASP.NET Core 2.0 依赖注入 [译]ASP.NET Core 2 ...

  4. [译]ASP.NET Core 2.0 部分视图

    问题 如何在ASP.NET Core 2.0中使用部分视图来重用页面的公共部分? 答案 新建一个空项目,在Startup中添加MVC服务和中间件: public void ConfigureServi ...

  5. [译]ASP.NET Core 2.0 区域

    问题 如何将一个规模庞大的ASP.NET Core 2.0应用程序进行逻辑分组? 答案 新建一个ASP.NET Core 2.0空项目,修改Startup类,增加Mvc服务和中间件: public v ...

  6. [译]ASP.NET Core 2.0 中间件

    问题 如何创建一个最简单的ASP.NET Core中间件? 答案 使用VS创建一个ASP.NET Core 2.0的空项目,注意Startup.cs中的Configure()方法: public vo ...

  7. [译]ASP.NET Core 2.0 带初始参数的中间件

    问题 如何在ASP.NET Core 2.0向中间件传入初始参数? 答案 在一个空项目中,创建一个POCO(Plain Old CLR Object)来保存中间件所需的参数: public class ...

  8. [译]ASP.NET Core 2.0 全局配置项

    问题 如何在 ASP.NET Core 2.0 应用程序中读取全局配置项? 答案 首先新建一个空项目,并添加两个配置文件: 1. appsettings.json { "Section1&q ...

  9. [译]ASP.NET Core 2.0 机密配置项

    问题 如何在ASP.NET Core 2.0中保存机密配置项(不用将其暴露给源代码管理器)? 答案 创建一个ASP.NET Core 2.0空项目,在项目节点上点击右键,并点击菜单项 - 管理用户机密 ...

随机推荐

  1. 一条语句导致CPU持续100%

    一大早收到一堆CPU预警邮件,通常每天只在统计作业执行期间会收到2~3封CPU预警邮件.这次的预警来自另一台服务器,并且明细数据显示其CPU一直维持在49%.登录到服务器,查看任务管理器(查看资源监视 ...

  2. 初学者---AngularJS详解

    AngularJS 简介 AngularJs是一个用于设计动态web应用的结构框架.首先,它是一个框架,不是类库,提供一整套方案用于设计web应用.它不仅仅是一个javascript框架,因为它的核心 ...

  3. JavaScript中的與和或的規則

    與(&&)的規則是: 第一項的Boolean值為false,則返回第一項的值 第一項的Boolean值為true,則返回第二項的值 簡記:一假返一,一真返二 與:一假為假,全真為真 或 ...

  4. webView 不能复制解决方案

    开发中遇到部分机型--主要是系统低于4.0,如果调用了WebView.setWebChromeClient的方法,则没办法长按复制文字 查了一下是系统的一个bug  https://bugzilla. ...

  5. JAVA多线程--Thinking in java

    聊聊并发:http://ifeve.com/java-concurrency-thread-directory/ 阻塞状态: sleep  可中断利用 interrupt方法 wait IO  不可中 ...

  6. Spring3.2不支持jdk8

    解决方案: http://stackoverflow.com/questions/24128045/spring-context-initialization-failed-with-java-lan ...

  7. Spring Boot Document Part II(上)

    Part II. Getting started 这一章内容适合刚接触Spring Boot或者"Spring"家族的初学者!随着安装指导说明,你会发现对Spring boot有一 ...

  8. PHP常用数组(Array)函数整理

    整理了一份PHP开发中数组操作大全,包含有数组操作的基本函数.数组的分段和填充.数组与栈.数组与列队.回调函数.排序.计算.其他的数组函数等. 一.数组操作的基本函数 数组的键名和值 array_va ...

  9. VC维含义的个人理解

    有关于VC维可以在很多机器学习的理论中见到,它是一个重要的概念.在读<神经网络原理>的时候对一个实例不是很明白,通过这段时间观看斯坦福的机器学习公开课及相关补充材料,又参考了一些网络上的资 ...

  10. Day1 Python基础学习

    一.编程语言分类 1.简介 机器语言:站在计算机的角度,说计算机能听懂的语言,那就是直接用二进制编程,直接操作硬件 汇编语言:站在计算机的角度,简写的英文标识符取代二进制去编写程序,本质仍然是直接操作 ...