0. 前言

在上一篇文章中,我们初步介绍了asp.net core,以及如何创建一个mvc项目。从这一篇开始,我将为大家展示asp.net core 的各种内容,并且尝试带领大家来挖掘其中的内在逻辑。

当然,那是以后的事情。这一篇将通过自定义一个控制器来为大家介绍asp.net core mvc 中控制器和路由的相关知识。

1. 控制器

先在Controllers目录下添加一个类,名叫:

public class DemoController
{
public string Index()
{
return "你好";
}
}

访问地址:

http://localhost:5006/demo/index

如果不出意外的话,你应该能看到网页上的"你好"两个字。

再新建一个类:

using Microsoft.AspNetCore.Mvc;
public class NoContrl : Controller
{
public IActionResult Index()
{
return Content("Test");
}
}

结合两个不常规的控制器类,让我们初窥asp.net core MVC是如何识别控制器的。这正是我之前说的,约定优于配置最好的体现。这个哲学最早也是为MVC提出来的,后来被.net framework引申到各个方面。

asp.net core mvc识别控制器,会在项目中发现 以Controller结尾的公开类或者继承自Controller的公开类,并将这些类标记为控制器。当接到用户或者界面转交的请求时,程序从请求路径中解析出控制器名称,然后寻找 <控制器>Controller 或者 <控制器> : Controller 的类。

在默认情况下,一个访问URL会在程序中解析成如下格式:

http://<HOST>:<PORT>/<Controller>/<Action>[其他参数]

在上文中,我们知道了控制器的解析规则,那么现在看一下Action的解析规则:

在DemoController中添加如下方法:

public int TestInt()
{
return 10;
} public object TestObject()
{
return new
{
Name = "TestObject",
Age = 1
};
} public string TestPublic()
{
return "成功访问 TestPublic";
} protected string TestProtect()
{
return "成功访问 TestProtect";
} private string TestPrivate()
{
return "成功访问 TestPrivate";
}

重新启动,后依次访问如下地址:

http://localhost:5006/Demo/TestInt
http://localhost:5006/Demo/TestObject
http://localhost:5006/Demo/TestPublic
http://localhost:5006/Demo/TestProtect
http://localhost:5006/Demo/TestPrivate

然后可以看到,TestInt、TestObject以及TestPublic均能正常访问,但TestProtect和TestPrivate都提示找不到网页或无法访问。

可以看到,对于程序而言,Action就是控制器类里的公开类方法,与方法的返回值无关。也就是说,程序会找到 XXXController 或者名为XXX但继承了Controller的类作为XXX的控制器,然后继续在这个类里寻找到Action,如果没有找到就会返回404的请求。

2. 路由

在第一节中,我们介绍了一下asp.net core mvc如何寻找控制器和Action,那这一节将介绍程序如何从请求链接中解析出控制器和Action的名称,也就是路由映射。

路由(Routing)负责匹配传入的HTTP请求,然后将这些请求发送给应用的可执行终结点。终结点是应用的可执行请求处理代码单元,也就是我们控制器里的方法(Action)。

2.1 路由的配置

对于所有的asp.net core模板都包括生成在代码中的路由。通常,我们要求路由在Startup.Configure方法中进行配置。

注意,Startup类里有且只有一个Configure方法,不能出现其重载版本。

该方法的声明一般情况如下:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env);

如果想要设置路由,需要先注明项目启用路由:

app.UseRouting();

然后使用如下方法配置路由:

app.UseEndpoints(endpoints =>
{
// 配置路由
});

通常对于mvc项目而言,我们一般使用如下方式配置路由:

endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");

这行代码的意思是:创建一个名字为 default 的映射控制器的路由,映射规则为 {controller}/{action}/{id?},也就是第一个为控制器,第二个为Action,第三个是ID,其中ID可以不存在,当Action无法从请求地址中解析出来时默认为Index,控制器默认为Home。

通过这个解析,我们可以得知 我们之前访问的

