2013-04-11 13 views
14

tôi sử dụng ASP.NET MVC để gửi JSON từ jQuery, và nhận được một số JSON trở lại, sử dụng ít chức năng này thư viện:jQuery bài JSON thất bại khi trở về null từ ASP.NET MVC

(function($) { 
    $.postJson = function(url, data) { 
     return $.ajax({ 
      url: url, 

      data: JSON.stringify(data), 
      type: 'POST', 
      dataType: 'json', 
      contentType: 'application/json; charset=utf-8' 
     }); 
    }; 
})(jQuery); 

Vì vậy, rõ ràng là tôi sẽ gọi này như:

$('#button').click(function() { 
    $.postJson('/controller/action', { Prop1: 'hi', Prop2: 'bye' }) 
    .done(function(r) { alert('It worked.'); }) 
    .fail(function(x) { alert('Fail! ' + x.status); }); 
}); 

ASP.NET MVC 3 và ASP.NET MVC 4 hỗ trợ bên gửi mọi thứ (trước khi bạn cần mở rộng ASP.NET MVC để xử lý việc gửi JSON), nhưng sự cố tôi đang chạy vào là trên sự trở lại. Trên điều khiển tôi thường trở về null về cơ bản nói "Thành công, không có gì khác để nói," như:

[HttpPost] 
public JsonResult DoSomething(string Prop1, string Prop2) 
{ 
    if (doSomething(Prop1, Prop2) 
     return Json(null); // Success 

    return Json(new { Message = "It didn't work for the following reasons" }); 
} 

tôi sử dụng mô hình này thường xuyên và nó hoạt động tốt - thành công/thực hiện cuộc gọi lại của tôi được gọi và tất cả là tốt. Nhưng gần đây tôi đã nâng cấp ASP.NET MVC và jQuery, và nó ngừng hoạt động - thay vì gọi lại không thành công của tôi là nhận được gọi bất cứ khi nào tôi return Json(null);. Hơn nữa, tôi đã kiểm tra phản hồi và việc lấy lại statusCode thực tế là 200, do đó máy chủ không bị lỗi - jQuery chỉ nói nó là vậy.

+1

BTW toàn cầu '$ (document) .ajaxError ...' show trong 'exception.message':" ** Kết thúc đầu vào không mong đợi ** "khi' Json (null) 'được trả về (chỉ cần đề cập đến nó, nó không giúp tôi tìm ra lý do cho vấn đề). – Slauma

Trả lời

35

Sự cố xảy ra do nâng cấp từ jQuery 1.8 lên 1.9. Trong jQuery 1.7 và 1.8, điều này trong MVC:

return Json(null); 

được chấp nhận là JSON hợp lệ và được hiểu là không có giá trị. Về mặt kỹ thuật, điều này sẽ gửi một chuỗi trống trở lại máy khách với HTTP 200, và điều đó đủ tốt cho jQuery < 1.9. Nhưng bây giờ (chúng tôi đang sử dụng jQuery 1.9.1), nó cố phân tích chuỗi rỗng dưới dạng JSON, trình phân tích cú pháp JSON của jQuery ném một ngoại lệ trên chuỗi trống và kích hoạt chuỗi mã kết thúc bằng một cuộc gọi lại fail(). .

Một cách giải quyết là thay vì vượt qua trở lại này từ máy chủ đến thành công không có thông tin khác:

return Json(new{}); 

Đó logo xứng đáng với phân tích cú pháp JSON jQuery và tất cả là tốt. Điều này cũng hoạt động:

return Json(true); 


Cập nhật

Musa lưu ý dưới đây hành vi này bằng MVC dường như bị phá vỡ. Điều này separate Stack Overflow answer to Using JSON.NET as the default JSON serializer in ASP.NET MVC 3 - is it possible? bao gồm làm thế nào để có được MVC trở về null cho Json(null) - về cơ bản, sử dụng Json.NET thay vì ASP.NET MVC được xây dựng trong serializer JSON. Đây là giải pháp cuối cùng tôi đã sử dụng.

Bạn cần sử dụng phiên bản được sửa đổi một chút của câu trả lời đó để sửa lỗi này - tuy nhiên, mã bên dưới. Về cơ bản, không bao gồm tuyên bố if kiểm tra giá trị null trước khi chuyển đến serialize hoặc bạn quay lại ngay trong cùng một tình huống khó khăn.


Cập nhật 2

Việc thực hiện mặc định của tiêu chuẩn ISO 8601 Ngày trong Json.NET phá vỡ Internet Explorer 9 và dưới khi nó cố gắng phân tích nó với new Date(...).Nói cách khác, những phân tích tốt trong Internet   Explorer   9:

var date = new Date('2014-09-18T17:21:57.669'); 
var date = new Date('2014-09-18T17:21:57.600'); 

Nhưng điều này ném một ngoại lệ:

var date = new Date('2014-09-18T17:21:57.6'); 

Internet   Explorer   9 của Date() thực hiện không thể đối phó với bất cứ điều gì nhưng chính xác ba phần nghìn giây. Để khắc phục điều này, bạn phải ghi đè lên định dạng ngày Json.NET để ép buộc nó. Bao gồm trong mã dưới đây.

public class JsonNetResult : JsonResult 
{ 
    public override void ExecuteResult(ControllerContext context) 
    { 
     if (context == null) 
      throw new ArgumentNullException("context"); 

     var response = context.HttpContext.Response; 

     response.ContentType = !String.IsNullOrEmpty(ContentType) ? ContentType : "application/json"; 

     if (ContentEncoding != null) 
      response.ContentEncoding = ContentEncoding; 

     var settings = new JsonSerializerSettings 
     { 
      Converters = new[] {new IsoDateTimeConverter 
      { 
       DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffK" 
      }} 
     }; 
     var jsonSerializer = JsonSerializer.Create(settings); 

     jsonSerializer.Serialize(response.Output, Data); 
    } 
} 

Một Gist thể hiện như thế nào để buộc này thành một BaseController:

https://gist.github.com/b9chris/6991b341e89bb0a4e6d801d02dfd7730

+0

'return Json (null);' trả về một chuỗi rỗng âm thanh bị hỏng, nó sẽ trả về 'null' – Musa

+0

@Musa Có lẽ, mặc dù vào thời điểm này cũng có thể là một thay đổi phá vỡ - Tôi đã đi đào và nó xuất hiện nó đã trả về một sản phẩm nào chuỗi cho null kể từ ngày bắt đầu của MVC. Tôi đồng ý rằng có thể là một giải pháp sạch hơn cho vấn đề này mặc dù. Câu trả lời này bao gồm làm như vậy, mặc dù mã mẫu kiểm tra null và trả về chuỗi rỗng trước khi Json.Net có thể nhận được một shot vào nó - loại bỏ 2 dòng đó và bạn sẽ nhận được null trả về chưa sửa đổi. http://stackoverflow.com/a/7150912/176877 –