【问题标题】:Asp.Net WebApi - Multiple actions were found that match the requestAsp.Net WebApi - 找到与请求匹配的多个操作
【发布时间】:2016-12-18 21:15:00
【问题描述】:

将 routeTemplate 定义为“api/{controller}/{id}”并在我的控制器 (ValuesController) 中有以下方法

    [HttpGet]
    public IEnumerable<string> GetX()
    {
        return new string[] { "xx1", "xx2" };
    }

    [HttpGet]
    public IEnumerable<string> GetY([FromUri]Customer c)
    {
        return new string[] { "c1", "c2" };
    }

     public class Customer
     {
        public bool IsMarried { get; set; }
        public string CustName { get; set; }
     }

使用 url - "/api/values?IsMarried=false&CustName=aa" 会导致错误 - "Multiple actions were found that match the request..." 。 如果不将 routeTemplate 更改为“api/{controller}/{action}/{id}”之类的内容,我无法解决上述问题。 如果有人知道如何在不更改 routeTemplate 的情况下解决上述问题,请建议。

【问题讨论】:

  • 您可以使用[Route("...")] 指令仅为特定控制器定义不同的路径。
  • 谢谢@TasosK。期待你的答复。看起来添加“Route”属性在我的特定情况下可能没有帮助,因为我正在使用的客户端由于某些原因只能调用 REST url(即不使用操作名称)。

标签: asp.net asp.net-web-api2


【解决方案1】:

解决方案一:路由

[RoutePrefix("api")]
public class FooController : ApiController
{
    [Route("Foo/getall")]
    [HttpGet]
    public IEnumerable<string> GetX()
    {
        return new string[] { "xx1", "xx2" };
    }

    [Route("foo/search")]
    [HttpGet]
    public IEnumerable<string> GetY([FromUri]Customer c)
    {
        return new string[] { "c1", "c2" };
    }

    public class Customer
    {
        public bool IsMarried { get; set; }
        public string CustName { get; set; }
    }
}

记得添加属性路由映射:

configuration.MapHttpAttributeRoutes();

方案二:可选参数

[RoutePrefix("api")]
public class FooController : ApiController
{
    [HttpGet]
    public IEnumerable<string> GetY([FromUri]Customer c)
    {
        if(c == null)
           // no parameters where set.

        if(c.IsMarried != null)
           // do stuff
        // etc....
        return new string[] { "c1", "c2" };
    }

    public class Customer
    {
        public bool? IsMarried { get; set; }
        public string CustName { get; set; }
    }
}

【讨论】:

  • 感谢您的回答。是的,这两种方法应该有效。对于我正在使用的客户端应用程序中的方法,我可能无法在 url 中提供特定的路由名称,即。它只能调用“api/Values?...”。基本上我想问为什么我得到“找到多个操作......”错误不能 webApi 映射到基于查询字符串的更正操作?看起来我在这里遗漏了一些东西,
  • @SunilThakur - 不,你没有遗漏任何东西。对于任何 1 个控制器,您可以根据操作名称(使用 Route 属性)或(默认情况下)在 Http Action 动词(get、put、post 等)上进行路由。你不能基于参数路由,它不像 c# 基于参数类型的方法重载。
  • 我可以在同一个控制器中拥有这样的方法 - Get()、Get(string x)、Get(string x, string y) 等 - 并且 web-api 根据提供的参数调用相应的方法在查询字符串中,即。 “api/Values”将调用 Get(),“api/Values?x=2”将调用 Get(string x) 等。如果在操作方法参数中仅指定简单类型,它就可以正常工作。只有当我们将复杂类型(在 Get 方法中)作为参数时,它才会中断。
  • 基本上就像@Petre Turcu 所描述的那样。
【解决方案2】:

如果您不能指定动作名称,那么您有两个选择。

基于参数的动作

创建一个采用默认(引用类型为 null)参数的重载。根据参数的状态,执行适当的操作。由于您的示例非常抽象,我不知道这是否适合您。

[HttpGet]
public IEnumerable<string> GetY([FromUri]Customer c = default(Customer))
{
    if(c == null /* or some other state */)
        return new string[] { "xx1", "xx2" };
    return new string[] { "c1", "c2" };
}

新控制器

创建一个新控制器并在那里定义您的附加操作。如果操作在本质上非常不同,这可能是一个更好的解决方案。这里不需要代码示例,只需创建一个新控制器并移动现有方法即可。

【讨论】:

  • 感谢您的回答。是的,同意这些方法应该有效。我担心的是为什么 web-api 不能在问题中指定的场景中映射到正确的操作方法,看起来我错过了一些关于 web-api 如何映射到操作方法的内容。
【解决方案3】:

使用简单类型并将它们映射到控制器中:

[HttpGet]
public IEnumerable<string> GetY(bool IsMarried, string CustName)
{
    var cust = new Customer {IsMarried = IsMarried, CustName = CustName};
    return new string[] { "c1", "c2" };
}

请注意,您将失去 ModelState.IsValid 等功能,因此您需要手动调用验证器。

查看Action Selection 部分,了解它是如何处理简单参数和复杂参数的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-08
    • 2017-10-26
    • 2016-10-18
    • 2016-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多