ASP.NET Web API中的可选参数

我需要实现以下WebAPI方法:

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

所有参数都可以为null,即调用者可以从0指定所有5个参数。

MVC4testing版中,我曾经做过以下操作:

 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的行为不再这样了。 如果我指定less于5个参数,它回答404

没有find符合请求的控制器“书籍”的操作。

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

这个问题已经在MVC4的定期发布中得到解决。 现在你可以做:

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

所有的东西都可以在盒子里运行

像维杰build议的那样,可以将多个参数作为单个模型传递。 这适用于使用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; } } 

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

使用如下所有参数的初始默认值

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

默认值不能被提供给那些没有声明为“ 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} _ ) 

如果你想传递多个参数,那么你可以创build模型,而不是传递多个参数。

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