0

我有一個ASP .Net Core 1.1 MVC Web API。如何在控制器操作中有一個字符串路由約束?字符串路由約束

我有以下兩個動作:

/ GET: api/Users/5 
[HttpGet("{id:int}")] 
[Authorize] 
public async Task<IActionResult> GetUser([FromRoute] int id) 
{ 
    if (!ModelState.IsValid) 
     return BadRequest(ModelState); 

    User user = await _context.User.SingleOrDefaultAsync(m => m.UserId == id); 

    if (user == null) 
     return NotFound(); 

    return Ok(user); 
} 

// GET: api/Users/abcde12345 
[HttpGet("{nameIdentifier:string}")] 
[Authorize] 
public async Task<IActionResult> GetUserByNameIdentifier([FromRoute] string nameIdentifier) 
{ 
    if (!ModelState.IsValid) 
     return BadRequest(ModelState); 

    User user = await _context.User.SingleOrDefaultAsync(m => m.NameIdentifier == nameIdentifier); 

    if (user == null) 
     return NotFound(); 

    return Ok(user); 
} 

第一個工作,但第二個不 - .NET不喜歡「串」的約束。所以基本上,ID我再次執行HTTPGET請求:

http://mywebsite.com/api/users/5

必須執行的第一個動作,如果我要求

http://mywebsite.com/api/users/abcde

必須執行第二個...任何想法?謝謝...

回答

2

搜索正如@Aistis提到的,默認情況下,路由數據是字符串。這就是沒有路由約束來強制數據類型爲字符串的原因。如果要將值限制爲特定的字符串值,則使用的字符串約束非常有用,它不能用於將字符串強制爲字符串。有幾個選項可以實現你正在嘗試做的事情。

1.使用正則表達式路由約束。請注意,您需要根據您的需要更改正則表達式。

// GET: api/Users/abcde12345 
[HttpGet("{nameIdentifier:regex(^[[a-zA-Z]])}")] 
[Authorize] 
public async Task<IActionResult> GetUserByNameIdentifier([FromRoute] string nameIdentifier) 
{ 
    if (!ModelState.IsValid) 
     return BadRequest(ModelState); 

    User user = await _context.User.SingleOrDefaultAsync(m => m.NameIdentifier == nameIdentifier); 

    if (user == null) 
     return NotFound(); 

    return Ok(user); 
} 

2.您可以實現自己的路由約束如下,再次更改正則表達式以滿足您的需要。

public class NameIdRouteConstraint : RegexRouteConstraint 
{ 
    public NameIdRouteConstraint() : base(@"([A-Za-z]{3})([0-9]{3})$") 
    { 
    } 
} 

現在,你可以在這個Startup.cs自定義路由約束圖如下

public void ConfigureServices(IServiceCollection services) 
{ 
    // Add framework services. 
    services.AddMvc(); 
    services.Configure<RouteOptions>(options => 
     options.ConstraintMap.Add("nameId", typeof(NameIdRouteConstraint))); 
} 

自定義路由約束「填充NameID」準備如下

// GET: api/Users/abcde12345 
[HttpGet("{nameIdentifier:nameId}")] 
[Authorize] 
public async Task<IActionResult> GetUserByNameIdentifier([FromRoute] string nameIdentifier) 
{ 
    if (!ModelState.IsValid) 
     return BadRequest(ModelState); 

    User user = await _context.User.SingleOrDefaultAsync(m => m.NameIdentifier == nameIdentifier); 

    if (user == null) 
     return NotFound(); 

    return Ok(user); 
} 
+0

謝謝Pradeep。非常詳細的答案! – user1900799

1

不知道我是否正確理解問題,但通過http傳遞的所有內容都是字符串,asp.net可以像第一種方法那樣將字符串轉換爲int,但是您不必強制執行字符串來自您的請求,默認情況下的所有數據都將採用字符串格式。

abc412是一個字符串,所以12352是一個字符串格式,如果你想確保只允許使用字母字符,那麼一旦你接收到數據,你就必須在你的控制器內執行檢查。你的方法已經通過控制器頭

public async Task<IActionResult> GetUserByNameIdentifier([FromRoute] string nameIdentifier) 

你需要做的檢查控制方法中允許的數據並進行相應處理什麼數據接收作爲字符串。

你也可以只具有兩個獨立的APICALLS,按ID搜索,按名稱

+0

感謝您使用這麼多Aistis – user1900799