C# 找到多个与请求 Web API 匹配的操作?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13291025/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 08:05:33  来源:igfitidea点击:

Multiple actions were found that match the request Web API?

c#asp.net-web-api

提问by Tom Rider

I am using web API and i am new in this. I am stuck in a routing problem. I have a controller with following actions :

我正在使用 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();
    }

The problem occure when i added the action GetFilteredCeremoniesto my controller. After adding this when i make an ajax call to GetCeremoniesaction then it return an Exception with following message :

当我将操作添加GetFilteredCeremonies到我的控制器时出现问题。添加此后,当我进行 ajax 调用GetCeremonies操作时,它会返回一个带有以下消息的异常:

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

FYI: The parameter Searchis the Model class which contains properties and a function name Ceremonies.

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

EDIT

编辑

Route:

路线:

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

回答by James

The problem here is your 2 Getmethods will resolve to api/Ceremonyand MVC does not allow parameter overloading. A quick workaround (not necessarily the preferred approach) for this sort of problem is to make your idparameter nullable e.g.

这里的问题是您的 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();
    }
}

However, you would then be returning a list of ceremonies when with 1 item when your trying to query for a single ceremony - if you could live with that then it may be the solution for you.

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

The recommended solution is to map your paths appropriately to the correct actions e.g.

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

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

回答by Admir Tuzovi?

If you're not requirement bound to use REST services that use api/{controller}/{id}route and attempt to resolve action based on method GET/POST/DELETE/PUT, you can modify your route to classic MVC route to api/{controller}/{action}/{id}and it will solve your problems.

如果您不需要使用使用api/{controller}/{id}路由的REST 服务并尝试根据GET/ POST/ DELETE/ PUT方法解决操作,则可以将路由修改为经典的 MVC 路由api/{controller}/{action}/{id},它将解决您的问题。

回答by Ramesh

Please check you have two methods which has the different name and same parameters.

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

If so please delete any of the method and try.

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

This error was raised because there are two methods which are looking for same parameters. try to delete any one of them and try...

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

回答by Ali Adravi

Here is my controller:

这是我的控制器:

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

Here is my api routing:

这是我的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 }
        );

I tested it like this:

我是这样测试的:

/api/PhoneFeatures//api/PhoneFeatures/GetFeatureById/101

/api/PhoneFeatures/GetByFeatureId/12

It works smooth in every condition :)

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

回答by Deepak Raj

I hope you are doing HttpGet while you invoke GetFilteredCeremonies(Search filter)

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

In that case, you cannot pass complex object in GET request like Searchthat you are passing.

在这种情况下,您不能像Search正在传递的那样在 GET 请求中传递复杂的对象。

If for some reason, you definitely want to get complex types in your get request, there are some work around. You may need to write a custom model binder and then set the attribute. please refer this article.

如果出于某种原因,您肯定希望在您的 get 请求中获得复杂类型,则有一些解决方法。您可能需要编写自定义模型绑定器,然后设置属性。请参考这篇文章

回答by Bart

Luckily nowadays with WEB API2 you can use Attribute Routing. Microsoft has gone open source on a big scale and then a wizard named Tim McCall contributed it from the community. So since somewhere end 2013, early 2014 you can add attributes like [Route("myroute")]on your WEB API methods. See below code example.

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

Still - as I just found out - you have to make sure to use System.Web.Http.Routeand NOT System.Web.Mvc.Route. Otherwise you'll still get the error message Multiple actions were found that match the request.

仍然 - 正如我刚刚发现的 - 你必须确保使用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();
}

回答by Parsa Karami

Edit Your WebApiConfig.csin App_Startfolder on the root of project and add {action}to routeTemplateparameter in MapHttpRoute Method like below :

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

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

回答by Jonathan Amend

I found another fix that doesn't require moving methods out of the controller or changing the route mapping config. Just add the [NonAction]attribute to the method you want to exclude:

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

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