2013-01-02 22 views
15

Tôi muốn có một API như vậy:Tôi có thể chuyển đối tượng dựa trên giao diện tới một bài đăng MVC 4 WebApi không?

public class RelayController : ApiController 
{ 
    // POST api/values 
    public void Post([FromBody]IDataRelayPackage package) 
    { 
     MessageQueue queue = new MessageQueue(".\\private$\\DataRelay"); 
     queue.Send(package); 
     queue.Close(); 
    } 
} 

Tôi nhận được một giá trị null cho 'gói' vì vậy tôi tự hỏi những gì có thể xảy ra sai. Suy nghĩ duy nhất của tôi là bộ nối tiếp mặc định JSON không thể xử lý điều này, nhưng tôi không rõ cách khắc phục.

+0

Vì lợi ích của thời gian, tôi đã quyết định thay đổi WebAPI POST của mình để chấp nhận một chuỗi chứa XML. Tôi dự định sẽ quay lại sau này. –

Trả lời

14

Bạn có thể thực hiện việc này khá dễ dàng với một trình kết nối mô hình tùy chỉnh. Đây là những gì làm việc cho tôi. (Sử dụng Web API 2 và JSON.Net 6)

public class JsonPolyModelBinder : IModelBinder 
{ 
    readonly JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }; 

    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) 
    { 
     var content = actionContext.Request.Content; 
     string json = content.ReadAsStringAsync().Result; 
     var obj = JsonConvert.DeserializeObject(json, bindingContext.ModelType, settings); 
     bindingContext.Model = obj; 
     return true; 
    } 
} 

Bộ điều khiển API Web trông như thế này. (Lưu ý: cũng nên làm việc cho những hành động MVC thường xuyên - Tôi đã làm điều gì đó như thế này cho họ trước khi là tốt.)

public class TestController : ApiController 
{ 
    // POST api/test 
    public void Post([ModelBinder(typeof(JsonPolyModelBinder))]ICommand command) 
    { 
     ... 
    } 
} 

Tôi cũng nên lưu ý rằng khi bạn serialize JSON, bạn nên serialize nó với cùng một thiết lập, và tuần tự hóa nó như là một giao diện để làm cho tự động khởi động và bao gồm gợi ý kiểu. Một cái gì đó như thế này.

JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }; 
    string json = JsonConvert.SerializeObject(command, typeof(ICommand), settings); 
+0

Điều này thật tuyệt vời và mở ra các giao diện nhà máy dịch vụ JSON quá tải. Cảm ơn! –

+1

Ngoài ra, JSON.Net có thể deserialize tin nhắn bất biến (không có setters công cộng) miễn là tên tài sản của bạn phù hợp với các thông số constructor của bạn (trường hợp insensitive). –

+0

Cuối cùng, tôi quyết định đơn giản hơn là có hành động Đăng của mình mà không có tham số và deserialize bài đăng như một phần của hành động. Bằng cách đó tôi có thể xử lý các trường hợp ngoại lệ hoặc bất cứ điều gì khác mà tôi muốn làm. –

1

Trình nối tiếp cần loại mà nó có thể tạo, một bộ có một hàm tạo trống (Mặc định). Vì một giao diện không thể được xây dựng, serialization không thành công và bạn nhận được một giá trị null.

Hai lựa chọn:

  1. Sử dụng một POCO (Plain Old Clr Object) với một constructor mặc định
  2. Implement your own binder using IActionValueBinder
3

Json.NET (mặc định Json serializer cho ASP.NET Web API) có thể xử lý tình huống này. Tất cả những gì bạn cần làm là thay đổi các thiết lập serializer, và thiết lập TypeNameHandling thành All (hoặc Objects). Điều này sẽ thêm thuộc tính -json "$ type" vào json của bạn, chứa tên kiểu của cá thể của bạn. Ở phía bên kia nó sẽ cố gắng deserialize loại này một lần nữa.

Chúng tôi đã sử dụng điều này cho chính mình, lấy một lớp cơ sở trừu tượng làm loại.

+0

Khi bạn nói "thay đổi cài đặt bộ nối tiếp", tôi sẽ làm điều này ở đâu? –

+0

@DavidCornelson nó được hiển thị trong liên kết trong câu trả lời của tôi http://stackoverflow.com/questions/12858748/asp-net-webapi-posting-collection-of-subclasses –

Các vấn đề liên quan