ASP.NET Core中的路由

news/2024/4/26 6:00:03/文章来源:https://blog.csdn.net/yunxiaobaobei/article/details/129126818

传统路由

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

MapControllerRoute用于创建单个路由。 单个路由命名为 default 路由 。大多数具有控制器和视图的应用都使用类似 default 路由的路由模板。

之所以称为传统路由,是因为它为 URL 路径建立了一个约定:

使用默认路由进行传统路由可以创建应用,而无需为每个操作提出新的 URL 模式。 对于具有 CRUD 样式操作的应用,跨控制器的 URL 保持一致:

  • 第一个路径段 {controller=Home} 映射到控制器名称。
  • 第二段 {action=Index} 映射到操作名称。
  • 第三段 {id?} 用于可选 id。 {id?} 中的 ? 使其成为可选。 id 用于映射到模型实体。
  • 此映射:

  • 仅基于控制器和操作名称。
  • 不基于命名空间、源文件位置或方法参数。
  • 有助于简化代码。
  • 使 UI 更具可预测性。

路由模板 "{controller=Home}/{action=Index}/{id?}"

匹配URL路径,例如 /Products/Details/5。在请求的URL中,如果不提供控制器名称,则使用默认的Home页面,操作默认为Index.例如 http://127.0.0.1:10050/,http://127.0.0.1:10050/Home,http://127.0.0.1:10050/Home/Index 这三个请求返回的都是同一个页面。

简便方法:app.MapDefaultControllerRoute();可替换上一个设置路由方案。

 

大多数应用应选择基本的描述性路由方案,让 URL 有可读性和意义。 默认传统路由 {controller=Home}/{action=Index}/{id?}

  • 支持基本的描述性路由方案。
  • 是基于 UI 的应用的有用起点。
  • 是许多 Web UI 应用所需的唯一路由模板。 对于较大的 Web UI 应用,通常只需要使用区域的另一个路由。

传统路由顺序

常规路由仅匹配应用定义的操作和控制器的组合。 这是为了简化传统路由重叠的情况。 使用 MapControllerRoute、MapDefaultControllerRoute 和 MapAreaControllerRoute 添加路由会根据调用它们的顺序自动为其终结点分配一个顺序值。 来自较早出现的路由的匹配具有更高的优先级。 传统路由依赖于顺序。 一般情况下,具有区域的路由应放在路由表中靠前的位置,因为它们比没有区域的路由更具体。 具有 catch-all 路由参数的专用传统路由(例如 {*article})会使某个路由变得太贪婪,也就是说,它会匹配你想要使用其他路由来匹配的 URL。 将贪婪路由放在路由表中靠后的位置可解决此问题。

属性路由

API 的属性路由REST

REST API 应使用属性路由将应用的功能建模为一组资源,其中操作由 HTTP 谓词表示。

属性路由使用一组属性将操作直接映射到路由模板。如下示例:

public class HomeController : Controller
{[Route("")][Route("Home")][Route("Home/Index")][Route("Home/Index/{id?}")]public IActionResult Index(int? id){return ControllerContext.MyDisplayRouteInfo(id);}[Route("Home/About")][Route("Home/About/{id?}")]public IActionResult About(int? id){return ControllerContext.MyDisplayRouteInfo(id);}
}

这里可以看到属性路由需要更多输入才能指定路由。 传统默认路由会更简洁地处理路由。 但是,属性路由允许并需要精确控制应用于每项操作的路由模板。

这里我们注意到控制器和操作名称在操作匹配中不起作用,除非使用标记替换。如下示例:

public class HomeController : Controller
{[Route("")][Route("Home")][Route("[controller]/[action]")]public IActionResult Index(){return ControllerContext.MyDisplayRouteInfo();}[Route("[controller]/[action]")]public IActionResult About(){return ControllerContext.MyDisplayRouteInfo();}
}

也可直接将标记 [Route("[controller]/[action]")] 应用于控制器:

