简体   繁体   中英

ASP Core 3.1 Routing

I have 2 HttpGet endpoints in a single controller. In order to make routes different I added parameter to the one of them. Look at the next code

[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);
    }
}

The problem is that the first endpoint is inaccessible. I hit the second endpoint even if I have id parameter in the query http://localhost:80/api/user?id=1 . Desired behavior is

  1. Request http://localhost:80/api/user?id=1 -> first endpoint
  2. Request http://localhost:80/api/user -> second endpoint

It must be something stupid-simple, because I'm sure I did the same way before, but now I stuck

when you use

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

it's mean your Url is like

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

OR

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

Desired behavior is

1.Request http://localhost:80/api/user?id=1 -> first endpoint

2.Request http://localhost:80/api/user -> second endpoint

If you'd like to match request(s) and map them to expected action(s) based on the querystring, you can try to implement a custom ActionMethodSelectorAttribute , like below.

[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);
        }
    }
}

Apply to Action(s)

[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");
}

Test Result

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM