ASP.NET Core 的 Routing

这篇具有很好参考价值的文章主要介绍了ASP.NET Core 的 Routing。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

ASP.NET Core 的 Routing

ASP.NET Core 的 controllers 使用Routing 中间件匹配客户端的 url 请求,然后映射到对应的 controller 的处理方法(Action)上。
Actions 可以是 常规路由属性路由 的映射。
MVC App一般使用常规路由。
REST APIs 应该使用属性路由。

MVC App 中用的常规路由

使用 MapControllerRoute() 方法,创建一个单一路由。

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

这个单一路由的名字是"default"。
这个单一路由的模板是"{controller=Home}/{action=Index}/{id?}",Home是默认Controller名称,Index是默认Action名称。

这个路由模板:

  • 匹配的url路径类似:/Products/Details/5
  • 解析的参数值是:{ controller = Products, action = Details, id = 5 }

如果有两个Controller 的定义是这样的:

public class ProductsController : Controller
{
    public IActionResult Details(int id)
    {
        // use id;
    }
}
public class HomeController : Controller
{
    public IActionResult Index() { ... }
}

如果有 url是:/Products/Details/5,
对应路由模板的 “{controller=Home}/{action=Index}/{id?}”,
因为可以找到Products Controller,所以匹配了ProductsController

  • Products Controller 中的 Products
  • Details 代表Action方法
  • 5 对应入参 id 的值,? 表示 5 是可空的,如果id出现在url中但无值,则默认为0。

而以下 url:都会匹配到HomeController:

  • /Home/Index/17
  • /Home/Index
  • /Home 可以找到Home controllers,没有指定具体的则找默认的 Index action
  • / 没有具体指定controllers和action,则找默认的Home controllers 和 Index action

注意:匹配的过程只基于Controllers名称和Action名称,与代码的命名空间,文件夹层级,Action的参数无关。

设置多个常规路由

可以多次调用 app.MapControllerRoute()。

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

blog路由在这里是一个专用的常规路由,符合规则的 url 都会映射到BlogController的Article方法。
“/Blog”, “/Blog/Article”, 和 “/Blog/{any-string}” 都会映射到BlogController的Article方法。
blog路由优先于default路由进行匹配,因为它先被注册。

Action 冲突

如果多个Action都被路由系统匹配,那么会:

  • 选择最匹配的,或
  • 抛出异常

比如url /Products/Edit/17 会同时匹配下面的两个 Action

public class ProductsController : Controller
{
    public IActionResult Edit(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
    [HttpPost]
    public IActionResult Edit(int id, Product product)
    {
        return ControllerContext.MyDisplayRouteInfo(id, product.name);
    }
}

而一般来说,只有id入参的Action,url 一般是GET方法,而入参是int id, Product product的Action,url一般是POST方法。
所以需要使用[HttpGet] 或者 [HttpPOST] 来标记Action,让路由系统匹配最佳的Action,HTTP Method属性包括:

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

REST APIs 中用的属性路由

属性路由没有像传统路由那样的通配路由,而且不再通过Controller和Action的名称匹配,除非使用占位符匹配。
直接在Controller的Action中用属性定义:

public class HomeController : Controller
{
    [Route("")]
    [Route("Home")]
    [Route("Home/Index")]
    [Route("Home/Index/{id?}")]
    [HttpGet]
    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);
    }
}

意思是一个Action可以匹配多个url模板。
但应该尽量精确的使用url模板,保证效率。

占位符匹配

占位符可以是 [action], [area], 和 [controller],占位符使用area,controller和action的名称进行匹配。
例如:

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]")]
public class HomeController : Controller
{
    [Route("~/")]
    [Route("/Home")]
    [Route("~/Home/Index")]
    public IActionResult Index()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    public IActionResult About()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

组合匹配

[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);
    }
}

在Controller上定义了[Route(“products”)],在Action 上定义了HttpMethod,那么在匹配时,会组合起来匹配,比如:

  • /products 会匹配 ProductsApi.ListProducts
  • /products/5 会匹配 ProductsApi.GetProduct(int)

但是 “/” 或者 “~/” 开头的模板不会被controller的模板组合。

匹配顺序

  • 模板规则越具体的越优先匹配
  • 根据 Order 属性,比如 [Route(“Home”, Order = 2)] 晚于 [Route(“Home”, Order = 1)]

指定参数类型

可以在Url模板中指定参数id的值类型:

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

还可以定义默认值:

public class MyApiControllerAttribute : Attribute, IRouteTemplateProvider
{
    public string Template => "api/[controller]";
    public int? Order => 2;
    public string Name { get; set; } = string.Empty;
}

