2009-07-22 38 views
7

Tôi đã có một catchall trong bộ điều khiển cơ sở của tôi xử lý các lỗi mà tôi không nắm bắt được. Nó đi gần như thế này:Vấn đề với xử lý lỗi bộ điều khiển cơ sở chung trong ASP.NET MVC

protected override void OnException(ExceptionContext filterContext) 
{ 
    // Bail if we can't do anything 
    if (filterContext == null) 
     return; 

    // log 
    var ex = filterContext.Exception ?? 
      new Exception("No further information exists."); 
    LogException(ex); 

    filterContext.ExceptionHandled = true; 
    var data = new ErrorPresentation 
     { 
     ErrorMessage = HttpUtility.HtmlEncode(ex.Message), 
     TheException = ex 
     }; 
    filterContext.Result = View("Error", data); 
    base.OnException(filterContext); 
} 

Bây giờ công trình này tuyệt vời nếu lỗi xảy ra trong bộ điều khiển. Vấn đề là nếu lỗi là trong khi hiển thị trang aspx (giả sử, trong phương thức HtmlHelper), toàn bộ toàn bộ chế độ xem lỗi được hiển thị, tại vị trí trên trang xảy ra lỗi. Điều đó có nghĩa rằng toàn bộ trang lỗi (MasterPage và tất cả) được hiển thị trong trang bị lỗi. Không chính xác hành vi mong đợi.

Tôi đã thử thay đổi dạng xem thành RedirectToAction, nhưng điều đó sẽ không hoạt động như một tuyến đường không tồn tại đối với mọi bộ điều khiển (Home/Error, Configuration/Error, vv).

Tôi làm cách nào để làm việc này cho cả lỗi trong bộ điều khiển VÀ lỗi trên trang?

+0

Bạn có nói rằng khi một lỗi xảy ra trong một khung nhìn, trang lỗi của bạn được hiển thị sau khi lỗi xảy ra trong khung nhìn của bạn ? –

Trả lời

1

Bạn cần có cách để theo dõi trạng thái của trang để bạn có thể phân biệt liệu bạn có đang thực hiện tác vụ hay không - trong trường hợp nào bạn muốn thay thế kết quả - hoặc thực hiện kết quả - trong trường hợp đó bạn muốn loại bỏ nội dung của phản hồi và thực hiện một ViewResult mới cho lỗi này. Giữ một lá cờ trong bộ điều khiển cơ sở sẽ là một cách để xử lý điều này. Bạn cũng có thể biết dựa trên loại ngoại lệ. Tôi không chắc là đáng tin cậy như thế nào.

Khi bạn tìm ra tình trạng bạn có thể làm:

var view = View("Error", data); 
if (executingResult) 
{ 
    filterContext.HttpContext.Response.ClearContent(); 
    view.ExecuteResult(); 
} 
else 
{ 
     filterContext.Result = view; 
     base.OnException(filterContext); 
} 

Bình luận: Nói chung tôi không ủng hộ việc này. Tôi nghĩ rằng hành động điều khiển của bạn nên bảo đảm cho View rằng tất cả các dữ liệu cần thiết là có hoặc View của bạn nên được viết phòng thủ để đảm bảo rằng không có ngoại lệ (đặc biệt là NullReferenceExceptions) không xảy ra.

12

Đây là câu hỏi cũ, nhưng đối với bất kỳ ai đang tìm kiếm, mã này hoạt động cho tôi, ngoại trừ bất kỳ đâu - trong bộ điều khiển, hành động hoặc kết quả hành động, tức là chế độ xem hoặc bất kỳ người trợ giúp nào mà chế độ xem gọi. (Tôi đã lấy nó từ cuốn sách của Steve Sanderson, để cho nó thuộc về nơi nào):

protected override void OnException(ExceptionContext filterContext) 
    { 
     if (filterContext.ExceptionHandled) 
      return; 

     //Let the request know what went wrong 
     filterContext.Controller.TempData["Exception"] = filterContext.Exception; 

     //redirect to error handler 
     filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(
      new { controller = "Exception", action = "HandleError" })); 

     // Stop any other exception handlers from running 
     filterContext.ExceptionHandled = true; 

     // CLear out anything already in the response 
     filterContext.HttpContext.Response.Clear(); 
    } 
+0

Đẹp, đã sử dụng một phần của nó và nó hoạt động rất tốt. – Andrew

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