[Asp.net core series] 2 The grievances between the controller and the router

0. Preface

In the last article, we initially introduced asp.net core and how to create an mvc project. Starting from this article, I will show you the various contents of asp.net core, and try to lead you to explore the inner logic.

Of course, that is the future. This article will introduce the knowledge of controller and routing in asp.net core mvc by customizing a controller.

image

1. Controller

First add a class under the Controllers directory, named:

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

address:

http://localhost:5006/demo/index

If nothing happens, you should be able to see the word "Hello" on the web page .

Create a new class:

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

Combining two unconventional controller classes, let us get a glimpse of how asp.net core MVC recognizes controllers. This is what I said before, the best embodiment of convention over configuration. This philosophy was first proposed for MVC, and later extended to all aspects by the .net framework.

Asp.net core mvc recognizes the controller, and will find public classes ending with Controller or public classes inherited from Controller in the project, and mark these classes as controllers. When receiving a request from the user or the interface, the program parses out the controller name from the request path, and then looks for the class of <Controller>Controller or <Controller>: Controller.

By default, an access URL will be parsed into the following format in the program:

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

In the above, we know the parsing rules of the controller, so now look at the parsing rules of Action:

Add the following method in 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";
}

Restart, and then visit the following addresses in turn:

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

Then you can see that TestInt, TestObject, and TestPublic can be accessed normally, but TestProtect and TestPrivate both indicate that the webpage cannot be found or cannot be accessed.

可以看到,对于程序而言,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/

Then see the page: Test word, you can see that the routing system automatically completes the controller name and action name for us. If there are parameters in the method, the parameters will be automatically viewed in the form of parameter name 1 = value 1 & parameter name 2 = value 2. Id is special and will be automatically mapped according to the directory. and so:

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

Is a request link.

2.2 Add routing configuration

So, let's go back and look at the method of declaring routes:

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

By default, we will not set defaults, constraints, and dataTokens. These three parameters have meanings. The latter two are not introduced here, but the first one is briefly introduced:

In the routing configuration method, add the following:

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

                   });

So far, we have not created a controller named DemoTest, but we are accessing:

http://localhost:5006/DemoTest

Can still get a response, and the controller is resolved as Demo.

This is the meaning of defaults. When routing is parsed, the system will automatically fill in the values ​​in defaults to values ​​that are not set in the routing connection.

When we set up multiple routes, the routing system will first try to match the configuration that is easiest to resolve. For example, when we visit:

http://localhost:5000/DemoTest/

At the time, the routing system will preferentially parse from the configuration table named test, and will parse from other routes only when it cannot be found here.

3. Summary

In this article, we briefly introduced the controller and route mapping, and you can access the routes we added. In development, usually, the created controller ends with Controller and inherits the Controller class. This is because the Controller class has many useful properties and methods for us to use. The ending with Controller is to unify the rules, allowing us to see at a glance which ones are controllers.


Guess you like

Origin blog.51cto.com/15060511/2639823