如何在 ASP.NET Core 中使用 Route 特性

ASP.NET Core 中的 Route 中间件的职责在于将 request 匹配到各自 Route 处理程序上,Route 分两种:基于约定基本特性 模式。

基于约定 模式的Route采用集中化的方式,而 基于特性 的方式允许你在 Action 或者 Controller 上单独定义,到底采用哪一种可以基于你自己的应用场景,本篇就来讨论如何使用 基于特性 模式。

创建 Controller 类

创建一个 DefaultController 类,新增如下代码。


    public class DefaultController : Controller
    {
        [Route("")]
        [Route("Default")]
        [Route("Default/Index")]
        public ActionResult Index()
        {
            return new EmptyResult();
        }
        [Route("Default/GetRecordsById/{id}")]
        public ActionResult GetRecordsById(int id)
        {
            string str = string.Format
            ("The id passed as parameter is: {0}", id);
            return Ok(str);
        }
    }

Controller 级别定义 Route 特性

Route特性可用于 Controller 和 Action 级别,值得注意的是,如果应到到前者,那么 Controller 下的所有 Action 都受这个 Route 管控。

如果你仔细观察上面的 DefaultController 类代码,你会发现两个 Action 方法的 Route 路径都有 Default 前缀,这就不优雅了,优化方式就是把 Route 路径中的 Default 提取到 Controller 级别,代码如下:


[Route("Default")]   
public class DefaultController : Controller
{
  [Route("")]
  [Route("Index")]
  public ActionResult Index()
  {
      return new EmptyResult();
   }
  [HttpGet]
  [Route("GetRecordsById/{id}")]
  public ActionResult GetRecordsById(int id)
  {
      string str = string.Format("The id passed as parameter is: {0}", id);
      return Ok(str);
   }
}

可以看出当 Controller 和 Action 级别都被 Route 打上标记之后,Asp.Net Core 中的 Route 引擎会自动将两者拼接起来,当然更简单粗暴的做法就是在 Controller 上使用 RoutePrefix 特性,如下代码所示:


[RoutePrefix("services")]
public class HomeController : Controller
{
   //Action methods
}

Action 级别定义 Route 特性

参考刚才的 DefaultController 类,我在 Index 方法上面定义了三个 Route 特性,这就意味着下面三种 Route 都可以访问到 Index() 方法,如下代码所示:


http://localhost:11277
http://localhost:11277/home
http://localhost:11277/home/index


常常在 基于约定 模式的Route中,它的 Route template 会有一些对参数的约定,比如下面的代码:


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

同样 基于特性 模式的 Route 也是可以使用参数模式的,比如文章之前的 DefaultController.GetRecordsById 就是的,值得注意的是模板中的 {id} 表示可接收任何参数,如 string,int 等等,如果你想限定为 int 的话,也是可以实现的。

使用 Route 约束

Route 约束 就是 Controller 前的一个防火墙,他会踢掉一些不合规范的 Action 请求,比如说:你要求某个 Action 接收的参数必须是 int,那在 Route 模板中定义的语法格式一定是这样的 {parameter:constraint},如下代码所示:


[Route("Default/GetRecordsById/{id:int}")]
public ActionResult GetRecordsById(int id)
{
  string str = string.Format("The id passed as parameter is: {0}", id);
  return Ok(str);
}

在 Route 中使用可选参数

你也可以在 Route Template 上指定可选参数,意味着这个参数可传可不传,格式如下:


[Route("Sales/GetSalesByRegionId/{id?}")]

有一点非常重要,当你使用了 Route特性 之后,其实 Controller 或者 Action 的名字就不再重要了,因为 Route处理引擎 已经不再将其作为参考选项,下面的代码片段展示了如何在 Action 方法上变更 Route template 格式。


[Route("Home/GetRecordsById/{id:int}")]
public ActionResult GetRecordsById(int id)
{
   string str = string.Format("The id passed as parameter is: {0}", id);
   return Ok(str);
}

