iT邦幫忙

2021 iThome 鐵人賽

DAY 2
0
自我挑戰組

.NET Core WebApi網頁應用開發系列 第 10

.Net Core Web Api_筆記10_路由約束

針對屬性路由可以透過Route() 或 Http verbs方式來設置路由模板
在路由模板當中我們還能夠透過"約束路由"來對參數進行約束。

語法格式

參數:約束

若沒有做一些格式約束往往會造成系統漏洞
甚至可能會讓系統出錯的問題

約束種類共分為以下幾種
1.參數約束
2.函數約束
3.正規表示式約束

1.參數約束
以之前的範例就是要以int 來做person的id查詢
https://ithelp.ithome.com.tw/upload/images/20210920/20107452rFOnU3ZooK.png

我們這裡就約束參數必為int
[HttpGet("GetPersonById/{id:int}")]

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using NetCoreApiTest1.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace NetCoreApiTest1.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class StudentController : ControllerBase
    {
        [HttpGet("GetPersonById/{id:int}")]
        public ActionResult<Person> GetPerson(int id)
        {
            List<Person> lsPersons = new List<Person>()
            {
                new Person(){Id=1,Name="Amy",Age=22,Sex="woman"},
                new Person(){Id=2,Name="Jessica",Age=25,Sex="woman"},
                new Person(){Id=3,Name="Banson",Age=24,Sex="man"}
            };
            return lsPersons.Where(item => item.Id == id).FirstOrDefault();
        }
    }
}

2.函數約束

可針對傳入的參數透過函數約束的計算來作條件的過濾操作

以我們的Person List來說目前最大只有到3最小則是1
就可以透過以下這些含數約束語法做限制

{id:min(1)}
[HttpGet("GetPersonById/{id:min(1)}")]
https://ithelp.ithome.com.tw/upload/images/20210920/20107452DNsF0gbk54.png

{id:max(3)}
[HttpGet("GetPersonById/{id:max(3)}")]
https://ithelp.ithome.com.tw/upload/images/20210920/20107452YJeIQooHS1.png

當然也可以兩個複合寫
[HttpGet("GetPersonById/{id:min(1):max(3)}")]

https://ithelp.ithome.com.tw/upload/images/20210920/20107452nfJkn4fyq3.png

或者也可以跟參數格式約束複合搭配然後用range設置上下限約束

{id:max:range(1,3)}
[HttpGet("GetPersonById/{id:int:range(1,3)}")]

也有一樣效果

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using NetCoreApiTest1.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace NetCoreApiTest1.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class StudentController : ControllerBase
    {
        //[HttpGet("GetPersonById/{id:min(1)}")]
        //[HttpGet("GetPersonById/{id:max(3)}")]
        //[HttpGet("GetPersonById/{id:min(1):max(3)}")]
        [HttpGet("GetPersonById/{id:int:range(1,3)}")]
        public ActionResult<Person> GetPerson(int id)
        {
            List<Person> lsPersons = new List<Person>()
            {
                new Person(){Id=1,Name="Amy",Age=22,Sex="woman"},
                new Person(){Id=2,Name="Jessica",Age=25,Sex="woman"},
                new Person(){Id=3,Name="Banson",Age=24,Sex="man"}
            };
            return lsPersons.Where(item => item.Id == id).FirstOrDefault();
        }
    }
}

3.正規表示式約束

比方傳入進來的參數代表的可能是名字
不可以是整數或者小數之類的只能是字串可能大小寫a~z組合

https://ithelp.ithome.com.tw/upload/images/20210920/20107452OgjKf08wey.png

或者年齡只能是純數字
https://ithelp.ithome.com.tw/upload/images/20210920/201074529SmWH3X9rs.png

這裡順帶提及到正規表示式在寫的時候
由於有些會有方括號
剛好會跟上一篇提到的Route Template中占位符裡面的
中方括號[] , 又固定只包含三種關鍵字[控制器]、[動作]、[區域]
[controller] , [action] , [area]
這個有衝突

因此在寫得時候要用雙重中方括號來區分是屬於正規表示式的函數約束

不然直接用一般正規表示式寫就可能會報
Replacement value for the token could not be found的錯誤

以下是測試程式碼

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using NetCoreApiTest1.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace NetCoreApiTest1.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class StudentController : ControllerBase
    {
        //[HttpGet("GetPersonById/{id:min(1)}")]
        //[HttpGet("GetPersonById/{id:max(3)}")]
        //[HttpGet("GetPersonById/{id:min(1):max(3)}")]
        [HttpGet("GetPersonById/{id:int:range(1,3)}")]
        public ActionResult<Person> GetPerson(int id)
        {
            List<Person> lsPersons = new List<Person>()
            {
                new Person(){Id=1,Name="Amy",Age=22,Sex="woman"},
                new Person(){Id=2,Name="Jessica",Age=25,Sex="woman"},
                new Person(){Id=3,Name="Banson",Age=24,Sex="man"}
            };
            return lsPersons.Where(item => item.Id == id).FirstOrDefault();
        }

        [HttpGet("GetPersonByAge/{age:regex(\\d)}")]
        public ActionResult<Person> GetPersonUseAge(int age)
        {
            List<Person> lsPersons = new List<Person>()
            {
                new Person(){Id=1,Name="Amy",Age=22,Sex="woman"},
                new Person(){Id=2,Name="Jessica",Age=25,Sex="woman"},
                new Person(){Id=3,Name="Banson",Age=24,Sex="man"}
            };
            return lsPersons.Where(item => item.Age == age).FirstOrDefault();
        }


        [HttpGet("GetPersonByName/{name:regex([[^0-9)]])}")]
        public ActionResult<Person> GetPersonUseName(string name)
        {
            List<Person> lsPersons = new List<Person>()
            {
                new Person(){Id=1,Name="Amy",Age=22,Sex="woman"},
                new Person(){Id=2,Name="Jessica",Age=25,Sex="woman"},
                new Person(){Id=3,Name="Banson",Age=24,Sex="man"}
            };
            return lsPersons.Where(item => item.Name == name).FirstOrDefault();
        }
    }
}

Ref:
Route Constraints in ASP.NET Core Web API
https://dotnettutorials.net/lesson/route-constraints-asp-net-core-web-api/

Route Constraints In ASP.net Core
https://dotnetcoretutorials.com/2017/06/25/route-constraints-asp-net-core/

WebAPI Regex path attribute throws error "Replacement value for the token could not be found"
https://stackoverflow.com/questions/60726746/webapi-regex-path-attribute-throws-error-replacement-value-for-the-token-could

本篇已同步發表至個人部落格
https://coolmandiary.blogspot.com/2021/09/net-core-web-api10.html


上一篇
.Net Core Web Api_筆記09_web api的屬性路由模板兩種寫法_路由模板使用
下一篇
.Net Core Web Api_筆記11_組合路由
系列文
.NET Core WebApi網頁應用開發16

尚未有邦友留言

立即登入留言