.NET 云原生架构师训练营(模块二 基础巩固 路由与终结点)--学习笔记

简介: - 路由模板- 约定路由- 特性路由- 路由冲突- 终结点

2.3.3 Web API -- 路由与终结点

  • 路由模板
  • 约定路由
  • 特性路由
  • 路由冲突
  • 终结点

ASP.NET Core 中的路由:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/routing?view=aspnetcore-5.0

UseRouting 添加路由中间件到管道,路由中间件用来匹配 url 和具体的 endpoint,然后执行 endpoint

UseEndpoints 添加或者注册 endpoint 到程序中,使得路由中间件可以发现它们

  • MapRazorPages for Razor Pages 添加所有 Razor Pages 终结点
  • MapControllers for controllers 添加所有 controller 终结点
  • MapHub for SignalR 添加 SignalR 终结点
  • MapGrpcService for gRPC 添加 gRPC 终结点

路由模板

路由模板由 token 和其他特定字符组成。比如“/”,特定字符进行路由匹配的时候必须全部匹配

/hello/{name:alpha}

{name:alpha} 是一段 token,一段 token 包括一个参数名,可以跟着一个约束(alpha)或者一个默认值(mingson),比如 {name=mingson} ,或者直接 {name}

app.UseEndpoints(endpoints =>
{
    //endpoints.MapControllers();
    endpoints.MapGet("/hello/{name:alpha}", async context =>
    {
        var name = context.Request.RouteValues["name"];
        await context.Response.WriteAsync($"Hello {name}!");
    });
});

路由模板中的参数被存储在 HttpRequest.RouteValues 中

大小写不敏感

url 中如果有符合,在模板中用{}代替

catch-all 路由模板

  • 在 token 前用 或者 加在参数名前,比如 blog/{slug}
  • blog/ 后面的字符串会当成 slug 的路由参数值,包括 "/",比如浏览器输入 blog/my/path 会匹配成 foo/my%2Fpath,如果想要得到 blog/my/path 则使用两个 ,foo/{path}
  • 字符串.也是可选的,比如 files/{filename}.{ext?},如果要输入 /files/myFile 也能匹配到这个路由
//app.Run(async context =>
//{
//    await context.Response.WriteAsync("my middleware 2");
//});

app.UseEndpoints(endpoints =>
{
    //endpoints.MapControllers();

    // 将终结点绑定到路由上
    endpoints.MapGet("/hello", async context =>
    {
        await context.Response.WriteAsync("Hello World!");
    });
});

启动程序,访问:https://localhost:5001/hello

输出如下:

my middleware 1Hello World!

获取路由模板参数

endpoints.MapGet("/blog/{*title}", async context =>
{
    var title = context.Request.RouteValues["title"];
    await context.Response.WriteAsync($"blog title: {title}");
});

启动程序,访问:https://localhost:5001/blog/my-title

输出如下:

my middleware 1blog title: my-title

constraint 约束

18.jpg
19.jpg

[Route("users/{id:int:min(1)}")]
public User GetUserById(int id) { }
app.UseEndpoints(endpoints =>
{
    endpoints.MapGet("{message:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)}",
        context => 
        {
            return context.Response.WriteAsync("inline-constraint match");
        });
});

约定路由

默认

endpoints.MapDefaultControllerRoute();

自定义

endpoints.MapControllerRoute("default","{controller=Home}/{action=Index}/{id?}");
// 约定路由
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
});

// 约定路由也可以同时定义多个
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");

    endpoints.MapControllerRoute(
        name: "blog",
        pattern: "blog/{*article}",
        defaults: new {controller = "blog", action = "Article"});
});

特性路由

controller

[Route("[controller]")]

http method

[HttpGet("option")]

[HttpGet]
[Route("option")]

[HttpGet]
[Route("option/{id:int}")]

路由冲突

[HttpGet]
//[Route("option")]
public IActionResult GetOption()
{
    return Ok(_myOption);
}

如果路由相同,启动程序会报错:

AmbiguousMatchException: The request matched multiple endpoints. Matches:
HelloApi.Controllers.ConfigController.GetOption (HelloApi)
HelloApi.Controllers.ConfigController.GetConfigurations (HelloApi)

