【问题标题】:Multiple actions were found that match the request Web API?找到多个与请求 Web API 匹配的操作?
【发布时间】:2012-11-08 14:33:26
【问题描述】:

我正在使用 Web API,我是新手。我陷入了路由问题。我有一个具有以下操作的控制器:

    // GET api/Ceremony
    public IEnumerable<Ceremony> GetCeremonies()
    {
        return db.Ceremonies.AsEnumerable();
    }

    // GET api/Ceremony/5
    public Ceremony GetCeremony(int id)
    {
        Ceremony ceremony = db.Ceremonies.Find(id);
        return ceremony;
    }

    public IEnumerable<Ceremony> GetFilteredCeremonies(Search filter)
    {
        return filter.Ceremonies();
    }

当我将操作 GetFilteredCeremonies 添加到我的控制器时,问题发生了。添加此内容后,当我对 GetCeremonies 操作进行 ajax 调用时,它会返回带有以下消息的异常:

"Message":"An error has occurred.","ExceptionMessage":"Multiple actions were 
 found that match the request

仅供参考:参数Search 是模型类,其中包含属性和函数名称仪式。

编辑

路线:

config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

【问题讨论】:

  • 你也可以分享你的路线吗?
  • @alliswell 请检查我的编辑
  • 我认为这和stackoverflow.com/questions/9499794/…是同一个问题
  • 在控制器中有两个名为 GetCeremony() 的方法尝试解决它们,因为它们都指向相同的路由

标签: c# asp.net-web-api


【解决方案1】:

如果您不要求使用使用 api/{controller}/{id} 路由的 REST 服务并尝试基于方法 GET/POST/DELETE 解决操作/PUT,你可以修改你的路由到经典MVC路由到api/{controller}/{action}/{id},它会解决你的问题。

【讨论】:

  • 一个简短而甜蜜的方式。
【解决方案2】:

这里的问题是您的 2 个 Get 方法将解析为 api/Ceremony 并且 MVC 不允许参数重载。此类问题的快速解决方法(不一定是首选方法)是使您的 id 参数可以为空,例如

// GET api/Ceremony
public IEnumerable<Ceremony> GetCeremonies(int? id)
{
    if (id.HasValue)
    {
        Ceremony ceremony = db.Ceremonies.Find(id);
        return ceremony;
    }
    else
    {
        return db.Ceremonies.AsEnumerable();
    }
}

但是,当您尝试查询单个仪式时,当您使用 1 项时,您将返回一个仪式列表 - 如果您可以忍受,那么它可能是您的解决方案。

推荐的解决方案是将您的路径适当地映射到正确的操作,例如

context.Routes.MapHttpRoute(
    name: "GetAllCeremonies",
    routeTemplate: "api/{controller}",
    defaults: new { action = "GetCeremonies" }
);

context.Routes.MapHttpRoute(
    name: "GetSingleCeremony",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { action = "GetCeremony", id = UrlParameter.Optional }
);

【讨论】:

  • 我认为那里有一个错误,你的路由器应该有不同的名字
【解决方案3】:

幸运的是,现在有了 WEB API2,您可以使用Attribute Routing。微软已经大规模开源,然后一位名叫 Tim McCall 的向导从社区贡献了它。因此,从 2013 年底、2014 年初开始,您可以在您的 WEB API 方法中添加 [Route("myroute")] 之类的属性。请参见下面的代码示例。

仍然 - 正如我刚刚发现的那样 - 你必须确保使用 System.Web.Http.Route 而不是 System.Web.Mvc.Route。否则你仍然会收到错误消息Multiple actions were found that match the request

using System.Web.Http;
...

[Route("getceremonies")]
[HttpGet]
// GET api/Ceremony
public IEnumerable<Ceremony> GetCeremonies()
{
    return db.Ceremonies.AsEnumerable();
}

[Route("getceremony")]
[HttpGet]
// GET api/Ceremony/5
public Ceremony GetCeremony(int id)
{
    Ceremony ceremony = db.Ceremonies.Find(id);
    return ceremony;
}

[Route("getfilteredceremonies")]
[HttpGet]
public IEnumerable<Ceremony> GetFilteredCeremonies(Search filter)
{
    return filter.Ceremonies();
}

【讨论】:

    【解决方案4】:

    这是我的控制器:

    public class PhoneFeaturesController : ApiController
    {
        public List<PhoneFeature> GetbyPhoneId(int id)
        {
            var repository = new PhoneFeatureRepository();
            return repository.GetFeaturesByPhoneId(id);
        }
    
        public PhoneFeature GetByFeatureId(int id)
        {
            var repository = new PhoneFeatureRepository();
            return repository.GetFeaturesById(id);
        }        
    }
    

    这是我的 api 路由:

            config.Routes.MapHttpRoute(
                name: "ApiWithId", 
                routeTemplate: "Api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional },
                constraints: new { id = @"^[0-9]+$" });
    
            config.Routes.MapHttpRoute(
                name: "ApiWithAction", 
                routeTemplate: "api/{controller}/{action}/{name}",
                defaults: null,
                constraints: new { name = @"^[a-z]+$" });
    
            config.Routes.MapHttpRoute(
                name: "ApiByAction",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { action = "Get" },
                constraints: new { id = @"^[0-9]+$" });
    
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
    

    我是这样测试的:

    /api/PhoneFeatures//api/PhoneFeatures/GetFeatureById/101
    
    /api/PhoneFeatures/GetByFeatureId/12
    

    它在任何情况下都能顺利运行 :)

    【讨论】:

      【解决方案5】:

      我发现了另一个不需要将方法移出控制器或更改路由映射配置的修复。只需将[NonAction] 属性添加到您要排除的方法即可:

      [NonAction]
      public IEnumerable<Ceremony> GetFilteredCeremonies(Search filter)
      

      【讨论】:

        【解决方案6】:

        请检查您有两个名称不同但参数相同的方法。

        如果是这样,请删除任何方法并尝试。

        出现此错误是因为有两种方法正在寻找相同的参数。尝试删除其中任何一个并尝试...

        【讨论】:

          【解决方案7】:

          我希望您在调用 GetFilteredCeremonies(Search filter) 时正在执行 HttpGet

          在这种情况下,您不能在 GET 请求中传递复杂的对象,例如您正在传递的 Search

          如果出于某种原因,您肯定想在 get 请求中获取复杂类型,则可以解决一些问题。您可能需要编写自定义模型绑定器,然后设置属性。请参考this article

          【讨论】:

          • 可以传递复杂类型,应该使用[FromUri]属性
          • 好吧,为了传递复杂的对象,你需要使用某种类型的“自定义模型绑定器”,它是 ASP.NET Web API 默认不提供的。
          • 好的..我也会在我的答案中添加这个以完成..感谢您提出这个..
          【解决方案8】:

          在项目根目录的 App_Start 文件夹中编辑您的 WebApiConfig.cs,并将 {action} 添加到MapHttpRoute 方法中的 routeTemplate 参数如下:

           config.Routes.MapHttpRoute(
                      name: "DefaultApi",
                      routeTemplate: "api/{controller}/{action}/{id}",
                      defaults: new { id = RouteParameter.Optional }
                  );
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2016-04-08
            • 1970-01-01
            • 1970-01-01
            • 2015-05-01
            • 2016-07-31
            • 2017-01-03
            相关资源
            最近更新 更多