[Route("[controller]/[action]")]
public class HomeController : Controller
{[Route("~/")][Route("/Home")][Route("~/Home/Index")]public IActionResult Index(){return ControllerContext.MyDisplayRouteInfo();}public IActionResult About(){return ControllerContext.MyDisplayRouteInfo();}
}

在前面的代码中,Index 方法模板必须将 / 或 ~/ 预置到路由模板。 应用于操作的以 / 或 ~/ 开头的路由模板不与应用于控制器的路由模板合并。

保留的路由名称

以下关键字是使用控制器或 Razor Pages 时保留的路由参数名称:

  • action
  • area
  • controller
  • handler
  • page
  • 在 Razor 视图或 Razor 页面的上下文中保留以下关键字:

  • page

  • using

  • namespace

  • inject

  • section

  • inherits

  • model

  • addTagHelper

  • removeTagHelper

不应将这些关键字用于链接生成、模型绑定参数或上层属性。

HTTP 谓词模板

ASP.NET Core 具有以下 HTTP 谓词模板:

  • [HttpGet]
  • [HttpPost]
  • [HttpPut]
  • [HttpDelete]
  • [HttpHead]
  • [HttpPatch]

路由模板

ASP.NET Core 具有以下路由模板:

  • 所有HTTP谓词模板都是路由模板。
  • [Route]

使用 Http 谓词属性的属性路由

[Route("api/[controller]")]
[ApiController]
public class Test2Controller : ControllerBase
{[HttpGet]   // GET /api/test2public IActionResult ListProducts(){return ControllerContext.MyDisplayRouteInfo();}[HttpGet("{id}")]   // GET /api/test2/xyzpublic IActionResult GetProduct(string id){return ControllerContext.MyDisplayRouteInfo(id);}[HttpGet("int/{id:int}")] // GET /api/test2/int/3public IActionResult GetIntProduct(int id){return ControllerContext.MyDisplayRouteInfo(id);}[HttpGet("int2/{id}")]  // GET /api/test2/int2/3public IActionResult GetInt2Product(int id){return ControllerContext.MyDisplayRouteInfo(id);}
}

REST API 应使用属性路由将应用的功能建模为一组资源,其中操作由 HTTP 谓词表示。 也就是说,对同一逻辑资源执行的许多操作(例如,GET 和 POST)都使用相同 URL。 属性路由提供了精心设计 API 的公共终结点布局所需的控制级别。

组合属性路由

若要使属性路由减少重复,可将控制器上的路由属性与各个操作上的路由属性合并。 控制器上定义的所有路由模板均作为操作上路由模板的前缀。 在控制器上放置路由属性会使控制器中的所有操作都使用属性路由。

[ApiController]
[Route("products")]
public class ProductsApiController : ControllerBase
{[HttpGet]public IActionResult ListProducts(){return ControllerContext.MyDisplayRouteInfo();}[HttpGet("{id}")]public IActionResult GetProduct(int id){return ControllerContext.MyDisplayRouteInfo(id);}
}

 

属性路由顺序

路由构建树并同时匹配所有终结点:

  • 路由条目的行为就像以理想的顺序排列一样。
  • 最具体的路由有机会在更通用的路由之前执行。

例如,blog/search/{topic} 之类的属性路由比 blog/{*article} 之类的属性路由更具体。 默认情况下,blog/search/{topic} 路由具有更高的优先级,因为它更具体。 使用传统路由时,开发人员负责按所需顺序放置路由。

属性路由可以使用 Order 属性配置顺序。 框架提供的所有路由属性都包括 Order。 路由按 Order 属性的升序进行处理。 默认顺序为 0。 使用 Order = -1 设置的路由在未设置顺序的路由之前运行。 使用 Order = 1 设置的路由在默认路由顺序之后运行。

路由模板 [controller]、[action]、[area] 中的标记替换

为方便起见,属性路由支持标记替换,方法是将标记用方括号([])括起来。 标记 [action][area] 和 [controller] 替换为定义了路由的操作中的操作名称值、区域名称值和控制器名称值。