终结点

ASP.NET Core 终结点是:

  • 可执行:具有 RequestDelegate。
  • 可扩展:具有元数据集合。
  • Selectable:可选择性包含路由信息。
  • 可枚举:可通过从 DI 中检索 EndpointDataSource 来列出终结点集合。

终结点可以:

  • 通过匹配 URL 和 HTTP 方法来选择。
  • 通过运行委托来执行。

17.jpg

中间件的每一步都在匹配终结点,所以路由和终结点之间的中间件可以拿到终结点的信息

app.UseRouting();

// 路由和终结点之间的中间件可以拿到终结点的信息
app.Use(next => context =>
{
    // 获取当前已经被选择的终结点
    var endpoint = context.GetEndpoint();
    if (endpoint is null)
    {
        return Task.CompletedTask;
    }
    // 输出终结点的名称
    Console.WriteLine($"Endpoint: {endpoint.DisplayName}");
    // 打印终结点匹配的路由
    if (endpoint is RouteEndpoint routeEndpoint)
    {
        Console.WriteLine("Endpoint has route pattern: " +
                          routeEndpoint.RoutePattern.RawText);
    }
    // 打印终结点的元数据
    foreach (var metadata in endpoint.Metadata)
    {
        Console.WriteLine($"Endpoint has metadata: {metadata}");
    }

    return Task.CompletedTask;
});

app.UseEndpoints(endpoints =>
{
    //endpoints.MapControllers();

    // 将终结点绑定到路由上
    endpoints.MapGet("/blog/{title}", async context =>
    {
        var title = context.Request.RouteValues["title"];
        await context.Response.WriteAsync($"blog title: {title}");
    });
});

启动程序,访问:https://localhost:5001/blog/my-first-blog

控制台输出如下:

Endpoint: /blog/{title} HTTP: GET
Endpoint has route pattern: /blog/{title}
Endpoint has metadata: System.Runtime.CompilerServices.AsyncStateMachineAttribute
Endpoint has metadata: System.Diagnostics.DebuggerStepThroughAttribute
Endpoint has metadata: Microsoft.AspNetCore.Routing.HttpMethodMetadata

打印 http 方法

// 打印终结点的元数据
foreach (var metadata in endpoint.Metadata)
{
    Console.WriteLine($"Endpoint has metadata: {metadata}");
    // 打印 http 方法
    if (metadata is HttpMethodMetadata httpMethodMetadata)
    {
        Console.WriteLine($"Current Http Method: {httpMethodMetadata.HttpMethods.FirstOrDefault()}");
    }
}

启动程序,访问:https://localhost:5001/blog/my-first-blog

控制台输出如下:

Current Http Method: GET

修改终结点名称、元数据

app.UseEndpoints(endpoints =>
{
    //endpoints.MapControllers();

    // 将终结点绑定到路由上
    endpoints.MapGet("/blog/{title}", async context =>
        {
            var title = context.Request.RouteValues["title"];
            await context.Response.WriteAsync($"blog title: {title}");
        }).WithDisplayName("Blog")// 修改名称
        .WithMetadata("10001");// 修改元数据
});
  • 调用 UseRouting 之前,终结点始终为 null。
  • 如果找到匹配项,则 UseRouting 和 UseEndpoints 之间的终结点为非 null。
  • 如果找到匹配项,则 UseEndpoints 中间件即为终端。 稍后会在本文档中定义终端中间件。
  • 仅当找不到匹配项时才执行 UseEndpoints 后的中间件。

GitHub源码链接:

https://github.com/MINGSON666/Personal-Learning-Library/tree/main/ArchitectTrainingCamp/HelloApi

