C# 如何在ASP.NET CORE 3.0中配置路由以使用带[FromQuery]参数的重载[HttpGet]方法?

C# 如何在ASP.NET CORE 3.0中配置路由以使用带[FromQuery]参数的重载[HttpGet]方法?,c#,controller,restful-url,asp.net-core-3.0,asp.net-core-routing,C#,Controller,Restful Url,Asp.net Core 3.0,Asp.net Core Routing,对不起,我不擅长这个题目,如果你知道更好的题目来描述问题的内容,请告诉我 所以我有两个方法,第一个是获取所有列表项,第二个也是获取所有列表项,但是,第二个方法上有一个查询参数,我用它来过滤,第二个方法也返回一个与第一个方法不同的对象。因为我有两个Http get方法,它们都指向同一个路由,所以当我调用其中一个方法时: Microsoft.AspNetCore.Routing.Matching.AmbiguousMatchException:异常 请求匹配多个端点。比赛: 如何在不合并这两种方法或

对不起,我不擅长这个题目,如果你知道更好的题目来描述问题的内容,请告诉我

所以我有两个方法,第一个是获取所有列表项,第二个也是获取所有列表项,但是,第二个方法上有一个查询参数,我用它来过滤,第二个方法也返回一个与第一个方法不同的对象。因为我有两个Http get方法,它们都指向同一个路由,所以当我调用其中一个方法时:

Microsoft.AspNetCore.Routing.Matching.AmbiguousMatchException:异常 请求匹配多个端点。比赛:

如何在不合并这两种方法或使用可选参数或更改一种方法的路径的情况下解决此问题?如果可能的话

示例代码:

// GET: api/Resources
[HttpGet]
public async Task<ActionResult<ICollection<Data>>> GetAll()
{
    return Ok(await Service.GetAll());
}

// GET: api/Resources
[HttpGet]
public async Task<ActionResult<Data2>> GetAll([FromQuery]int parameter)
{
    return Ok(await Service.GetAll2(parameter));
}

编辑:按照注释建议尝试在这样的配置中使用操作

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute("default", "{controller}/{action}/{id?}");
});
它不起作用,因为在我执行get请求时调用了错误的方法, 例如,第一个getall方法:api/resources/getall 下面的方法会被触发,但会导致错误,因为getall不是int

// GET: api/Resources/5
[HttpGet("{id}")]
public async Task<ActionResult<Data>> GetById(int id)
{
    return Ok(await Service.GetById(id));
}
//GET:api/Resources/5
[HttpGet(“{id}”)]
公共异步任务


现在操作正常,必须更改控制器中的属性路由

[Route("api/[controller]/[action]")]
[ApiController]
public class ResourcesController : ControllerBase
{
    // GET: api/Resources/GetAll
    [HttpGet]
    public ActionResult<ICollection<string>> GetAll()
    {
        return Ok(new List<string>() { "foo", "bar" });
    }

    // GET: api/Resources/GetAll2?parameter="bar"
    [HttpGet]
    public ActionResult<string> GetAll2([FromQuery]string parameter)
    {
        return Ok(parameter);
    }

