Queue giới thiệu dài ...Web dựa trên Chấp nhận tiêu đề
Tôi đã một nguồn tài nguyên quy định tại
http://my-awesome-product.com/api/widgets/3
đại diện cho một widget với một id
của 3. Trong Web API tôi sẽ xác định một bộ điều khiển để phục vụ tài nguyên đó như sau:
public class WidgetsController : ApiController
{
public Widget Get(int id)
{
return new Widget(...);
}
}
Bây giờ, lớp Widget
có khả năng có thể là khá lớn, và muốn tiết kiệm băng thông từ cơ sở dữ liệu đến máy chủ web và từ máy chủ web đến máy khách, tôi tạo một số lớp DTO chứa một số trường bị hạn chế trong tổng số Widget
tổng thể. Ví dụ:
public class WidgetSummary
{
public int Id { get; set; }
public string Code { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
}
public class FullWidgetForEditing
{
public int Id { get; set; }
public string Code { get; set; }
public string Description { get; set; }
public decimal Weight { get; set; }
public decimal Price { get; set; }
public Color Color { get; set; }
public decimal Width { get; set; }
public decimal Height { get; set; }
public decimal Depth { get; set; }
}
public class WidgetForDropDownList
{
public int Id { get; set; }
public string Code { get; set; }
}
Với những Widget
cơ quan đại diện, khách hàng sẽ yêu cầu WidgetSummary
để hiển thị trên một mạng lưới tóm tắt tất cả các Widget
s trong hệ thống, nó sẽ yêu cầu FullWidgetForEditing
trên trang chỉnh sửa của một cụ Widget
, và nó sẽ yêu cầu WidgetForDropDownList
để sử dụng trong danh sách thả xuống trên mẫu đơn đặt hàng.
Từ những gì tôi hiểu về REST, để truy cập vào một Widget
cần có một URL duy nhất vì nó là một nguồn tài nguyên duy nhất, bất kể đại diện của mình và khách hàng nên xác định Accept
tiêu đề với một số loại phương tiện truyền thông để lấy Widget
trong của nó các dạng khác nhau, ví dụ my-awesome-product.type=widgetsummary
, my-awesome-product.type=fullwidgetforediting
và my-awesome-product.type=widgetfordropdownlist
.
tôi có thể đạt được điều đó trong Web API bằng cách kiểm tra các tiêu đề của các yêu cầu như vậy:
public class WidgetsController : ApiController
{
public object Get(int id)
{
if (Request.Headers.Accept.Any(x => x.Parameters.Any(y => y.Name == "my-awesome-product.type" && y.Value == "widgetsummary")))
{
return new WidgetSummary(...);
}
else if (Request.Headers.Accept.Any(x => x.Parameters.Any(y => y.Name == "my-awesome-product.type" && y.Value == "fullwidgetforediting")))
{
return new FullWidgetForEditing(...);
}
else if (Request.Headers.Accept.Any(x => x.Parameters.Any(y => y.Name == "my-awesome-product.type" && y.Value == "widgetfordropdownlist")))
{
return new WidgetForDropDownList(...);
}
throw new HttpResponseException(HttpStatusCode.NotAcceptable);
}
}
Tuy nhiên, điều này trở nên lộn xộn một cách nhanh chóng như số lượng các loại phát triển và làm cho kiểm tra đơn vị khó khăn hơn. Những gì tôi thực sự muốn làm là như sau:
public class WidgetsController : ApiController
{
[HttpGet(MediaType = "my-awesome-product.type", MediaTypeValue = "widgetsummary")]
public WidgetSummary GetWidgetSummary(int id)
{
return new WidgetSummary();
}
[HttpGet(MediaType = "my-awesome-product.type", MediaTypeValue = "fullwidgetforediting")]
public FullWidgetForEditing GetFullWidgetForEditing(int id)
{
return new FullWidgetForEditing();
}
[HttpGet(MediaType = "my-awesome-product.type", MediaTypeValue = "widgetfordropdownlist")]
public WidgetForDropDownList GetWidgetForDropDownList(int id)
{
return new WidgetForDropDownList();
}
}
Và có đường dẫn API Web đến phương pháp hành động cụ thể dựa trên loại phương tiện. Tuy nhiên, tôi đã điều tra trọng số ApiControllerActionSelector
, tôi bắt đầu kéo một lượng lớn mã hiện có cho thuộc tính này bởi vì tôi thực sự muốn lựa chọn hành động mặc định, nhưng trong trường hợp các hành động mơ hồ, tôi muốn lọc danh sách các hành động dựa trên phương tiện kiểu. Tôi thực sự muốn nó không xâm nhập để tôi có thể trộn quy ước định tuyến, định tuyến thuộc tính tiêu chuẩn (trong API Web v2) và thuộc tính giả định này định tuyến trong cùng một bộ điều khiển nếu cần.
Thời gian câu hỏi: hiện tại, bạn có thể triển khai chiến lược định tuyến như vậy với API Web không? Tôi có phải hoàn toàn reimplement các ApiControllerActionSelector
để đạt được điều này (và sau đó hãy chắc chắn reimplementation của tôi vẫn được cập nhật)?
flipchart, tôi cũng đang tìm kiếm chính xác những gì bạn mô tả - một URL nên đại diện cho 1 đối tượng (không định dạng của nó, hoặc trả lại loại). Bạn đã bao giờ tìm được giải pháp chưa? Tôi bối rối là lý do tại sao việc ghi đè bộ chọn mặc định đã lấy quá nhiều mã, bạn không nên xử lý các tiêu đề chấp nhận của mình và nếu bạn không nhận được kết quả phù hợp, hãy chuyển yêu cầu xuống lớp cơ sở? Tôi đang thiếu gì? – jeremyh