问题

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. angular 如何获取使用filter过滤后的ng-repeat的数据长度

    在做项目的过程中,被产品要求在内容为空的过程中显示提示信息,然哦户内容使用ng-repeat循环输出的,并且使用了filter过滤.后在谷歌上找到解决方案,如下: ​之前代码如下显示: <ul& ...

  2. filter的两种使用方法

    1. 在模板中使用filter 我们可以直接在{{}}中使用filter,跟在表达式后面用 | 分割,语法如下: {{ expression | filter }} 也可以多个filter连用,上一个 ...

  3. 两句话动态修改table数据并提交到后台

    //为所有的input 添加click事件,我将对象的id放入到name属性中,行数放入到alt属性中 $("input").click(function(obj){ //获得当前 ...

  4. 我的Spring学习记录(三)

    学习了AOP之后就可以应用一下了,所以这次我们了解一下Spring的声明式事务. 事务在我们的很多方面都可以体现,就拿我们平时的买卖活动,或者是银行的转账来说,这些活动要么是成功,要么是失败,比如:张 ...

  5. 第一个ExtJS练习(添加用户面板)

    1.[准备] 我是在visual studio里面建立了一个asp.net MVC项目,然后导入ExtJS必要的包,然后写的. ExtJS5.1版本下载:https://pan.baidu.com/s ...

  6. TCP/IP(三)数据链路层~2

    一.局域网 1.1.局域网和以太网的区别和联系 局域网:前面已经介绍了,其实就是学校里面.各个大的公司里,自己组件的一个小型网络,这种就属于局域网. 以太网:以太网(Ethernet)指的是由Xero ...

  7. Linux学习——Shell基础

    1 shell概述 Shell 是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用shell来启动,挂起,停止甚至编写一些程序. Shell 还是一 ...

  8. 【原】Spark 编程指南

    尊重原创,注重版权,转贴请注明原文地址:http://www.cnblogs.com/vincent-hv/p/3322966.html   1.配置程序使用资源: System.setPropert ...

  9. UWP 改变Button样式

    -----some words------ 1.Control:控制 (我们理解成控件) 2.Template:模板 3.Ellipse 椭圆 4.Content 内容 5.Presenter 节目主 ...

  10. 教你ASP.NET中如何防止注入攻击

    你应该在程序中验证所有的不信任输入.你应该假定所有的用户输入都是非法的.用户可以在应用程序中提供表单字段,查询字串,客户端cookies和浏览器环境值比如用户代理字串和IP地址等. 弱输入校验通常为注 ...