ASP.NET Web API中的可选查询字符串参数

fra*_*llo 200 c# url query-string asp.net-web-api

我需要实现以下WebAPI方法:

/api/books?author=XXX&title=XXX&isbn=XXX&somethingelse=XXX&date=XXX
Run Code Online (Sandbox Code Playgroud)

所有查询字符串参数都可以为null.也就是说,调用者可以指定从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) 
    {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

MVC4 RC不再像这样了.如果我指定少于5个参数,它会回复404一句话:

未在与请求匹配的控制器"Books"上找到任何操作.

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

fra*_*llo 297

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

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

一切都将开箱即用.

  • 是的,`null`被认为是[常量表达式](https://msdn.microsoft.com/en-us/library/aa691319(v = vs.71).aspx),因此是[有效默认值]( https://msdn.microsoft.com/en-us/library/dd264739.aspx?f=255&mspperror=-2147217396#Anchor_2). (2认同)

And*_*w C 77

如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; }
  }
Run Code Online (Sandbox Code Playgroud)

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

// 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; }
}
Run Code Online (Sandbox Code Playgroud)

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

  • @JohnMeyer你是正确的使用[FromUri]没有直接回答原始问题.它基本上说用Uri的值填充这些模型.模型属性需要是可空的或引用类型,以便它们支持可选.添加了其他信息. (5认同)
  • 是的,但是[FromUri]装饰器似乎并不支持可选参数。 (2认同)
  • @Clark - 如果没有使用可空类型,你将不知道用户是否提供了一个值并获得了未初始化的类型值(0表示int)或者如果用户指定了0.通过使用nullable,您确定用户将其保留为undefined因此,您可以安全地在控制器操作中应用默认值.如果你从上面的例子中看看Take,如果它为Take获得0,那么该动作应该怎么办?用户是否要求请求0条记录,或者是否未指定,因此您应该记录所有记录.通常,如果您希望值类型(int,bool等)是可选的,那么它应该是可空的. (2认同)

Muh*_*min 65

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

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

  • 这是正确的过程,但一方面:`DateTime` 不可为空。我已经尝试使用`DateTime?` 代替,但是如果我只在我的 HTTP 请求中设置了一些参数,MVC 不会将请求映射到给定的方法。 (2认同)
  • @IvayloSlavov DateTime.Now 不是编译时常量,因此不能将其分配为默认参数。 (2认同)