2013-04-23 34 views
5

Trong WebAPI, tôi đã nhận thấy sự không nhất quán đang gây rối với thực tiễn xác thực của chúng tôi. Nếu bạn gửi một cơ thể xấu/tải trọng với một POST trong xml, deserialization không thành công và bạn nhận được một con trỏ null. Nếu bạn gửi một bad body/payload trong JSON, thay vào đó bạn sẽ nhận được một đối tượng rỗng. Nó gây hiểu lầm và tôi không thích nó. Có cách nào để buộc một con trỏ null với một deserialization json thất bại ??Trình nối tiếp JSON tạo một đối tượng trống trên quá trình deserialization không thành công thay vì null

CẬP NHẬT: Tôi không gặp sự cố deserialization. Tôi đang gặp một vấn đề hành vi mà có vẻ là một sự khác biệt giữa DataContractSerializer và serializer Json.net. Khi xml không deserialize, tải trọng là null. Tuy nhiên, khi Json không deserialize, có vẻ như nó là instantiating một thể hiện mặc định của trọng tải dự kiến.

Ví dụ về một tải trọng xml xấu: enter image description here

Ví dụ về các cuộc gọi tương tự sử dụng một json tải trọng xấu (. Tải trọng không null thay vì nó là một trường hợp mặc định của lớp tải trọng)

enter image description here

+1

bạn có thể chia sẻ mã được cho thấy sự khác biệt này? –

+0

Tôi không chắc chắn làm thế nào để hiển thị cho bạn khi nó xảy ra tại điểm vào. – Sinaesthetic

+1

Vâng, để bắt đầu, hãy hiển thị mô hình của bạn, hiển thị hành động điều khiển API Web của bạn đang lấy mô hình này làm đối số và hiển thị XML và JSON bạn đang đăng lên hành động này giải thích sự khác biệt chính xác mà bạn đã quan sát thấy trong hành vi.Điều này là đủ để bắt đầu một cuộc thảo luận mang tính xây dựng khá khó khăn ở giai đoạn hiện tại của câu hỏi này. –

Trả lời

4

Theo mặc định Web.API đã sử dụng cài đặt MissingMemberHandling.Ignore trong JsonMediaTypeFormatter.

Bạn cần phải đặt nó vào MissingMemberHandling.Error với:

GlobalConfiguration.Configuration 
    .Formatters.JsonFormatter 
    .SerializerSettings.MissingMemberHandling = MissingMemberHandling.Error; 

và bạn sẽ nhận null khi gửi JSON như:

{ 
    "somenotexistingprop": "" 
} 

Tuy nhiên nếu bạn gửi một đối tượng JSON hoàn toàn trống rỗng: {} sau đó bạn sẽ vẫn nhận được đối tượng có thuộc tính trống và không phải là null. Bởi vì JsonConvert.DeserializeObject trả về một đối tượng trống nếu nó deserializes một JSON trống (xem bài kiểm tra đơn vị này của github).

+0

Tôi cũng tìm thấy điều này. Nó không hoạt động. Cùng một kết quả! – Sinaesthetic

+0

@Sinesthetic Tôi đã hủy xóa câu trả lời của tôi vì đây là giải pháp cho vấn đề của bạn nhưng hiện tại có vẻ như có lỗi trong Wep.API ngăn chặn việc này ... – nemesv

+1

Ngoài việc làm cho MissingMemberHandling thành "Lỗi", bạn cũng có thể thực hiện kiểm tra sau để nó nhất quán trên các trình định dạng Xml và Json 'if (! ModelState.IsValid) { ném HttpResponseException mới (Request.CreateErrorResponse (HttpStatusCode.BadRequest, this.ModelState)); } ' –

1

Sau khi một trong những thành viên trong nhóm của tôi đã giúp tôi hiểu tại sao đây là trường hợp, sau đây là một số lưu ý về kịch bản này:

  1. Chúng tôi theo mặc định không có "MissingMemberHandling.Error" trên Json formatter vì đây có thể giúp đỡ trong các tình huống mà bạn phiên bản mới hơn của khách hàng gửi dữ liệu với các thành viên bổ sung vào một phiên bản dịch vụ cũ hơn. Phiên bản dịch vụ cũ hơn vẫn có thể chấp nhận yêu cầu này và bỏ qua các thuộc tính bổ sung. Hành vi này phù hợp với cách trình định dạng Xml cũng hoạt động.

  2. @Thẩm thẩm: nếu bạn đang đặt "MissingMemberHandling.Error" và không muốn chỉ dựa vào "ModelState.IsValid", bạn có thể kiểm tra thuộc tính của ModelState's Keys để tìm hiểu xem yêu cầu của bạn có thực sự không hợp lệ hay không vì một thành viên mất tích hoặc thứ gì đó khác.

Ví dụ dưới đây:

public class Customer 
{ 
    public int Id { get; set; } 

    [MaxLength(5)] 
    public string Name { get; set; } 

    public Address Address { get; set; } 
} 

public class Address 
{ 
    public string Line1 { get;set;} 
} 

//action 
public void Post([FromBody]Customer customer) 
    { 
     if (!ModelState.IsValid) 
     { 
      ModelStateDictionary msd = new ModelStateDictionary(); 

      foreach (string key in ModelState.Keys) 
      { 
       if (ModelState[key].Errors.Count > 0) 
       { 
        foreach (ModelError error in ModelState[key].Errors) 
        { 
         Exception ex = error.Exception; 

         if (ex != null 
          && typeof(JsonSerializationException).IsAssignableFrom(ex.GetType()) 
          && ex.Message.StartsWith("Could not find member")) 
         { 
          msd.AddModelError(key, ex); 
         } 
        } 
       } 
      } 

      if (msd.Count > 0) 
      { 
       throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, msd)); 
      } 
     } 

     //process the supplied customer 
    } 
Các vấn đề liên quan