[MyApiController]
[ApiController]
public class MyTestApiController : ControllerBase
{
    // GET /api/MyTestApi
    [HttpGet]
    public IActionResult Get()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

混合使用传统路由和属性路由

Actions 可以是传统路由或者属性路由,但是定义了属性路由的Actions 就不能再被传统路由匹配了,意思是属性路由的优先级更高。
而如果Controller上定义了属性路由,那么所有内部的Actions 就都不能再被传统路由匹配了。

系统保留的路由关键字

保留的路由关键字不应该用在路由匹配系统中,包括:

  • action
  • area
  • controller
  • handler
  • page
    而且在ulr中不可以包含ASCII的"/" 或者" ",路由系统不支持URL 转义。

URL Generation 和 环境值

ASP.NET Core App 可以生成指向Action的 URL,这个功能叫 URL Generation
URL Generation 可以减少 hard code的URL,使代码更健壮,更好维护。
可以在controllers和views使用Url属性使用 IUrlHelper 接口的方法。
先看传统路由的例子:

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

    public IActionResult Destination()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

这里使用的是传统路由,url 变量的值是URL的路径字符串 “/UrlGeneration/Destination”。通过组合http request的路由值(环境值):

  1. 环境值: { controller = “UrlGeneration”, action = “Source” }
  2. 环境值传给 Url.Action: { controller = “UrlGeneration”, action = “Destination” }
  3. 路由模板: {controller}/{action}/{id?}
  4. 结果: /UrlGeneration/Destination

路由模板中的每个路由参数会被环境值替代。没有值的路由参数要么使用默认值,要么跳过(可空)。

再看属性路由的例子:

public class UrlGenerationAttrController : Controller
{
    [HttpGet("custom")]
    public IActionResult Source()
    {
        var url = Url.Action("Destination");
        return ControllerContext.MyDisplayRouteInfo("", $" URL = {url}");
    }

    [HttpGet("custom/url/to/destination")]
    public IActionResult Destination()
    {
       return ControllerContext.MyDisplayRouteInfo();
    }
}

Source action 生成了 custom/url/to/destination。

通过Action名称生成URL

Url.Action, LinkGenerator.GetPathByAction 都用于通过Controller和Action的名称生成URL。
使用 Url.Action 时,controller 和 action的路由值由.NET 运行时生成。
假设有一个路由是这样: {a}/{b}/{c}/{d},环境值是 { a = Alice, b = Bob, c = Carol, d = David },那么路由有足够信息生成URL,不需要额外的值。
如果添加了{ d = Donovan },那么{ d = David }会被忽略,会生成URL Alice/Bob/Carol/Donovan。
如果添加了 { c = Cheryl },那么{ c = Carol, d = David } 都会被忽略。

任何不匹配路由参数的额外的值都会被放进query字符串中。比如:

public IActionResult Index()
{
    var url = Url.Action("Buy", "Products", new { id = 17, color = "red" });
    return Content(url!);
}

会生成URL: /Products/Buy/17?color=red

下面的代码生成一个绝对路径URL:

public IActionResult Index2()
{
    var url = Url.Action("Buy", "Products", new { id = 17 }, protocol: Request.Scheme);
    // Returns https://localhost:5001/Products/Buy/17
    return Content(url!);
}

通过路由名称生成URL

Url.RouteUrl 可以指定一个路由名称生成URL,而一般不指定Controller或者Action名称。
比如:

public class UrlGeneration2Controller : Controller
{
    [HttpGet("")]
    public IActionResult Source()
    {
        var url = Url.RouteUrl("Destination_Route");
        return ControllerContext.MyDisplayRouteInfo("", $" URL = {url}");
    }

    [HttpGet("custom/url/to/destination2", Name = "Destination_Route")]
    public IActionResult Destination()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

下面的代码生成一个指向Destination_Route的链接:

<h1>Test Links</h1>
<ul>
    <li><a href="@Url.RouteUrl("Destination_Route")">Test Destination_Route</a></li>
</ul>

在Action Results中生成URL

在Controlle中最常见的用法是在Action Results中返回一个URL,另一个用法是Redirect到另一个Action。
Controller基类提供了方便的方法来实现Redirect。

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(int id, Customer customer)
{
    if (ModelState.IsValid)
    {
        // Update DB with new details.
        ViewData["Message"] = $"Successful edit of customer {id}";
        return RedirectToAction("Index");
    }
    return View(customer);
}

Area 路由

Area路由是MVC中的功能,可以把相关的功能做成一个分组。
可以通过Routing 命名空间分组controller 和 actions,也可以通过文件夹分组Views。
Areas 可以让多个controller 在不同的Area下有相同的名字。
比如:

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

MapAreaControllerRoute创建的路由中,blog_route是路由名,Blog是Area名。
当匹配URL路径比如 /Manage/Users/AddUser 时,“blog_route” 路由生成的路由值是:{ area = Blog, controller = Users, action = AddUser }。
上面这个路由会匹配这个Action:

    [Area("Blog")]
    public class UsersController : Controller
    {
        // GET /manage/users/adduser
        public 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属性的Controller不会匹配任何带Area的路由模板。文章来源地址https://www.toymoban.com/news/detail-686533.html

到了这里,关于ASP.NET Core 的 Routing的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【ASP.NET Core 基础知识】--最佳实践和进阶主题--设计模式在ASP.NET Core中的应用

    一、设计模式概述 1.1 什么是设计模式 设计模式是在软件设计过程中反复出现的、经过验证的、可重用的解决问题的方法。它们是针对特定问题的通用解决方案,提供了一种在软件开发中可靠的指导和标准化方法。设计模式通常描述了一种在特定情景下的解决方案,包括了问

    2024年02月21日
    浏览(168)
  • ASP.NET Core 8 基础

    2023年11月将发布发布.NET 8,基于.NET 8 的 ASP.NET Core 8.0也会一并发布,这是继ASP.NET Core 6.0之后,又一个重要版本,因为引入了nativeAOT,在性能上有很大提升,所以系统地学习一下这项技术。 ASP.NET Core 的几个主要优势: 跨平台,支持 Windows, macOS, Linux,Docker,Azure和AWS等云服务自

    2024年02月11日
    浏览(49)
  • Asp.Net Core 6 - 概述

    Q: 什么是 .NET? A:.NET 是一个开发人员平台,由工具、编程语言、库组成,用于构建许多不同类型的应用程序。使用 .NET,可以使用多种语言、编辑器和库来构建 Web、移动、桌面、游戏和 IoT 等,可以使用 C#、F# 或 Visual Basic 编写 .NET 应用。 .NET 发展至今,出现了两种实现 n

    2024年02月06日
    浏览(54)
  • ASP.NET Core —配置系统

    一个应用要运行起来,往往需要读取很多的预设好的配置信息,根据约定好的信息或方式执行一定的行为。 配置的本质就是软件运行的参数,在一个软件实现中需要的参数非常多,如果我们以 Hard Code (硬编码)的方式写在应用代码中,这样配置就会很乱,而且后续也不容易修

    2024年02月08日
    浏览(53)
  • 【C#/.NET】使用ASP.NET Core对象池

    Microsoft.Extensions.ObjectPool   减少初始化/资源分配,提高性能。这一条与线程池同理,有些对象的初始化或资源分配耗时长,复用这些对象减少初始化和资源分配。比如:我有一个执行耗时约500毫秒,内存空间 2KB的任务为此创建一个新线程异步执行,而创建线程耗时1秒,内存空

    2024年02月06日
    浏览(67)
  • ASP.NET Core 的 HttpContex

    HttpContext 类封装了HTTP Request 和 HTTP Response。 当收到一条HTTP Request 请求时,就会实例化一个HttpContext对象。HttpContext对象可以被中间件访问。 注意:HttpContext 不是线程安全的。 从Razer Page 读取 从Razer Page 的cshtml 读取 从 Controller 读取 从 Minimal API 读取 HttpContext.Request 可以获取客

    2024年02月11日
    浏览(28)
  • ASP.NET Core SignalR 入门

    本章将和大家分享使用 SignalR 生成实时应用的基础知识。通过本文您将学习如何:使用ASP.NET Core SignalR + MVC + Vue 2.x + require 最终创建一个正常运行的简易聊天应用。 废话不多说,我们直接来看一个Demo,Demo的目录结构如下所示: 本Demo的Web项目为ASP.NET Core Web 应用程序( 目标框

    2024年02月11日
    浏览(42)
  • ASP.NET Core 配置系列一

    A S P . N E T   C o r e   配 置 主 要 通 过 这 3 个 文 件 设 置 : 1   项 目 文 件 也 叫 . c s p r o j   文 件 2   P r o g r a m . c s 3   a p p s e t t i n g s . j s o n 这 些 配 置 告 诉 A S P . N E T   C o r e   应 用 程 序 基 于 用 户 的 交 互 是 如 何 工 作 的, 在 本 节 中 我 们 理 解 A S P .

    2024年02月03日
    浏览(109)
  • Asp.net Core系列学习(1)

    ASP.NET Core 是一个跨平台的高性能开源 框架 ,用于生成启用云且连接 Internet 的新式应用。 使用 ASP.NET Core,可以: 生成 Web 应用和服务、物联网 (IoT) 应用和移动后端。 在 Windows、macOS 和 Linux 上使用喜爱的开发工具。 部署到云或本地。 在 .NET Core 上运行。 ASP.NET Core 是对 ASP

    2024年02月06日
    浏览(67)
  • asp.net core之实时应用

    本文将介绍ASP.NET Core SignalR,这是一个强大的实时通信库,用于构建实时、双向通信应用程序。我们将探讨SignalR的基本概念、架构和工作原理,并提供一些示例代码来帮助读者更好地理解和使用SignalR。 ASP.NET Core SignalR提供了一种简单而强大的方式来构建实时通信应用程序。

    2024年02月14日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包