接下来可以直接使用如下地址访问 GetRecordsById 方法。


http://localhost:11277/home/GetRecordsById/1

对 Action 中的参数使用多个约束

真实场景中你不仅要求 id 必须是整数,还要求必须有一定意义,比如说最小值为1,对这种有 多重约束 的需求如何去实现呢?请看下面代码。


[Route("Default/GetRecordsById/{id:int:min(1)}")]
public ActionResult GetRecordsById(int id)
{
    string str = string.Format("The id passed as parameter is: {0}", id);
    return Ok(str);
}

常使用的 Route 约束

  • int       限定为 int 类型

  • max/min   限定 int 的最大数和最小数

  • minlength 限定 string 的最小长度

  • regex     限定符合的正则

创建自定义的 Route 约束

如果上面的一些约束不满足你的要求,你完全可以为你的场景深度定制,做法就是使用 IRouteConstraint 接口并实现它的 Match 方法即可,如下代码所示:


    public class CustomRouteConstraint : IRouteConstraint
    {
        public bool Match(HttpContext httpContext, IRouter route,
        string routeKey,
        RouteValueDictionary values, RouteDirection routeDirection)
        {
            throw new NotImplementedException();
        }
    }

在 Controller 上使用 token 占位符

所谓的 token 占位符 就是具有一些特定含义的占位符号,比如说:[action], [area] 和 [controller],分别表示用你真实的 Controller 和 Action 去替换,下面的代码展示了如何使用这种模式去实现。


[Route("[controller]/[action]")]
public class HomeController : Controller
{
   private readonly ILogger<HomeController> _logger;
   public HomeController(ILogger<HomeController> logger)
   {
       _logger = logger;
   }
   public IActionResult Index()
   {
       return View();
   }
   //Other action methods
}

整体来看,基于特性 的 Route 给了你更多的操控权限,灵活的 Route Template 配置实现了 Controller 和 Action 的解耦,当然这里也不是说 基于约定 的Route 不好,毕竟人家是 Global 级别的,真实场景下两者更多的是混着用。

译文链接:https://www.infoworld.com/article/3569369/how-to-use-attribute-routing-in-aspnet-core.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ASP.Net Core MVC上传文件,可以使用以下步骤: 1. 在视图添加一个表单,包含一个文件输入控件: ```html <form method="post" enctype="multipart/form-data"> <div class="form-group"> <label for="file">选择文件:</label> <input type="file" name="file" id="file" class="form-control-file" /> </div> <button type="submit" class="btn btn-primary">上传</button> </form> ``` 2. 在控制器添加一个动作方法,用于接收上传的文件: ```csharp [HttpPost] public async Task<IActionResult> Upload(IFormFile file) { if (file == null || file.Length == 0) { return BadRequest("请选择文件"); } using (var stream = new MemoryStream()) { await file.CopyToAsync(stream); // 处理上传的文件 // ... return Ok("上传成功"); } } ``` 3. 在Startup.cs文件的ConfigureServices方法添加文件上传服务: ```csharp services.AddMvc(options => { options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()); // 添加防伪标记,防止跨站攻击 }).AddRazorPagesOptions(options => { options.Conventions.AddPageRoute("/Index", ""); }) .AddNewtonsoftJson(); // 添加NewtonsoftJson,用于序列化JSON services.AddControllersWithViews(); // 添加控制器和视图 services.AddRazorPages(); // 添加Razor页面 services.AddAntiforgery(); // 添加防伪标记,防止跨站攻击 services.Configure<IISServerOptions>(options => { options.AllowSynchronousIO = true; // 允许同步IO }); services.Configure<FormOptions>(options => { options.MultipartBodyLengthLimit = long.MaxValue; // 设置允许上传的最大文件大小 }); ``` 以上就是在ASP.Net Core MVC上传文件的步骤。需要注意的是,要添加防伪标记,防止跨站攻击;要设置允许上传的最大文件大小。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值