231

我需要实现以下 WebAPI 方法:

/api/books?author=XXX&title=XXX&isbn=XXX&somethingelse=XXX&date=XXX

所有查询字符串参数都可以为空。也就是说,调用者可以指定从 0 到所有 5 个参数。

MVC4 beta中,我曾经做过以下事情:

public class BooksController : ApiController
{
    // GET /api/books?author=tolk&title=lord&isbn=91&somethingelse=ABC&date=1970-01-01
    public string GetFindBooks(string author, string title, string isbn, string somethingelse, DateTime? date) 
    {
        // ...
    }
}

MVC4 RC 不再像这样了。如果我指定的参数少于 5 个,它会回复404说:

在与请求匹配的控制器“Books”上未找到任何操作。

什么是正确的方法签名,使其表现得像以前一样,而不必在 URL 路由中指定可选参数?

4

5 回答 5

323

此问题已在 MVC4 的常规版本中修复。现在你可以这样做:

public string GetFindBooks(string author="", string title="", string isbn="", string  somethingelse="", DateTime? date= null) 
{
    // ...
}

一切都会开箱即用。

于 2012-09-12T11:39:07.843 回答
95

正如 vijay 建议的那样,可以将多个参数作为单个模型传递。当您使用 FromUri 参数属性时,这适用于 GET。这告诉 WebAPI 从查询参数中填充模型。

结果是一个更简洁的控制器动作,只有一个参数。有关详细信息,请参阅:http ://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

public class BooksController : ApiController
  {
    // GET /api/books?author=tolk&title=lord&isbn=91&somethingelse=ABC&date=1970-01-01
    public string GetFindBooks([FromUri]BookQuery query)
    {
      // ...
    }
  }

  public class BookQuery
  {
    public string Author { get; set; }
    public string Title { get; set; }
    public string ISBN { get; set; }
    public string SomethingElse { get; set; }
    public DateTime? Date { get; set; }
  }

它甚至支持多个参数,只要属性不冲突。

// GET /api/books?author=tolk&title=lord&isbn=91&somethingelse=ABC&date=1970-01-01
public string GetFindBooks([FromUri]BookQuery query, [FromUri]Paging paging)
{
  // ...
}

public class Paging
{
  public string Sort { get; set; }
  public int Skip { get; set; }
  public int Take { get; set; }
}

更新
为了确保这些值是可选的,请确保对模型属性使用引用类型或可空值(例如 int?)。

于 2014-05-23T14:16:27.143 回答
76

对所有参数使用初始默认值,如下所示

public string GetFindBooks(string author="", string title="", string isbn="", string  somethingelse="", DateTime? date= null) 
{
    // ...
}
于 2012-08-08T11:59:05.050 回答
1

如果要传递多个参数,则可以创建模型而不是传递多个参数。

如果你不想传递任何参数,那么你也可以跳过它,你的代码会看起来整洁干净。

于 2012-09-12T11:51:18.710 回答
1

不能为未声明的参数提供默认值 ' optional'

 Function GetFindBooks(id As Integer, ByVal pid As Integer, Optional sort As String = "DESC", Optional limit As Integer = 99)

在你的WebApiConfig

 config.Routes.MapHttpRoute( _
          name:="books", _
          routeTemplate:="api/{controller}/{action}/{id}/{pid}/{sort}/{limit}", _
          defaults:=New With {.id = RouteParameter.Optional, .pid = RouteParameter.Optional, .sort = UrlParameter.Optional, .limit = UrlParameter.Optional} _
      )
于 2013-02-21T10:54:35.313 回答