字符串路由约束

Fab*_*uez 2 c# routes asp.net-core-mvc asp.net-core-webapi asp.net-core-1.1

我有一个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);
}
Run Code Online (Sandbox Code Playgroud)

第一个工作,但第二个不工作 - .Net不喜欢"字符串"约束.所以基本上,我再次执行HTTPGET请求:

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

它必须执行第一个动作,如果我请求

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

它必须执行第二个...任何想法?谢谢...

Pra*_*mar 6

正如@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);
}
Run Code Online (Sandbox Code Playgroud)

2.您可以如下所示实现自己的路径约束,再次更改正则表达式以满足您的需要.

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

现在,您可以在Startup.cs中映射此自定义路由约束,如下所示

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

自定义路由约束"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);
}
Run Code Online (Sandbox Code Playgroud)