27

我正在使用 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到我的控制器时,就会出现问题。添加此内容后,当我进行 ajax 调用GetCeremonies操作时,它会返回带有以下消息的异常:

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

8 回答 8

22

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

于 2012-11-10T06:27:25.353 回答
8

这里的问题是您的 2Get种方法将解决,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 }
);
于 2012-11-08T14:47:39.453 回答
6

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

尽管如此 - 正如我刚刚发现的那样 - 你必须确保使用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();
}
于 2015-11-11T01:18:29.900 回答
3

这是我的控制器:

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

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

于 2014-03-04T03:00:57.830 回答
1

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

[NonAction]
public IEnumerable<Ceremony> GetFilteredCeremonies(Search filter)
于 2018-03-23T19:06:01.543 回答
0

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

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

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

于 2014-03-04T05:21:06.897 回答
0

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

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

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

于 2013-07-10T18:17:47.790 回答
0

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

 config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
于 2017-04-07T15:42:36.827 回答