• 【asp.net core 系列】2 控制器与路由的恩怨情仇


    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结尾是为了统一规则,可以让我们一眼看出哪些是控制器。

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

    file

  • 相关阅读:
    Python+selenium怎么自定义函数进行翻页操作定位第二页元素
    序列
    元组
    读书笔记-活出意义来
    多线程源代码学习笔记
    MacOS环境下Redis安装
    django修改静态文件(css,js)之后,浏览器效果没改变
    JavaScript变量、值类型介绍和启发-day01
    99乘法法则(使用bootstrap做表格效果)
    do-while循环的与for循环,while循环的区别是什么——(摘抄)
  • 原文地址:https://www.cnblogs.com/c7jie/p/13029067.html
Copyright © 2020-2023  润新知