【ASP.NET Core 基础知识】--路由和请求处理--Attribute路由

一、介绍

在ASP.NET Core中,路由是将传入的URL请求映射到正确的控制器和操作的方法。Attribute路由是一种基于属性,用于定义路由规则的方式,通过在控制器类和操作方法上应用特定的属性,来定义URL模板。

  1. 基本概念:

    • **路由:**在ASP.NET Core中,路由是将URL请求映射到正确的控制器和操作的过程。路由中间件会按照定义的路由规则,将传入的HTTP请求匹配到正确的路由路径,进而执行对应的控制器和操作方法。
    • **控制器:**控制器是处理HTTP请求的类,其中包含处理请求的操作方法。在ASP.NET Core中,控制器类必须继承自Controller或ControllerBase类。
    • **操作方法:**操作方法是控制器中用于处理HTTP请求的具体实现。通过在控制器类或操作方法上应用特定的属性,可以定义URL模板,从而实现路由匹配。
  2. 重要性:

    • 可读性更强:使用属性路由,可以定义更加清晰和易读的路由路径,使得URL更加友好和易于理解。
    • **灵活性更高:**属性路由可以更加灵活地定义路由规则,支持多种路由匹配方式,如默认路由、自定义路由、参数路由等。
    • **可维护性更高:**属性路由的路由规则定义更加集中和清晰,易于维护和管理。同时,由于路由规则定义在控制器类和操作方法上,可以更好地与代码分离,提高代码的可读性和可维护性。
    • **性能更优:**属性路由在路由匹配时,可以利用编译时静态分析,提前解析路由模板,从而提高路由匹配的性能。

二、传统路由和属性路由的比较和选择

传统路由和属性路由(Attribute Routing)是ASP.NET Core中的两种主要路由(Routing)方式。下面是它们的比较和选择:

  1. 传统路由(Convention-based Routing):
    传统路由是一种基于约定的路由方式。在传统路由中,我们定义路由规则时,需要指定路由的URL模板以及相应的控制器和操作方法。传统路由是一种静态路由方式,它的路由规则是在应用程序启动时静态定义的。

    • 优点:

      • 简单易用:传统路由的路由规则定义简单明了,易于理解和使用。
      • 性能较高:传统路由的路由规则定义是在应用程序启动时静态定义的,因此在路由匹配时具有较高的性能。
    • 缺点:

      • 不够灵活:传统路由的路由规则定义是基于约定的,不够灵活,无法满足一些复杂的路由需求。
      • 可读性较差:传统路由的路由规则定义在代码中分散开来,可读性较差。
  2. 属性路由(Attribute Routing):
    属性路由是一种基于属性的路由方式。在属性路由中,我们可以在控制器类和操作方法上应用特定的属性来定义路由规则。属性路由是一种动态路由方式,它的路由规则是在运行时动态定义的。

    • 优点:

      • 更加灵活:属性路由的路由规则定义更加灵活,可以满足一些复杂的路由需求。
      • 可读性更好:属性路由的路由规则定义在代码中集中起来,可读性更好。
      • 可维护性更高:属性路由的路由规则定义更加集中和清晰,易于维护和管理。
    • 缺点:

      • 相对复杂:属性路由的路由规则定义相对复杂,需要一定的学习成本。
      • 性能较低:属性路由的路由规则定义是在运行时动态定义的,因此在路由匹配时性能相对较低。
  3. 选择:
    在选择传统路由和属性路由时,需要根据具体的应用场景和需求来选择。如果应用程序的路由规则比较简单,且性能要求较高,可以选择传统路由;如果应用程序的路由规则比较复杂,且需要更高的可读性和可维护性,可以选择属性路由。同时,在实际开发中,也可以结合使用传统路由和属性路由,以满足不同的路由需求。

三、Attribute路由的基本使用

3.1 在Controller上使用Attribute路由

在ASP.NET Core中,我们可以在控制器类上使用[Route]属性来定义控制器级别的路由规则。以下是一个示例:

[Route("api/[controller]")]
public class UsersController : Controller
{[HttpGet]public IActionResult Get(){return Ok();}[HttpGet("{id}")]public IActionResult Get(int id){return Ok();}// ...
}

在上面的示例中,我们在UsersController类上使用了[Route("api/[controller]")]属性,这表示所有该控制器的操作方法都可以通过“api/users”路径访问。

Tip:这里的[controller]是一个占位符,它会被实际的控制器名称替换。例如,如果你访问api/users路径,[controller]将被替换为Users

此外,我们还分别在GetGet(int id)方法上使用了[HttpGet][HttpGet("{id}")]属性来定义它们的路由。其中,[HttpGet]表示该方法可以通过HTTP GET请求访问,而[HttpGet("{id}")]表示该方法可以通过具有id参数的HTTP GET请求访问。

通过这种方式,我们可以方便地定义控制器级别的路由规则,从而更好地组织我们的代码和URL。

3.2 在Action上使用Attribute路由

在ASP.NET Core中,我们可以在操作方法上使用[Route]属性来定义操作方法级别的路由规则。以下是一个示例:

public class UsersController : Controller
{[HttpGet("{id:int}")]public IActionResult GetUser(int id){// ...}[HttpPost][Route("users/create")]public IActionResult CreateUser(UserViewModel model){// ...}// ...
}

在上面的示例中,我们在GetUser方法上使用了[HttpGet("{id:int}")]属性,这表示该方法可以通过具有id参数的HTTP GET请求访问,并且id必须是整数类型。而在CreateUser方法上,我们使用了[HttpPost][Route("users/create")]属性。这表示该方法可以通过HTTP POST请求访问,并且可以通过“users/create”路径访问。
通过这种方式,我们可以更加精细地定义操作方法级别的路由规则,从而更好地满足我们的需求。注意,操作方法级别的路由规则会覆盖控制器级别的路由规则。如果一个操作方法上定义了路由规则,它将优先于控制器级别的路由规则。

3.3 使用自定义路由

在ASP.NET Core中,我们可以使用自定义路由来实现更加灵活的路由规则。以下是一个示例:

public class CustomRouteAttribute : Attribute, IConfigureRoute
{public string RouteName { get; set; }public string[] RouteNames { get; set; }public string Template { get; set; }public object[] Constraints { get; set; }public string[] Order { get; set; }public void Configure(RouteCollection routes, string routeName){var route = new Route(Template, new CustomRouteHandler());if (Constraints != null){foreach (var constraint in Constraints){route.Constraints.Add(constraint.GetType().Name, constraint);}}if (Order != null){var routeList = new List<Route>();foreach (var name in RouteNames){var r = routes.GetRouteData(new MvcContext(HttpContext.Current));while (r != null){if (r.Route.RouteName.Equals(name, StringComparison.OrdinalIgnoreCase)){routeList.Add(r.Route);break;}r = r.Route.Parent;}}if (routeList.Count > 0){var index = routeList.IndexOf(route);if (index >= 0){routeList.RemoveAt(index);routeList.Insert(index, route);}}else{routes.Add(route);}}else{routes.Add(route);}}
}[CustomRoute(RouteName = "custom", Template = "custom/{id}")]
public class CustomController : Controller
{public IActionResult Index(){return View();}
}

在上面的示例中,我们自定义了一个CustomRouteAttribute属性,并在CustomController上使用它来定义路由规则。该属性的Template属性定义了路由模板,RouteName属性定义了路由名称,还可以定义其他的路由约束和路由顺序等。在Configure方法中,我们通过RouteCollectionRouteName来添加路由规则,并且可以根据需要对路由规则进行排序。
通过这种方式,我们可以更加灵活地定义路由规则,从而更好地满足我们的需求。注意,在使用自定义路由时,需要将UseMvc替换为UseMvcWithDefaultRoute,并且需要在Startup.cs文件的ConfigureServices方法中注册自定义路由。

四、Attribute路由的高级使用

4.1 路由参数

在 ASP.NET Core 中,我们可以使用 Attribute 路由来定义路由参数。这可以让我们更精确地控制路由的生成。
下面是一个基本的例子:

[Route("api/[controller]")]
public class UsersController : Controller
{[HttpGet("{id:int}")]public IActionResult GetUser(int id){// ...}
}

在这个例子中,[Route("api/[controller]")]是控制器级别的路由,表示所有 UsersController 的操作都会被路由到 “api/users” 路径。[HttpGet("{id:int}")]是操作级别的路由,表示 GetUser 方法可以被通过 GET 请求访问,并且需要一个整数参数 “id”。
你可以使用不同的 HTTP 方法来定义路由,例如:

[HttpGet("{id:int}")]
public IActionResult GetUser(int id)
{// ...
}[HttpPost]
public IActionResult CreateUser(UserModel model)
{// ...
}

在上面的例子中,[HttpPost]表示 CreateUser 方法只能通过 POST 请求访问。
你还可以使用自定义的路由约束来限制路由参数的取值范围,例如:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)]
public class PositiveIntConstraint : Attribute, IHttpRouteConstraint
{public bool Match(HttpContext context, RouteData data, string parameterName, out RouteValueDictionary values){var value = data.Values[parameterName];if (value != null && value.ToString().IsInt() && Convert.ToInt32(value) > 0){values = new RouteValueDictionary(new { });return true;}return false;}
}public class UsersController : Controller
{[HttpGet("{id}", Name = "GetUserById")][PositiveIntConstraint]public IActionResult GetUser(int id){// ...}
}

在上面的例子中,PositiveIntConstraint是一个自定义的路由约束,它限制了路由参数 “id” 必须是一个大于 0 的整数。如果不符合这个条件,路由请求将会失败。

4.2 其他高级功能

除了上述的路由参数,Attribute 路由还有其他一些高级功能,包括:

  1. 路由模板:你可以使用和传统路由一样的模板语法来定义 Attribute 路由。比如,[Route("{controller}/{action}/{id}")]
  2. 可选参数:你可以定义可选的路由参数。比如,[Route("products/{id:int?}")],这里 id 是可选的。
  3. 默认值:你可以给路由参数设置默认值。比如,[Route("{controller=Home}/{action=Index}/{id=0}")],这里 controller 的默认值是 Home,action 的默认值是 Index,id 的默认值是 0。
  4. 约束类型:除了整数,你还可以对其他类型的参数进行约束。比如,[HttpGet("{id:guid}")] 可以约束 id 必须是 GUID 类型。
  5. 自定义约束:你可以定义自己的约束。比如,你可以定义一个约束来检查一个字符串是否是一个有效的 email 地址。
  6. 嵌套路由:你可以在一个路由中嵌套另一个路由。比如,[Route("{category}/{product}")],这里 category 和 product 都是路由参数。
  7. 静态和动态路由:你可以结合使用静态和动态路由。比如,[Route("/about")][Route("{id}")] 可以同时存在。

五、示例

好的,以下是一个综合了前面所有内容的示例:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)]
public class PositiveIntConstraint : Attribute, IHttpRouteConstraint
{public bool Match(HttpContext context, RouteData data, string parameterName, out RouteValueDictionary values){var value = data.Values[parameterName];if (value != null && value.ToString().IsInt() && Convert.ToInt32(value) > 0){values = new RouteValueDictionary(new { });return true;}return false;}
}public class UsersController : Controller
{[HttpGet("{id}", Name = "GetUserById")][PositiveIntConstraint]public IActionResult GetUser(int id){// ...}[HttpGet("users/edit/{id:guid}")]public IActionResult EditUser(Guid id){// ...}[HttpPost][Route("users/create")]public IActionResult CreateUser(UserModel model){// ...}[Route("users/deleted/{id}")]public IActionResult DeleteUser(int id){// ...}[Route("users/restore/{id}")]public IActionResult RestoreUser(int id){// ...}[Route("{*url}", Name = "PageNotFound")]public IActionResult PageNotFound(){// ...}
}

在上面的例子中,我们定义了一个 PositiveIntConstraint 约束来限制路由参数必须是一个大于 0 的整数。我们定义了 5 个不同的路由:

  • GetUser 方法可以通过 /users/123 这样的 URL 访问,其中 123 是一个大于 0 的整数。
  • EditUser 方法可以通过 /users/edit/456 这样的 URL 访问,其中 456 是一个 GUID 类型的参数。
  • CreateUser 方法可以通过 /users/create 这样的 URL 访问,不需要任何参数。
  • DeleteUser 方法可以通过 /users/deleted/789 这样的 URL 访问,其中 789 是一个大于 0 的整数。
  • RestoreUser 方法可以通过 /users/restore/1000 这样的 URL 访问,其中 1000 是一个大于 0 的整数。
  • 如果请求的 URL 不符合上面的任何一个路由,那么就会返回 PageNotFound 方法的结果,这个方法会返回一个 404 页面。

六、总结

Attribute路由是一种强大的路由机制,允许我们在 ASP.NET Core 中灵活地定义路由。通过使用各种属性和约束,我们可以精确控制 URL 的生成和解析。Attribute 路由提供了路由参数、可选参数、默认值、约束类型、自定义约束、嵌套路由、静态和动态路由等高级功能。这使得我们能够构建复杂而强大的 Web 应用程序,同时也提高了代码的可读性和可维护性。通过合理地使用 Attribute 路由,我们可以提升 Web 应用程序的性能和用户体验。

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

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

相关文章

线性代数逆矩阵的求法

在线性代数中&#xff0c;逆矩阵是一个非常重要且有趣的概念。一个 n 阶方阵 A 的逆矩阵&#xff0c;记作 A^-1&#xff0c;是指存在另一个 n 阶方阵 B&#xff0c;使得 A 和 B 的乘积等于单位矩阵 E&#xff0c;即&#xff1a; A * B E 或者等价地&#xff1a; B * A E 这里…

uniapp技术积累

2024.01.19 1.textarea &#xff08;1&#xff09;默认文字样式设置 placeholder-style"color:rgba(0,0,0,0.7)" 2024.01.18 1.hbuilderx运行uniapp到ipad&#xff08;复用率低&#xff09; &#xff08;1&#xff09;电脑端&#xff1a;首先会有一个运行工具包&…

只用Mysql搞一个分布式锁

在web开发中&#xff0c;分布式的锁的应用场景甚多&#xff0c;我们可以通过分布式锁来进行一些仅依赖于数据库的事务很难直接保证原子性的操作&#xff0c;比如多种不同数据源的访问&#xff0c;网络通信等等。多数情况下我们会使用memcache的add, redis中在set中指定nx参数等…

怎么用小程序将身份证转为结构化Excel?

随着科技的不断发展&#xff0c;我们的生活变得越来越智能化。现在&#xff0c;我们可以使用金鸣表格文字识别小程序来识别身份证并转为结构化的excel&#xff0c;并且可自动核对真伪&#xff0c;保留头像。金鸣表格文字识别小程序是一种基于人工智能技术的应用程序&#xff0c…

nacos,nginx及java服务自重启

微服务之服务自重启 设置Nacos开机自启在/lib/systemd/system文件夹下创建nacos.service文件 [Unit] Descriptionnacos Afternetwork.target[Service] Typeforking ExecStart/opt/nacos-server-1.4.1/nacos/bin/startup.sh -m standalone ExecReload/opt/nacos-server-1.4.1/…

将字符串中的制表符替换为指定数量的空格expandtabs()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 将字符串中的制表符 替换为指定数量的空格 expandtabs() [太阳]选择题 请问以下代码text3的空白处是&#xff1f; text1 "这里有一个\t制表符" text2 "这里有一个12345制表符…

第二次作业+第三次作业

第二次作业第三次作业 第二次作业 题目&#xff1a; 网站需求&#xff1a; ​ 1.基于域名[www.openlab.com](http://www.openlab.com)可以访问网站内容为 welcome to openlab!!! 2.给该公司创建三个子界面分别显示学生信息&#xff0c;教学资料和缴费网站&#xff0c;基于[ww…

利用HTML+CSS+JS打造炫酷时钟网页的完整指南

引言 在现代Web开发中&#xff0c;制作一个引人注目的时钟网页是一种常见而令人愉悦的体验。本文将介绍如何使用HTML、CSS和JavaScript来创建一个炫酷的时钟网页&#xff0c;通过这个项目&#xff0c;你将学到如何结合这三种前端技术&#xff0c;制作一个动态且美观的时钟效果…

vue 中的watch 的deep属性

在 Vue 中&#xff0c;watch 是一个用于观察和响应 Vue 实例上的数据变化的选项。当你在一个属性上设置 watch 时&#xff0c;Vue 会监视该属性的变化并在变化时执行相应的回调函数。 deep 属性是 watch 选项的一个属性&#xff0c;用于深度观察一个对象的变化。默认情况下&am…

深入探索 Android 中的 Runtime

深入探索 Android 中的 Runtime 一、什么是 Runtime二、Android 中的 Runtime 类型2.1. Dalvik Runtime2.2. ART&#xff08;Android Runtime&#xff09; 三、Runtime 的作用和特点3.1. 应用程序执行环境3.2. 跨平台支持3.3. 性能优化3.4. 应用程序优化 四、与应用开发相关的重…

Unity3D Pico VR 手势识别物体交互 适配 MRTK3

当前Pico已经支持手势识别了&#xff0c;但是提供的PICO Unity Integration SDK 中是没有手势和物体交互的功能&#xff0c;Unity XR Interaction Toolkit提供的手势识别物体交互对 Quest适配的挺好的&#xff0c;Pico 当前只能用指尖点触还不能对物体进行抓握以及手势控制射线…

ubuntu18.04以上版本使用systemd 开启自启动服务

进入/etc/systemd/system/目录&#xff0c;创建myscript.service&#xff0c;并赋予权限 sudo vim /etc/systemd/system/myscript.service [Unit] DescriptionMy Script Service Afternetwork.target [Service] Userroot ExecStart/home/start.sh Restartalways [Install]…

【水文】打印99乘法表

#include <stdio.h> int main() { for (int i 1; i < 9; i) { for (int j 1; j < i; j) { printf("%d*%d%d\t", j, i, i * j); } printf("\n"); } return 0; }

JS-WebAPIs-其他事件(三)

• 页面加载事件 页面加载事件主要有二种事件&#xff0c;分别是load和DOMContentLoaded 加载外部资源&#xff08;如图片、外联CSS和JavaScript等&#xff09;加载完毕时触发的事件为什么要学&#xff1f; 有些时候需要等页面资源全部处理完了做一些事情老代码喜欢把 scrip…

JAVA如何创建对象

在 Java 中创建对象的步骤如下&#xff1a; 定义一个类&#xff1a;在 Java 中&#xff0c;所有的对象都是通过类来创建的。因此&#xff0c;首先需要定义一个类&#xff0c;即描述对象的属性和行为。 声明变量&#xff1a;要创建一个对象&#xff0c;需要先声明一个变量来保存…

Spring MVC的面试知识点

1、Spring MVC的入口是什么&#xff1f; Spring MVC的入口是DispatcherServlet。这个Servlet是Spring MVC框架的关键组件&#xff0c;负责接收所有来自客户端的请求&#xff0c;并将其分派给适当的Controller对象进行处理。在Spring MVC框架中&#xff0c;所有的请求都会经过D…

redisson-spring-boot-starter 自动化配置源码解析

版本 redisson-spring-boot-starter:3.25.2 此starter会自动注册RedissonClient Bean 并可通过注册RedissonAutoConfigurationCustomizer Bean实现配置自定义 BeanRedissonAutoConfigurationCustomizer jdkCodecCustomizer() {return configuration->{// 使用JDK序列化器c…

Hadoop详解

Hadoop 概念 就是一个大数据解决方案。它提供了一套分布式系统基础架构。 核心内容包含 hdfs 和mapreduce。hadoop2.0 以后引入 yarn. hdfs 是提供数据存储的&#xff0c;mapreduce 是方便数据计算的。 hdfs 又对应 namenode 和 datanode. namenode 负责保存元数据的基本信息…

移动端自适应解决方法(adaptive插件,原理是rem布局)

点击跳转官方Git地址 此博客参考笔记 也可以直接复制下方的js文件直接使用 index.js var adaptive {}; (function (win, lib) {var doc win.document;var docEl doc.documentElement;// 设备像素比var devicePixelRatio win.devicePixelRatio;// 我们设置的布局视口与理…

docker使用Dockerfile制做容器(以hyperf为列,开机启动)

1、Dockerfile文件 FROM hyperf/hyperf:8.1-alpine-v3.18-swoole WORKDIR /data MAINTAINER dade <dadeqq.com> ADD start.sh start.sh RUN chmod x ./start.sh CMD /data/start.sh1-1、执行命令生成hyperf:latest容器&#xff08;文件名是Dockerfile可以省略&#xff0…