Các tham số chuỗi truy vấn tùy chọn trong ASP.NET Web API


212

Tôi cần triển khai phương pháp WebAPI sau:

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

Tất cả các tham số chuỗi truy vấn có thể là null. Nghĩa là, người gọi có thể chỉ định từ 0 đến tất cả 5 tham số.

Trong MVC4 beta, tôi đã từng làm như sau:

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 không hoạt động như thế này nữa. Nếu tôi chỉ định ít hơn 5 tham số, nó sẽ trả lời bằng một 404câu:

Không có hành động nào được tìm thấy trên bộ điều khiển 'Sách' phù hợp với yêu cầu.

Chữ ký phương thức chính xác để làm cho nó hoạt động như trước đây mà không phải chỉ định tham số tùy chọn trong định tuyến URL là gì?


đặt [httpget] vào hành động.
user960567

2
Nếu tôi đặt tất cả các tham số, phương thức sẽ được gọi; hơn nữa nó bắt đầu bằng Getvì vậy nó được tự động ràng buộc với HTTP GETphương thức ...
frapontillo

Đây là cách thức hoạt động, trang web api định tuyến asp.net/web-api/overview/web-api-routing-and-actions/...
user960567

4
Đúng. Tôi biết làm thế nào nó hoạt động. Tôi chỉ không thể làm cho nó hoạt động trong hoàn cảnh cụ thể NÀY.
frapontillo

Làm thế nào điều này thậm chí biên dịch? string?không phải là một loại hợp lệ. Bạn không thể khai báo stringlà loại nullable vì đây là loại tham chiếu.
EkoostikMartin

Câu trả lời:


307

Vấn đề này đã được khắc phục trong bản phát hành thường xuyên của MVC4. Bây giờ bạn có thể làm:

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

và mọi thứ sẽ làm việc ra khỏi hộp.


Tôi có thể sử dụng null ở đây làm mặc định không? Ví dụ: chuỗi tác giả = null?
Boris Zinchenko

2
Có, nullđược coi là biểu thức hằng và do đó, giá trị mặc định hợp lệ .
JDawg

Tôi tự hỏi tại sao chúng ta phải đề cập đến các giá trị mặc định ngay cả đối với các tham số tùy chọn như đã nói ở đây . Bất kỳ loại nào trong C # luôn có giá trị mặc định, vì vậy thời gian chạy định tuyến có thể lấy giá trị mặc định của loại nếu nó không nhận được từ URI. Lý do kỹ thuật đằng sau này là gì? Tôi chắc chắn rằng điều này có liên quan đến chất kết dính mô hình.
RBT

@RBT Vì vậy, tuyến đường có thể được khớp
James Westgate

Tôi đã sử dụng các tham số ngày và nếu tôi chỉ đặt chúng thành nullable thì không hoạt động. Vì vậy, tôi phải đặt nó là null và đặt null làm giá trị mặc định và sử dụng xác thực phía máy chủ tương ứng và trả lại thông báo lỗi. Nó đã làm việc.
Atta H.

85

Có thể truyền nhiều tham số dưới dạng một mô hình như vijay đề xuất. Điều này hoạt động cho GET khi bạn sử dụng thuộc tính tham số FromUri. Điều này báo cho WebAPI điền vào mô hình từ các tham số truy vấn.

Kết quả là một hành động điều khiển sạch hơn chỉ với một tham số duy nhất. Để biết thêm thông tin, hãy xem: 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; }
  }

Nó thậm chí còn hỗ trợ nhiều tham số, miễn là các thuộc tính không xung đột.

// 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; }
}

Cập nhật :
Để đảm bảo các giá trị là tùy chọn, hãy đảm bảo sử dụng các loại tham chiếu hoặc nullables (ví dụ: int?) Cho các thuộc tính mô hình.


4
Có, nhưng một mình trang trí [FromUri] không xuất hiện để hỗ trợ các tham số tùy chọn.
John Meyer

