8

更新

我最初的假设是可选参数是问题的原因。这似乎是不正确的。相反,当其中一个方法包含某些参数的可空值类型(例如 int? )时,这似乎是多个操作方法的问题。

我正在使用 Visual Studio 2012 RC,并且刚刚开始使用 Web API。我遇到了一个问题并收到错误消息“在与请求匹配的控制器 'Bars' 上未找到任何操作。”

我有一个酒吧控制器。它有一个接收可选参数的 Get() 方法。

public IEnumerable<string> Get(string h, string w = "defaultWorld", int? z=null)
{
    if (z != 0)
        return new string[] { h, w, "this is z: " + z.ToString() };
    else
       return new string[] { h, w };
}

因此,我使用以下网址对其进行了测试

  • /api/bars?h=你好
  • /api/bars?h=hello&w=world
  • /api/bars?h=hello&w=world&z=15

它适用于所有三个。

然后,我去添加另一个 Get() 方法,这次使用单个 id 参数

 public string Get(int id)
 {
     return "value";
 }

我再次测试网址。这次 /api/bars?h=hello&w=world 和 api/bars?h=hello 失败了。错误消息是“未在与请求匹配的控制器 'Bar' 上找到任何操作。”

出于某种原因,这两种方法不能很好地结合在一起。如果我删除Get(int id),它的工作原理。如果我改变int?z 到字符串 z,然后它可以工作(但是它需要在我的操作方法中转换对象!)。

为什么 Web API 会这样做?这是一个错误还是设计使然?

非常感谢。

4

3 回答 3

3

我还没有找到这个问题的真正答案(为什么 Web API 会这样做),但我有一个解决方法允许重载 Get()。诀窍是将参数值包装在一个对象中。

public class Foo
{
    public string H { get; set; }
    public string W { get; set; }
    public int? Z { get; set; }
}

并将 Bars 控制器修改为

public IEnumerable<string> Get([FromUri] Foo foo)
{
    if (foo.Z.HasValue)
        return new string[] { foo.H, foo.W, "this is z: " + foo.Z.ToString() };
    else
        return new string[] { foo.H, foo.W, "z does not have a value" };
}

[FromUri]是必要的,因为默认情况下 WebAPI 不使用 URI 参数来形成“复杂”对象。一般的想法是复杂对象来自<form>动作,而不是 GET 请求。

我仍然会继续检查为什么 Web API 会以这种方式运行,以及这是否真的是一个错误或预期的行为。

于 2012-07-11T15:07:58.007 回答
2

您可以通过在路由中添加操作参数来重载 WEB API 控制器方法。

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

一旦您在路线中进行了此更改,您就可以调用您的方法,例如

/api/bars/get?id=1
/api/bars/get?h=hello&w=world&z=15

希望这有帮助。

奥马尔

于 2012-07-10T17:40:48.130 回答
2

问题解决了,但是,它留下了一个额外的问题。问题似乎是重载的 Action 方法在可选参数方面存在问题。

所以新的问题是为什么会这样,但我会把它留给比我低级别的人;)

但这是个好消息。我不喜欢你报告的问题,并且走复杂类型的路线,虽然很高兴知道,但这只是一个 jerry rig 修复,并且会很差地反映 Web Api 中的某些东西是如何工作的。所以好消息是,如果你有这个问题,它可以通过简单地取消可选参数来解决,做好的 ol' 重载路线。好消息,因为这绝不是一个 jerry rig 修复,只是让你失去了一些可选参数的便利:

public class BarsController : ApiController
{
    public string Get(int id)
    {
        return "value";
    }

    public IEnumerable<string> Get(string h)
    {
        return Get(h, null, null);
    }

    public IEnumerable<string> Get(string h, string w)
    {
        return Get(h, w, null);
    }

    public IEnumerable<string> Get(string h, string w, int? z) 
    {
        if (z != 0)
            return new string[] { h, w, "this is z: " + z.ToString() };
        else
            return new string[] { h, w };
    }
}

干杯

于 2012-08-01T05:52:21.113 回答