2011-01-19 22 views
14

Tôi bối rối về cách xử lý tình huống này.Chiến lược tốt nhất để xử lý các ngoại lệ chưa được giải quyết (lỗi 500 phản hồi) trong hành động Asp.Net MVC cho các yêu cầu Ajax là gì?

Thông thường khi một ngoại lệ ASP.Net chưa được xử lý xảy ra, máy chủ gửi lại thông báo HTML của một số loại, trình xử lý lỗi Asp.Net mặc định hoặc trình xử lý lỗi tùy chỉnh. Tuy nhiên, trong cả hai trường hợp, HTML đang được gửi lại (và thường là một ý tưởng hay để làm cho trang thân thiện với người dùng).

Tuy nhiên, tôi gặp sự cố trong đó các ngoại lệ chưa được xử lý xảy ra trong hành động của trình điều khiển Asp.net MVC được dự kiến ​​sẽ trả về JSON cho các cuộc gọi Ajax. Khi javascript đọc trang được trả về (là HTML thay vì JSON dự định) nó bị treo do không thể chuyển đổi phản hồi thành JSON (ngay bây giờ tôi đang sử dụng ExtJS). Tôi muốn Json được trả lại khi có ngoại lệ để người dùng có thể được thông báo rằng đã xảy ra lỗi.

Giải pháp duy nhất tôi có thể nghĩ đến là phải làm như sau trong mọi hành động trả về Json:

try { .... } 
catch (Exception ex) 
{ 
    return Json(new { success = false, msg = ex.Message }); 
} 

tôi không giống như phương pháp mà bởi vì nó đòi hỏi tôi bắt tất cả các trường hợp ngoại lệ (mà có hại cho rõ ràng lý do) và nó đòi hỏi tôi phải tiêu mỗi hành động JsonResult với cùng một mã xử lý ngoại lệ (mà làm cho nó khó thay đổi sau này).

Có phương pháp nào tốt hơn để trả về kết quả lỗi thích hợp hơn chỉ trên các phương thức hành động trả về Json, nhưng vẫn giữ các trang lỗi thường xuyên thân thiện với người dùng đối với các yêu cầu web không Ajax?

Trả lời

12

Đây là cách tôi giải quyết vấn đề này:

public class HandleJsonError : HandleErrorAttribute 
{ 
    public override void OnException(ExceptionContext exceptionContext) 
    { 
     if (!exceptionContext.HttpContext.Request.IsAjaxRequest() || exceptionContext.Exception == null) return; 

     exceptionContext.HttpContext.Response.StatusCode = (int) HttpStatusCode.InternalServerError; 
     exceptionContext.Result = new JsonResult 
            { 
             Data = new 
                { 
                 exceptionContext.Exception.Message, 
                 exceptionContext.Exception.StackTrace 
                } 
            }; 

     exceptionContext.ExceptionHandled = true; 
    } 
} 
+6

Bạn có thể muốn kế thừa từ HandleErrorAttribute thay thế và ghi đè OnException. Bằng cách đó, bộ lọc của bạn sẽ chỉ kích hoạt khi có ngoại lệ, thay vì cho mọi yêu cầu. –

+0

Bộ lọc hành động dường như là cách để đi. Đánh dấu đây là câu trả lời do mã! – KallDrexx

+0

@ The Flower Guy: Ồ, huh, nghe có vẻ đúng. Tôi sẽ bắn một khi tôi có cơ hội. Cảm ơn! – adamjford

1

Bạn có thể sử dụng ActionFilter tùy chỉnh và sau đó bên trong đó nếu đó là yêu cầu javascript, bạn có thể định dạng phản hồi dưới dạng đối tượng JSON thay vì trang HTML. HandleError sẽ là một nơi tốt để xem xét mở rộng lớp cơ sở của bạn.

Tùy chọn thay thế nếu bạn không muốn thực hiện bộ lọc actio sẽ ghi đè OnException trong bộ điều khiển của bạn và đặt exceptionContext.Result thành JsonResult mới cho biết lỗi.

3

Bạn có thể ghi đè lên OnException trong bộ điều khiển và đưa vào một số logic để trả lại một phản ứng lỗi JSON mà bạn sẽ cần phải xử lý trong javascript của bạn gọi mã:

protected override void OnException(ExceptionContext filterContext) 
    { 
     if (filterContext.HttpContext.Request.IsAjaxRequest()) 
     { 
      filterContext.Result = Json("..."); 
     } 
     else 
     { 
      base.OnException(filterContext); 
     } 
    } 

Nếu bạn muốn làm điều đó 'đúng', bạn có thể viết một bộ lọc hành động với nhiều mã giống nhau và áp dụng nó cho tất cả các bộ điều khiển. Nếu bạn đang sử dụng MVC3, bạn có thể làm cho nó một bộ lọc toàn cục để nó sẽ áp dụng cho tất cả các bộ điều khiển.

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