目录
相关文章
|
6月前
|
存储 开发框架 前端开发
前端框架EXT.NET Dotnet 3.5开发的实验室信息管理系统(LIMS)成品源码 B/S架构
发展历史:实验室信息管理系统(LIMS),就是指通过计算机网络技术对实验的各种信息进行管理的计算机软、硬件系统。也就是将计算机网络技术与现代的管理思想有机结合,利用数据处理技术、海量数据存储技术、宽带传输网络技术、自动化仪器分析技术,来对实验室的信息管理和质量控制等进行全方位管理的计算机软、硬件系统,以满足实验室管理上的各种目标(计划、控制、执行)。
67 1
|
6月前
|
机器学习/深度学习 算法 安全
隐私计算训练营第三讲-详解隐私计算的架构和技术要点
SecretFlow 是一个隐私保护的统一框架,用于数据分析和机器学习,支持MPC、HE、TEE等隐私计算技术。它提供设备抽象、计算图表示和基于图的ML/DL能力,适应数据水平、垂直和混合分割场景。产品层包括SecretPad(快速体验核心能力)和SecretNote(开发工具)。算法层涉及PSI、PIR、数据分析和联邦学习(水平、垂直、混合)。此外,SecretFlow还有YACL密码库和Kusica任务调度框架,Kusica提供轻量化部署、跨域通信和统一API接口。
214 0
|
22天前
|
存储 消息中间件 前端开发
.NET常见的几种项目架构模式,你知道几种?
.NET常见的几种项目架构模式,你知道几种?
|
3月前
|
设计模式 存储 前端开发
揭秘.NET架构设计模式:如何构建坚不可摧的系统?掌握这些,让你的项目无懈可击!
【8月更文挑战第28天】在软件开发中,设计模式是解决常见问题的经典方案,助力构建可维护、可扩展的系统。本文探讨了.NET中三种关键架构设计模式:MVC、依赖注入与仓储模式,并提供了示例代码。MVC通过模型、视图和控制器分离关注点;依赖注入则通过外部管理组件依赖提升复用性和可测性;仓储模式则统一数据访问接口,分离数据逻辑与业务逻辑。掌握这些模式有助于开发者优化系统架构,提升软件质量。
51 5
|
3月前
|
XML 开发框架 .NET
.NET框架:软件开发领域的瑞士军刀,如何让初学者变身代码艺术家——从基础架构到独特优势,一篇不可错过的深度解读。
【8月更文挑战第28天】.NET框架是由微软推出的统一开发平台,支持多种编程语言,简化应用程序的开发与部署。其核心组件包括公共语言运行库(CLR)和类库(FCL)。CLR负责内存管理、线程管理和异常处理等任务,确保代码稳定运行;FCL则提供了丰富的类和接口,涵盖网络、数据访问、安全性等多个领域,提高开发效率。此外,.NET框架还支持跨语言互操作,允许开发者使用C#、VB.NET等语言编写代码并无缝集成。这一框架凭借其强大的功能和广泛的社区支持,已成为软件开发领域的重要工具,适合初学者深入学习以奠定职业生涯基础。
99 1
|
6月前
|
架构师 网络协议 算法
Android高级架构师整理面试经历发现?(大厂面经+学习笔记(1)
Android高级架构师整理面试经历发现?(大厂面经+学习笔记(1)
|
6月前
|
SpringCloudAlibaba 负载均衡 Java
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(目录大纲)
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(目录大纲)
152 1
|
6月前
|
数据安全/隐私保护 Windows
.net三层架构开发步骤
.net三层架构开发步骤
|
3天前
|
弹性计算 Kubernetes Cloud Native
云原生架构下的微服务设计原则与实践####
本文深入探讨了在云原生环境中,微服务架构的设计原则、关键技术及实践案例。通过剖析传统单体架构面临的挑战,引出微服务作为解决方案的优势,并详细阐述了微服务设计的几大核心原则:单一职责、独立部署、弹性伸缩和服务自治。文章还介绍了容器化技术、Kubernetes等云原生工具如何助力微服务的高效实施,并通过一个实际项目案例,展示了从服务拆分到持续集成/持续部署(CI/CD)流程的完整实现路径,为读者提供了宝贵的实践经验和启发。 ####
|
2天前
|
缓存 监控 API
探索微服务架构中的API网关模式
随着微服务架构的兴起,API网关成为管理和服务间交互的关键组件。本文通过在线零售公司的案例,探讨了API网关在路由管理、认证授权、限流缓存、日志监控和协议转换等方面的优势,并详细介绍了使用Kong实现API网关的具体步骤。
11 3

热门文章

最新文章