ASP Core 3.1路由

时间:2020-06-23 10:12:26

标签: c# asp.net-core asp.net-core-routing

我在一个控制器中有2个HttpGet端点。为了使路由不同,我向其中之一添加了参数。看下一个代码

[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase
{
    [HttpGet("{id:decimal}")]
    public async Task<IActionResult> Get(decimal id)
    {
        var user = await User.GetAsync(id);
        return Ok(user);
    }

    [HttpGet]
    public async Task<IActionResult> GetAll()
    {
        var users = await User.GetAllAsync();
        return Ok(users);
    }
}

问题是第一个端点不可访问。即使查询id中有http://localhost:80/api/user?id=1个参数,我也达到了第二个端点。 期望的行为是

  1. 请求http://localhost:80/api/user?id=1->第一个端点
  2. 请求http://localhost:80/api/user->第二个端点

这一定是愚蠢的,因为我确定我以前做过同样的事情,但是现在我坚持了

2 个答案:

答案 0 :(得分:3)

使用时

[HttpGet("{id:decimal}")]

这意味着您的网址就像

http://localhost:80/api/user/{id}

OR

http://localhost:80/api/user/1

答案 1 :(得分:1)

期望的行为是

1.Request http://localhost:80/api/user?id=1->第一个端点

2.Request http://localhost:80/api/user->第二端点

如果您想匹配请求并将其基于查询字符串映射到预期的操作,则可以尝试实现自定义ActionMethodSelectorAttribute,如下所示。

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class QueryStringConstraintAttribute : ActionMethodSelectorAttribute
{
    public string QueryStingName { get; set; }
    public bool CanPass { get; set; }
    public QueryStringConstraintAttribute(string qname, bool canpass)
    {
        QueryStingName = qname;
        CanPass = canpass;
    }
    public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor action)
    {
        StringValues value;

        routeContext.HttpContext.Request.Query.TryGetValue(QueryStingName, out value);

        if (QueryStingName == "" && CanPass)
        {
            return true;
        }
        else
        {
            if (CanPass)
            {
                return !StringValues.IsNullOrEmpty(value);
            }

            return StringValues.IsNullOrEmpty(value);
        }
    }
}

应用于操作

[HttpGet]
[QueryStringConstraintAttribute("id",true)]
[QueryStringConstraintAttribute("", false)]
public async Task<IActionResult> Get([FromQuery]decimal id)
{
    //var user = await User.GetAsync(id);
    //return Ok(user);
    
    //for test purpose
    return Ok("ActionWithQueryString");
}

[HttpGet]
[QueryStringConstraintAttribute("id", false)]
[QueryStringConstraintAttribute("", true)]
public async Task<IActionResult> GetAll()
{
    //var users = await User.GetAllAsync();
    //return Ok(users);

    //for test purpose
    return Ok("ActionWithOutQueryString");
}

测试结果

enter image description here