http://localhost:5000/

是哪个控制器里的什么方法来处理了——HomeController.Index。

那么我们修改一下HomeController.Index来验证一下,我们理解是否有误:

public IActionResult Index()
{
return View();
}
// 修改为
public IActionResult Index()
{
return Content("测试");
}

重新运行程序,访问

http://localhost:5000/

然后看到页面出现:测试字样,可以看到路由系统自动为我们补全了控制器名和action名。如果方法中出现参数,则自动按照参数名1=值1&参数名2=值2这种形式查看参数。Id为特殊的,会自动按照目录其映射。所以:

http://localhost:5000/控制器1/方法1/id值
http://localhost:5000/控制器1/方法1?id=id值

是一个请求链接。

2.2 添加路由配置

那么,我们回过头来看一下声明路由的方法:

public static ControllerActionEndpointConventionBuilder MapControllerRoute(this IEndpointRouteBuilder endpoints, string name, string pattern, object defaults = null, object constraints = null, object dataTokens = null);

默认情况下,我们不会设置 defaults、constraints、dataTokens,这三个参数都有含义,这里不对后两个做介绍,简单介绍一下第一个:

在路由配置的方法里,添加以下内容:

endpoints.MapControllerRoute(
name : "test",
pattern: "DemoTest/{action=Index}/{id?}",
defaults : new
{
Controller = "Demo", });

至此,我们没有创建名为DemoTest的控制器,但是我们在访问:

http://localhost:5006/DemoTest

仍然能得到响应,而且控制器被解析为Demo。

这就是defaults的意义,路由在解析的时候,系统会把defaults中的值自动填充到路由连接中没有设置的值里。

当我们设置多个路由的时候,路由系统会优先尝试匹配最容易解析的配置。比如说,当我们访问:

http://localhost:5000/DemoTest/

的时候,路由系统会优先从名为test的配置表中解析,只有当无法从这里找到时才会从其他路由中解析。

3. 总结

这一篇我们简单介绍了控制器与路由映射,可以访问我们自己添加的路由。在开发中,通常情况下,创建的控制器都是以Controller结尾并继承Controller类。这是因为Controller类有很多有用的属性和方法供我们使用,以Controller结尾是为了统一规则,可以让我们一眼看出哪些是控制器。

更多内容烦请关注我的博客《高先生小屋》

最新文章

  1. 用CIL写程序:你好,沃尔德
  2. Java防盗链机制
  3. Java数据结构和算法之栈与队列
  4. Moto G如何进入开发者选项
  5. 由登录服务器时ulimit配置报错,也谈下ulimit配置
  6. URAL 1992
  7. 安装、配置JDK的步骤
  8. DELL 720XD和R820玩赏
  9. Team Queue(多队列技巧处理)
  10. top使用命令
  11. 和逛微博、刷朋友圈一样玩转 GitHub
  12. 局域网配置dnsmasq
  13. centos7之NFS使用
  14. Python自学:第三章 使用函数sort( )对列表进行临时排序
  15. 回文的范围——算法面试刷题2(for google),考察前缀和
  16. JAVA记录-SpringMVC集成redis
  17. hammer.js方法总结(只做了一个简单的demo)
  18. (C++)字符串分割
  19. 多媒体开发之rtmp---rtmp client 编译
  20. 微信小程序-注册和第一个demo

热门文章

  1. JDK基本库概述
  2. 动态代理学习(二)JDK动态代理源码分析
  3. java基础篇 之 final关键字
  4. JS字符串截取 “指定字符” 前面和后面的内容!
  5. 在Qsys中创建用户自定义IP
  6. 曹工谈Spring Boot:Spring boot中怎么进行外部化配置,一不留神摔一跤;一路debug,原来是我太年轻了
  7. 3.9 Go Slice切片
  8. 2.2 Go变量类型
  9. 06 返回静态文件的映射(函数/多线程)web框架
  10. jsp获取当前日期