[Route("[controller]/[action]")]
public class Products0Controller : Controller
{[HttpGet]  //匹配Products0/Listpublic IActionResult List(){return ControllerContext.MyDisplayRouteInfo();}[HttpGet("{id}")]//匹配 /Products0/Edit/{id}public IActionResult Edit(int id){return ControllerContext.MyDisplayRouteInfo(id);}
}

多个属性路由

属性路由支持定义多个访问同一操作的路由。 此操作最常用于模拟默认传统路由的行为,如以下示例所示:

[Route("Store")]
[Route("[controller]")]
public class Products6Controller : Controller
{[HttpPost("Buy")]       // Matches 'Products6/Buy' and 'Store/Buy'[HttpPost("Checkout")]  // Matches 'Products6/Checkout' and 'Store/Checkout'public IActionResult Buy(){return ControllerContext.MyDisplayRouteInfo();}
}

指定属性路由的可选参数、默认值和约束

属性路由支持使用与传统路由相同的内联语法,来指定可选参数、默认值和约束。

public class Products14Controller : Controller
{[HttpPost("product14/{id:int}")]public IActionResult ShowProduct(int id){return ControllerContext.MyDisplayRouteInfo(id);}
}

在前面的代码中,[HttpPost("product14/{id:int}")] 应用路由约束。 Products14Controller.ShowProduct 操作仅与 /product14/3 等 URL 路径匹配。 路由模板部分 {id:int} 将该段限制为仅整数。

URL 生成和环境值

应用可以使用路由 URL 生成功能来生成指向操作的 URL 链接。 生成 URL 可消除硬编码URL,使代码更稳定、更易维护。 本部分重点介绍 MVC 提供的 URL 生成功能,并且仅涵盖 URL 生成工作原理的基础知识。

IUrlHelper 接口用于生成 URL,是 MVC 与路由之间的基础结构的基础部分。 在控制器、视图和视图组件中,可通过 Url 属性获得 IUrlHelper 的实例。

在以下示例中,将通过 Controller.Url 属性使用 IUrlHelper 接口来生成指向另一项操作的 URL。

public class UrlGenerationController : Controller
{public IActionResult Source(){// Generates /UrlGeneration/Destinationvar url = Url.Action("Destination");return ControllerContext.MyDisplayRouteInfo("", $" URL = {url}");}public IActionResult Destination(){return ControllerContext.MyDisplayRouteInfo();}
}

这里MyDisplayRouteInfo由 Rick.Docs.Samples.RouteInfo NuGet 包提供,会显示路由信息。

如果应用使用的是传统默认路由,则 url 变量的值将为 URL 路径字符串 /UrlGeneration/Destination。 此 URL 路径由路由通过组合以下内容创建:

  • 当前请求的路由值,称为环境值。
  • 传递到 Url.Action 的值,并将这些值替换到路由模板中:

ambient values: { controller = "UrlGeneration", action = "Source" } values passed to Url.Action: { controller = "UrlGeneration", action = "Destination" } route template: {controller}/{action}/{id?} result: /UrlGeneration/Destination

路由模板中的每个路由参数都会通过将名称与这些值和环境值匹配,来替换掉原来的值。 没有值的路由参数可以:

  • 使用默认值(如果有)。
  • 如果可选,则跳过。 例如,路由模板 {controller}/{action}/{id?} 中的 id

Areas

区域是一项 MVC 功能,用于将相关功能作为一个单独的组组织到一个组中:

  • 控制器操作的路由命名空间。
  • 视图的文件夹结构。

通过使用区域,应用可以有多个名称相同的控制器,只要它们具有不同的区域。 通过向 controller 和 action 添加另一个路由参数 area,可使用区域为路由创建层次结构。 本部分讨论路由如何与区域交互。

app.MapAreaControllerRoute("blog_route", "Blog","Manage/{controller}/{action}/{id?}");
app.MapControllerRoute("default_route", "{controller}/{action}/{id?}");

传统路由依赖于顺序。 一般情况下,具有区域的路由应放在路由表中靠前的位置,因为它们比没有区域的路由更具体。

在前面的示例中,路由值 { area = Blog, controller = Users, action = AddUser } 匹配以下操作:

using Microsoft.AspNetCore.Mvc;namespace MyApp.Namespace1
{[Area("Blog")]public class UsersController : Controller{// GET /manage/users/adduserpublic IActionResult AddUser(){var area = ControllerContext.ActionDescriptor.RouteValues["area"];var actionName = ControllerContext.ActionDescriptor.ActionName;var controllerName = ControllerContext.ActionDescriptor.ControllerName;return Content($"area name:{area}" +$" controller:{controllerName}  action name: {actionName}");}        }
}

[Area] 属性将控制器表示为区域的一部分。 此控制器位于 Blog 区域。 没有属性的[Area]控制器不是任何区域的成员,并且当路由提供路由值时area不匹配

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_71599.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

工业4.0和工业物联网如何协同工作

虽然许多公司已经接受了工业物联网,但他们现在必须接受工业4.0对数据驱动的数字化转型的承诺。随着制造业、能源、公用事业和供应链应用迅速采用工业物联网(IIoT),这些行业的新现实正在形成。工业物联网提供了企业管理数千个活动部件所需的数据类型&…

【部署】项目正式服部署更新

chihiro-notes 千寻简笔记 v0.1 内测版 📔 笔记介绍 大家好,千寻简笔记是一套全部开源的企业开发问题记录,毫无保留给个人及企业免费使用,我是作者星辰,笔记内容整理并发布,内容有误请指出,笔…

第一章 初识 Spring Security

第一章 初识 Spring Security 1、权限管理 权限管理 基本上涉及到用户参与的系统都要进行权限管理,权限管理属于系统安全的范畴,权限管理实现了对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资…

计算机网络学习笔记02

学习视频:https://www.bilibili.com/video/BV1c4411d7jb/?p7&spm_id_frompageDriver&vd_source75dce036dc8244310435eaf03de4e330 一、计算机网络体系结构 1 常见的计算机网络体系结构 OSI体系结构和TCP/IP体系结构 TCP/IP体系结构的网络接口层并没有规…

鼠标指针文件格式解析

鼠标指针文件格式解析 文章目录鼠标指针文件格式解析windowsico文件格式分析文件头:图像数据头段:图像数据段:Ani动态光标格式解析数据结构:anihseq **rate**LISTcur静态光标文件格式解析macOSLinuxwindows ico文件格式分析 是一…

【Java基础】IO流

IO流 最后一定要关闭流,防止资源泄露 字节流 一次读取1字节,8比特 FileInputStream import org.junit.jupiter.api.Test;import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException;public class CopyBytes {pub…

分布式之Raft共识算法分析

写在前面 在分布式之Paxos共识算法分析 一文中我们分析了paxos算法,知道了其包括basic paxos和multi paxos,并了解了multi paxos只是一种分布式共识算法的思想,而非具体算法,但可根据其设计具体的算法,本文就一起来看…

DAMA认证|数据治理产业上规模需要做到“三化”

数据治理是开启数据安全体系化建设的第一步,需要从产业层面做大做强,支撑数据安全整体框架,为数据流通提供安全保障,推动促进数字化产业进一步发展。 规模化发展是数据治理产业的瓶颈,行业数字化业务的复杂性和过多的定…

Spring Boot 日志文件,你都会了吗?

目录 1、日志文件的作用 2、日志的使用 2.1、从程序中得到日志对象 2.2、使用日志 2.3、日志格式 3、日志级别 3.1、这样的日志级别有什么用? 3.2、日志级别分类和使用 3.3、日志级别设置 4、日志持久化 5、更简单的日志输出——lombok 5.1、对比 5.2、…

Linux下安装MySQL8.0的详细步骤(解压tar.xz安装包方式安装)

Linux下安装MySQL8.0的详细步骤 第一步:下载安装配置 第二步:修改密码,并设置远程连接(为了可以在别的机器下面连接该mysql) 第三步:使用Navicat客户端连接 搞了一台云服务器,首先要干的活就是…

批处理删除指定文件或文件夹

声明:1-2节参考了 https://blog.csdn.net/weixin_43960383/article/details/1243673841. DEL1.1 DEL 的命令参数使用 del 命令能指定文件,Del (erase)[Drive:][Path]FileName指删除指定文件。指定要删除的文件或文件集的位置和名称。语法格式如下&#x…

Unity毛发系统TressFX Exporter

Unity 数字人交流群:296041238 一:在Maya下的TressFX Exporter 插件安装步骤: 1. 下载Maya的TressFX Exporter插件 下载地址:TressFX Exporter 链接:https://github.com/Unity-China/cn.unity.hairfx.core/tree/m…

利用OpenCV的函数equalizeHist()对图像作直方图均衡化处理

如果一幅图像的灰度值集中在某个比较窄的区域,则图像的对比度会显得比较小,不便于对图像的分析和处理。 图像的直方图均衡化可以实现将原图像的灰度值范围扩大,这样图像的对比度就得到了提高,从而方便对图像进行后续的分析和处理…

Cosmos 基础教程(二)-- Run a Node, API, and CLI

有很多不同的方法来运行Cosmos区块链的节点。您将探索如何使用simapp 进行此操作。 1、编译simapp Cosmos SDK存储库包含一个名为 simapp 的文件夹。在这个文件夹中,您可以找到运行Cosmos SDK模拟版本的代码,这样您就可以在不实际与链交互的情况下测试…

化解射频和微波设计挑战的六个技巧

即使是最自信的设计人员,对于射频电路也往往望而却步,因为它会带来巨大的设计挑战,并且需要专业的设计和分析工具。这里将为您介绍六条技巧,来帮助您简化任何射频PCB 设计任务和减轻工作压力! 1、保持完好、精确的射频…

由浅入深,一起来刷Java高级开发岗面试指南,面试必定无忧!

前言 我只想面个CV工程师,面试官偏偏让我挑战造火箭工程师,加上今年这个情况更是前后两男,但再难苟且的生活还要继续,饭碗还是要继续找的。在最近的面试中我一直在总结,每次面试回来也都会复盘,下面是我根…

【2022.12.9】Lammps+Python 在计算g6(r)时遇到的问题

目录写在前面绘制g6( r )执行步骤【updated】如何检查图像的正确性:不是编程问题,而是数学问题的一个小bug废稿2则:写在前面 全部log: 【2022.11.16】LammpsPythonMATLAB在绘制维诺图时遇到的问题 绘制g6( r )执行步骤【updated…

面试中经常被问到的【宏定义】,改变你对【C\C++】中宏定义的认识。

最近遇到挺多宏定义的代码,其实挺烦的,每次看复杂的宏定义看到一半就懵了,今天盘一盘它。本篇设计宏定义的原理、使用方法、使用技巧。 目录 一、宏定义原理 二、宏定义定义复杂功能函数 2.1 定义注册函数 三、宏定义实现条件编译 四、宏…

扬帆优配|五千亿巨头一度涨停! 4天3倍,港股又现“狂飙”股!

周一,A股三大指数走势分化。到午间收盘,沪指震荡走高涨近1%,深证成指涨0.75%,创业板指继续弱势调整。 盘面上,钢铁、煤炭、大金融等权重板块团体走强,三大通讯运营商一同拉升,其间我国电信盘中一…

超25亿全球月活,字节依然没有流量

(图片来源于网络,侵删) 文|螳螂观察 作者| 搁浅虎鲸 注意看,这个男人叫梁汝波,是字节跳动的联合创始人,也是接棒张一鸣的新任CEO。 在字节跳动十周年之际,他发表了激情昂扬的演讲。“激发创…