    // GET: api/Resources/GetById/5
    [HttpGet("{id}")]
    public ActionResult<int> GetById(int id)
    {
        return Ok(id);
    }
}
[路由(“api/[控制器]/[操作]”)
[ApiController]
公共类资源控制器:ControllerBase
{
//获取:api/Resources/GetAll
[HttpGet]
公共行动结果GetAll()
{
返回Ok(新列表(){“foo”,“bar”});
}
//获取:api/Resources/GetAll2?parameter=“bar”
[HttpGet]
public ActionResult GetAll2([FromQuery]字符串参数)
{
返回Ok(参数);
}
//获取:api/Resources/GetById/5
[HttpGet(“{id}”)]
公共操作结果GetById(int id)
{
返回Ok(id);
}
}
虽然如果没有不同的路径就不可能实现这一点,但我将只更改一个方法的路径,而不是在控制器中使用动作,并且在调用方法时必须在路径中添加动作名称

更新1:我在几周后遇到的另一个可能有效的方法(没有测试)是使用路由约束,如中所示

更新2:差不多一年之后,我决定查找查询参数约束, 我在stackoverflow上遇到了一个问题,答案是这是不可能的,尽管这个问题已经很老了,所以

如何在不合并这两种方法或使用可选参数或更改一种方法的路径的情况下解决此问题?如果可能的话

如果您希望在不合并这两个动作或在路由中指定动作名称的情况下使其工作,可以尝试使用
Http[Verb]属性
使第二个动作接受路由数据中的参数,如下所示

// GET: api/Resources
[HttpGet]
public async Task<ActionResult<ICollection<Data>>> GetAll()
{
    return Ok(await Service.GetAll());
}


// GET: api/Resources/1
[HttpGet("{parameter:int}")]
public async Task<ActionResult<Data2>> GetAll([FromRoute]int parameter)
{
    return Ok(await Service.GetAll2(parameter));
}
//GET:api/Resources
[HttpGet]
公共异步任务GetAll()
{
返回Ok(等待Service.GetAll());
}
//获取:api/Resources/1
[HttpGet(“{parameter:int}”)]
公共异步任务GetAll([FromRoute]int参数)
{
返回Ok(wait Service.GetAll2(参数));
}
此外,在我看来,合并这两个操作并使用可选参数会更好。我想知道什么场景需要不使用这种方法来实现需求

[HttpGet("{parameter:int?}")]
public async Task<IActionResult> GetAll([FromQuery]int parameter)
{
    if (parameter == 0)
    {
        return Ok(await Service.GetAll());
    }
    else
    {
        return Ok(await Service.GetAll2(parameter));
    }
}
[HttpGet(“{parameter:int?}”)]
公共异步任务GetAll([FromQuery]int参数)
{
如果(参数==0)
{
返回Ok(等待Service.GetAll());
}
其他的
{
返回Ok(wait Service.GetAll2(参数));
}
}

作为参考,我创建了一个新的web api asp.net core 3项目

另外,假设您在Startup.cs上注册了默认路由。
endpoints.mapDefaultControllerOute()

添加

[Route("api/[controller]/[action]")]
[ApiController]
在控制器启动时,会覆盖启动,因此您不必担心其他控制器

如果Id是可选参数,您也无法实现这一点。 你会变得模棱两可。由于GetAll()和GetAll(int参数)完全相同,因为我们已将该参数声明为可选参数。这就是为什么会出现错误

还要注意,在第二次GetAll()时,我在HttpGet中添加了参数

这只是为了更新路由引擎,该路由将有一个参数,因为在我的文件顶部的通用级别上,我将注册该操作

要获得更多参数,您可以这样做。
[HttpGet({parameter}/{resourceId})]


然后,您的路径将类似于此api/Resource/GetAll/2/4

你的问题在于路由而不是方法。您能提供您的web api配置吗?默认情况下,它有一个api/{controller}/{id},这可能是非常有问题的。因为如果您的web api中有两个方法具有相同的参数控制器,那么您会遇到歧义,换句话说,就是您的错误,请查看这个问题的答案->@panoskarajohn,那么我必须使用操作?没有别的办法吗?不幸的是,没有。你对路线的要求越具体。你得到的含糊不清就越少。由于api忽略了动作,所以两种方法之间的歧义并不少见。你必须重新考虑你的web api设计。您可以参考文档了解更多信息->@panoskarajohn知道如何在.NET Core 3.0中运行这些操作吗?我尝试了:app.UseEndpoints(endpoints=>{endpoints.mapcontrollerOute(“默认值”),“{controller}/{action}/{id?}”);});但是不起作用。是的,但是,我从查询中得到的参数变量,不是资源的一个id,所以将它作为路径变量对路径没有意义,合并是我真的不想做的事情。我正试图通过使用问题下面的注释建议的操作来让它起作用,但是
[Route("api/[controller]/[action]")]
[ApiController]
using Microsoft.AspNetCore.Mvc;

namespace WebApiTest.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class ResourceController : ControllerBase
    {

        [HttpGet]
        //api/Resource/GetAll
        public IActionResult GetAll()
        {
            return Content("I got nth");
        }

        //GET: //api/Resource/GetAll/2
        [HttpGet("{parameter}")]
        public IActionResult GetAll(int parameter)
        {
            return Ok($"Parameter {parameter}");
        }

    }
}