• asp.net core之路由


    在 ASP.NET Core 中,路由是一个非常重要的概念,它决定了如何将传入的请求映射到相应的处理程序。本文将详细介绍 ASP.NET Core 中的路由系统,包括路由的基本原理、路由模板、路由参数、路由约束等内容,并提供相应的代码示例。

    基本示例#

    var builder = WebApplication.CreateBuilder(args);
    var app = builder.Build();
    
    app.MapGet("/Hello", () => "Hello World!");
    
    app.Run();
    

    前面的示例包含使用 MapGet 方法的单个终结点:

    • 当 HTTP GET 请求发送到 URL /Hello时:
      • 将执行请求委托。
      • Hello World! 会写入 HTTP 响应。
    • 如果请求方法不是 GET 或根 URL 不是 /Hello,则无路由匹配,并返回 HTTP 404。

    UseRouting 和UseEndpoints#

    在asp.net core5之前的默认模板项目里面,我们都能看到UseRouting和UseEndpoints这两个中间件。用于配置路由。但是在新版本使用 WebApplicationBuilder配置中间件管道时,该管道使用 UseRouting 和 UseEndpoints 包装在 Program.cs 中添加的中间件,不需要显式调用。但是也可以手动显示调用这个方法来修改中间件的执行顺序。

    路由基本原理#

    在 ASP.NET Core 中,路由系统负责将传入的 URL 请求映射到相应的处理程序。它通过匹配传入的 URL 和预定义的路由模板来确定请求应该由哪个处理程序处理。路由系统的工作流程如下:

    1. 接收传入的 URL 请求。
    2. 根据路由模板匹配请求的 URL。
    3. 如果找到匹配的路由,则将请求转发给相应的处理程序。
    4. 如果没有找到匹配的路由,则返回 404 错误。

    路由模板#

    路由模板是用于定义路由的模式字符串。它可以包含静态文本和占位符,用于匹配传入的 URL。占位符由花括号包围,例如 {controller}、{action} 等。路由模板中的占位符可以用于捕获 URL 中的参数,并将其传递给处理程序。以下是一个示例路由模板:

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

    如果路由找到匹配项,{} 内的令牌定义绑定的路由参数。 可在路由段中定义多个路由参数,但必须用文本值隔开这些路由参数。
    在上面的示例中,{controller}、{action} 和 {id} 是占位符,/是文本值,它们将匹配传入的 URL 中相应的部分。{id?} 中的问号表示参数是可选的。例如,对于 URL /Home/Index/123,controller 的值将是 Home,action 的值将是 Index,id 的值将是 123。
    我们新建一个HomeController

    public class HomeController : Controller
    {
        [HttpGet]
        public IActionResult Index(string? id)
        {
            return Ok(new { id });
        }
    }
    

    然后启动服务请求根路径/和/Home/Index/123
    image.png
    image.png
    可以看到,请求顺利。
    需要注意的是,这种对ApiController无效,适合MVC模式。只要有ApiController特性标签,则必须使用[Route]特性标记路由。

    路由参数#

    路由参数是从 URL 中捕获的值,它们可以用于向处理程序传递数据。在路由模板中,可以使用占位符来定义路由参数。在处理程序中,可以使用属性路由或参数路由的方式来接收路由参数。

    属性路由#

    属性路由是通过在处理程序的属性上添加路由特性来定义的。属性路由的示例如下:

    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        [HttpGet("{id}")]
        public IActionResult GetId(int id)
        {
            return Ok(new { id });
        }
    }
    

    在上面的示例中,[Route("api/[controller]")] 表示该控制器的路由模板是 api/[controller],其中 [controller] 是一个占位符,它将被控制器的名称替换。[HttpGet("{id}")] 表示 GetId 方法的路由模板是 {id},它将匹配传入的 URL 中的 id 参数。使用swagger测试响应:
    image.png

    参数路由#

    参数路由是通过在处理程序的方法参数上添加路由特性来定义的。参数路由的示例如下:

    [HttpGet("GetId/{id}")]
    public IActionResult GetIdTow(int id)
    {
        return Ok(new { id });
    }
    

    在上面的示例中,[HttpGet("GetId/{id}")] 表示该方法的路由模板是 GetId/{id},其中 id 是一个占位符,它将匹配传入的 URL 中的 id 参数。使用swagger测试响应:
    image.png

    路由约束#

    路由约束用于限制路由模板中参数的值。它可以是预定义的约束,也可以是自定义的约束。预定义的约束包括:

    • int:表示参数必须是整数。
    • bool:表示参数必须是布尔值。
    • datetime:表示参数必须是日期时间。
    • decimal:表示参数必须是十进制数。
    • double:表示参数必须是双精度浮点数。
    • float:表示参数必须是单精度浮点数。
    • guid:表示参数必须是 GUID。
    • long:表示参数必须是长整数。

    下表是官方给出的约束表格:
    image.png
    要在路由模板中使用约束,可以在参数名称后面使用冒号 :,并指定约束的名称。例如,{id:int} 表示 id 参数必须是整数。
    我们在GetIdTowi就上整数和最小值1的约束。

    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        [HttpGet("{id}")]
        public IActionResult GetId(int id)
        {
            return Ok(new { id });
        }
        [HttpGet("GetId/{id:int:min(1)}")]
        public IActionResult GetIdTow(int id)
        {
            return Ok(new { id });
        }
    }
    

    然后分别尝试字符串和小于1的数字:
    image.png
    image.png

    自定义的约束可以通过实现 IRouteConstraint 接口来创建。以下是一个官方示例自定义约束的代码,实现 NoZeroesRouteConstraint 可防止将 0 用于路由参数:

    [ApiController]
    [Route("api/[controller]")]
    public class NoZeroesController : ControllerBase
    {
        [HttpGet("{id:noZeroes}")]
        public IActionResult Get(string id) =>
            Content(id);
    }
    
    public class NoZeroesRouteConstraint : IRouteConstraint
    {
        private static readonly Regex _regex = new(
            @"^[1-9]*$",
            RegexOptions.CultureInvariant | RegexOptions.IgnoreCase,
            TimeSpan.FromMilliseconds(100));
    
        public bool Match(
            HttpContext? httpContext, IRouter? route, string routeKey,
            RouteValueDictionary values, RouteDirection routeDirection)
        {
            if (!values.TryGetValue(routeKey, out var routeValue))
            {
                return false;
            }
    
            var routeValueString = Convert.ToString(routeValue, CultureInfo.InvariantCulture);
    
            if (routeValueString is null)
            {
                return false;
            }
    
            return _regex.IsMatch(routeValueString);
        }
    }
    

    若要使用自定义 IRouteConstraint,必须在服务容器中使用应用的 ConstraintMap 注册路由约束类型。 ConstraintMap 是将路由约束键映射到验证这些约束的 IRouteConstraint 实现的目录。 应用的 ConstraintMap 可作为 AddRouting 调用的一部分在 Program.cs 中进行更新,也可以通过使用 builder.Services.Configure 直接配置 RouteOptions 进行更新。

    builder.Services.AddRouting(options =>
        options.ConstraintMap.Add("noZeroes", typeof(NoZeroesRouteConstraint)));
    

    尝试请求id为0时:
    image.png
    请求不为0时候:
    image.png

    ASP.NET Core 中的路由系统,包括路由的基本原理、路由模板、路由参数、路由约束和路由属性。通过灵活使用路由系统,可以实现灵活的 URL 映射和参数传递,从而构建强大的 Web 应用程序。

    欢迎进群催更。

  • 相关阅读:
    如何为勒索软件攻击做准备?
    Linux系统——Session ID(负载均衡如何保持会话)
    工程管理系统简介 工程管理系统源码 java工程管理系统 工程管理系统功能设计
    分布式服务器架构的优点有哪些?
    Qt 客户端和服务器通信【一对一版本】
    OpenVPN服务器搭建与OpenVPN客户端访问
    SVN下载上传文件
    细说 单链表、双向链表 、LinkedList类(附 add 源码解读)和 ArrayList 和 LinkedList 的区别 —— 数据结构
    【算法与数据结构】501、LeetCode二叉搜索树中的众数
    MySQL关于Count你知道多少
  • 原文地址:https://www.cnblogs.com/fanshaoO/p/17600858.html