6
@JohnMeyer Bạn đúng khi sử dụng [FromUri] không trả lời trực tiếp câu hỏi ban đầu. Về cơ bản, nó cho biết các mô hình này với các giá trị từ Uri. Các thuộc tính mô hình sẽ cần phải là null hoặc một kiểu tham chiếu để chúng hỗ trợ là tùy chọn. Đã thêm thông tin bổ sung.
Andrew C

@AndrewC - Bạn có thể giải thích chi tiết khi nào / tại sao bạn cần sử dụng nullables để đảm bảo các giá trị là tùy chọn không? Nếu bạn không biến các giá trị thành null (đối với ex, property int Skip) và không có tham số truy vấn nào cho thuộc tính đó được chỉ định, phương thức Trình điều khiển API sẽ vẫn khớp thành công với yêu cầu và giá trị Skipsẽ chỉ là giá trị mặc định cho loại đó, hoặc 0 trong trường hợp này
Clark

2
@Clark - Không sử dụng loại nullable, bạn sẽ không biết nếu người dùng không cung cấp giá trị và nhận giá trị loại chưa được khởi tạo (0 cho int) hoặc nếu người dùng chỉ định 0. Bằng cách sử dụng nullable, bạn chắc chắn rằng người dùng sẽ không xác định do đó bạn có thể áp dụng một cách an toàn mặc định của mình trong hành động của bộ điều khiển. Nếu bạn nhìn vào Take từ ví dụ trên, hành động nên làm gì nếu nhận được 0 cho Take? Có phải người dùng có nghĩa là yêu cầu 0 hồ sơ hoặc họ không chỉ định nó và do đó bạn nên lấy tất cả các hồ sơ. Nói chung nếu bạn muốn một loại giá trị (int, bool, v.v.) là tùy chọn thì nó phải là null.
Andrew C

70

Sử dụng các giá trị mặc định ban đầu cho tất cả các tham số như bên dưới

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

1
Đây là thủ tục chính xác nhưng vì một điều: DateTimekhông thể rỗng. Tôi đã cố gắng sử dụng DateTime?thay thế, nhưng sau đó MVC không ánh xạ yêu cầu đến phương thức đã cho nếu tôi chỉ đặt một số tham số trong yêu cầu HTTP của mình.
frapontillo

bạn có thể truyền ngày dưới dạng chuỗi và phân tích cú pháp bên trong hàm điều khiển của mình bằng hàm DateTime.Pude ().
Muhammad Amin

1
@MuhammadAmin, DateTimekhông phải là một nullable kiểu dữ liệu. Mã của bạn không nên biên dịch, vì bạn sẽ không thể gán nullgiá trị cho tham số loại DateTime. Có lẽ, bạn nên thay đổi nó thành DateTime?hoặc sử dụng giá trị khác nhau cho một mặc định như thế nào DateTime.Now.
Ivaylo Slavov

1
@IvayloSlavov DateTime. Bây giờ không phải là hằng số thời gian biên dịch nên không thể gán nó làm tham số mặc định.
GiriB

@GiriB, bạn thực sự đúng. Datetime.NowKhông thể được sử dụng trong khởi tạo tham số mặc định, tôi đứng chính xác.
Ivaylo Slavov

1

Nếu bạn muốn truyền nhiều tham số thì bạn có thể tạo mô hình thay vì truyền nhiều tham số.

trong trường hợp bạn không muốn vượt qua bất kỳ tham số nào thì bạn cũng có thể bỏ qua nó và mã của bạn sẽ trông gọn gàng và sạch sẽ.


1
Điều này chỉ đúng với các tham số POST trong thân yêu cầu - các tham số trong url vẫn có thể được tham chiếu riêng lẻ dưới dạng đối số.
Nathan

1

Các giá trị mặc định không thể được cung cấp cho các tham số không được khai báo ' optional'

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

Trong bạn 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} _
      )

8
Trên thực tế, họ có thể. Tôi đang sử dụng C #, không phải VB.NET.
frapontillo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.