7

Nếu lỗi tải trang bình thường, tôi có thể báo cáo chi tiết ngoại lệ cho người dùng qua chế độ xem Error và kiểu HandleErrorInfo.Lỗi báo cáo từ Ajax đã gọi các phương thức PartialView trong MVC

Nếu một ajax gọi mong đợi một Json lỗi kết quả, tôi có thể xử lý một cách rõ ràng các lỗi và thông qua chi tiết cho khách hàng:

public JsonResult Whatever() 
{ 
    try 
    { 
     DoSomething(); 
     return Json(new { status = "OK" }); 
    } 
    catch (Exception e) 
    { 
     return Json(new { status = "Error", message = e.Message }); 
    } 
} 

Vì vậy, vấn đề của tôi, tôi không thể nhìn thấy bất cứ cách nào để báo cáo chi tiết lỗi từ một cuộc gọi Ajax đến một hành động trả lại một phần xem.

$.ajax({ 
    url: 'whatever/trevor', 
    error: function (jqXHR, status, error) { 
     alert('An error occured: ' + error); 
    }, 
    success: function (html) { 
     $container.html(html); 
    } 
}); 

Điều này sẽ chỉ báo cáo mã lỗi Http (ví dụ: Lỗi máy chủ nội bộ) không hữu ích cho khách hàng. Có một số mẹo thông minh để vượt qua một kết quả thành công (html) thành công hoặc thông báo lỗi không?

Đánh giá rõ ràng html từ ViewResult và trả lại nó như một phần của đối tượng Json cùng với trạng thái có vẻ quá có mùi. Có một mô hình được thiết lập để xử lý kịch bản này không?

Trả lời

14

điều khiển hành động:

public ActionResult Foo() 
{ 
    // Obviously DoSomething could throw but if we start 
    // trying and catching on every single thing that could throw 
    // our controller actions will resemble some horrible plumbing code more 
    // than what they normally should resemble: a.k.a being slim and focus on 
    // what really matters which is fetch a model and pass to the view 

    // Here you could return any type of view you like: JSON, HTML, XML, CSV, PDF, ... 

    var model = DoSomething(); 
    return PartialView(model); 
} 

Sau đó, chúng ta định nghĩa một lỗi xử lý toàn cầu cho các ứng dụng của chúng tôi:

protected void Application_Error(object sender, EventArgs e) 
{ 
    var exception = Server.GetLastError(); 
    var httpException = exception as HttpException; 
    Response.Clear(); 
    Server.ClearError(); 

    if (new HttpRequestWrapper(Request).IsAjaxRequest()) 
    { 
     // Some error occurred during the execution of the request and 
     // the client made an AJAX request so let's return the error 
     // message as a JSON object but we could really return any JSON structure 
     // we would like here 

     Response.StatusCode = 500; 
     Response.ContentType = "application/json"; 
     Response.Write(new JavaScriptSerializer().Serialize(new 
     { 
      errorMessage = exception.Message 
     })); 
     return; 
    } 

    // Here we do standard error handling as shown in this answer: 
    // http://stackoverflow.com/q/5229581/29407 

    var routeData = new RouteData(); 
    routeData.Values["controller"] = "Errors"; 
    routeData.Values["action"] = "General"; 
    routeData.Values["exception"] = exception; 
    Response.StatusCode = 500; 
    if (httpException != null) 
    { 
     Response.StatusCode = httpException.GetHttpCode(); 
     switch (Response.StatusCode) 
     { 
      case 404: 
       routeData.Values["action"] = "Http404"; 
       break; 
      case 500: 
       routeData.Values["action"] = "Http500"; 
       break; 
     } 
    } 

    IController errorsController = new ErrorsController(); 
    var rc = new RequestContext(new HttpContextWrapper(Context), routeData); 
    errorsController.Execute(rc); 
} 

Đây là cách ErrorsController sử dụng trong xử lý lỗi trên toàn cầu có thể nhìn như thế nào. Có lẽ chúng ta có thể xác định một số quan điểm tùy chỉnh cho các hành động 404 và 500:

public class ErrorsController : Controller 
{ 
    public ActionResult Http404() 
    { 
     return Content("Oops 404"); 
    } 

    public ActionResult Http500() 
    { 
     return Content("500, something very bad happened"); 
    } 
} 

Sau đó, chúng ta có thể đăng ký cho một global error handler cho tất cả các lỗi AJAX để chúng ta không cần phải lặp lại mã lỗi xử lý này cho tất cả các yêu cầu AJAX nhưng nếu chúng ta muốn chúng ta có thể lặp lại nó:

$('body').ajaxError(function (evt, jqXHR) { 
    var error = $.parseJSON(jqXHR.responseText); 
    alert('An error occured: ' + error.errorMessage); 
}); 

Và cuối cùng chúng tôi bắn một yêu cầu AJAX đến hành động điều khiển chúng tôi hy vọng sẽ trở lại một phần HTML trong trường hợp này:

$.ajax({ 
    url: 'whatever/trevor', 
    success: function (html) { 
     $container.html(html); 
    } 
}); 
+1

Làm cho kiến ​​thức của bạn về MVC làm tôi ngạc nhiên trở lại. Tôi đã không hoàn toàn hiểu một vài điểm ở đây, nhưng tôi đã tìm ra rằng tôi có thể đạt được một cái gì đó tương tự một chút đơn giản chỉ với một bộ lọc ajax đăng ký trong bộ lọc toàn cầu. Dường như nó hoạt động ổn. Cảm ơn bạn. – fearofawhackplanet

+0

Chỉ cần một lưu ý, nếu bạn đang sử dụng mã trên để bẫy 404 và hiển thị một trang tùy chỉnh, bạn có thể muốn thêm một Response.TrySkipIisCustomErrors = true (.net 3.5 trở đi chỉ tôi tin) –

+0

Làm việc như một nét duyên dáng, aweseome – Dilip