2008-10-13 16 views
5

Tôi đang cố gắng xử lý lỗi trong MVC. Những gì tôi đang tìm kiếm là một cách tập trung để bắt lỗi, ghi nhật ký chúng, nếu có thể giải quyết chúng, nếu không có các hành động khác và cuối cùng hiển thị chế độ xem chính xác cho người dùng.Xử lý lỗi với ErrorController thay vì xem trực tiếp

Tôi nghĩ rằng tôi có thể sử dụng bộ lọc [HandleError] cho điều này, nhưng tôi không thấy bất kỳ cách nào để định tuyến cho Bộ điều khiển/Hành động. Tùy chọn duy nhất tôi thấy là chỉ nó trực tiếp vào một khung nhìn.

Trả lời

4

HandleErrorAttribute đi kèm với MVC là trình duyệt IExceptionFilter khá cơ bản.

Bạn có một vài tùy chọn để đạt được những gì tôi nghĩ bạn muốn.

Bạn có thể sử dụng [HandleError (Type = typeof (MyException), Xem = "ErrorView")] trên hành động/điều khiển hoặc thực hiện của riêng

HandleErrorAttribute isnt rất phức tạp. Tôi nghĩ MS đề nghị bạn sao chép mã này và sửa đổi cho phù hợp với yêu cầu của bạn.

Ghi đè OnException cho phép bạn truy cập vào tất cả thông tin mà bạn có thể cần - điều khiển, hành động, dữ liệu tuyến đường, v.v. - thông qua ExceptionContext.

Hãy nhớ đặt ExceptionHandled. Sau đó, bạn có thể đặt filterContext.Result thành một thể hiện RedirectToAction mới chuyển hướng đến ErrorController và hành động của bạn - rõ ràng là bạn có thể trưng ra bộ điều khiển và hành động cụ thể với các thuộc tính.

+0

HandleError chuẩn không cho phép tôi định tuyến đến bộ điều khiển mà tôi nghĩ. Vì vậy, đó không phải là những gì tôi cần. Tôi nghĩ rằng tôi sẽ phải cuộn của riêng tôi sau đó. Không xảy ra bất kỳ tài liệu nào tốt để tham khảo ở đây? –

+0

Yup, http://haacked.com/archive/2008/08/14/aspnetmvc-filters.aspx – CVertex

+1

Jep, nhận thấy các liên kết trong thư trả lời của bạn trễ một chút: P Cảm ơn. Tôi đang tạo một RerouteFilterAttribute ngay bây giờ. Có khá một số thử/lỗi đang diễn ra, nhưng tôi sẽ đến đó. –

1

Tại sao không tạo lỗi ErrorResult của riêng bạn từ ActionResult?

0

Những gì tôi đang làm (mà có thể hoặc không thể là một thực hành tốt) là thế này:

Khi một lỗi xảy ra:

  • Nếu tôi mong đợi nó và có thể xử lý nó, tôi làm (đăng nhập nó với ELMAH)
  • Nếu tôi mong đợi nó và không thể xử lý nó, tôi đăng nhập nó vào ELMAH và trả về một ViewResult đó là trang lỗi của tôi
    • Bao gồm một mô tả về lỗi, một thông báo tiêu chuẩn và một liên kết lại với những gì tôi đang làm
  • Nếu tôi không mong đợi nó, ghi đè của tôi về onerror trong lớp điều khiển cơ sở của tôi không bước trước
  • Tất cả các lỗi khác mà không thể xử lý được tự động đăng nhập bằng ELMAH và yellowscreens yêu cầu

Hầu hết xử lý lỗi chung của tôi đều nằm trong lớp cơ sở cho tất cả các trình điều khiển của tôi. Vấn đề duy nhất là tôi phải tự thiết lập một bộ điều khiển và giá trị hành động trong lớp cơ sở để nó có thể tạo ra một ActionLink cho chuyển hướng trong trang lỗi.

+0

Bộ lọc dường như là cách để xử lý lỗi thay vì ghi đè onerror. Họ đang trực giao độc đáo với bộ điều khiển. – CVertex

+0

Đánh giá cao phản hồi, nhưng tôi không muốn đặt xử lý lỗi trong cùng một lớp với bộ điều khiển cơ sở của tôi. Điều này sẽ khiến lớp cơ sở của tôi ít sử dụng được hơn vì logic xử lý lỗi thường khác nhau đối với mọi trang web. Tôi hiện đang tạo bộ lọc RerouteErrorAttribute để thực hiện công việc. –

2

Leppi, iNếu bạn muốn gửi đến kết quả hành động, bạn có thể xác định hành động và bộ điều khiển để chuyển hướng trên lỗi. Đó là một ví dụ tốt, nhưng personaly tôi không thích sử dụng các trang tùy chỉnh hoặc mã http để mã

Đây là ví dụ về IExtenptionFilter của tôi. Trình kiểm soát cơ sở của tôi có IExceptionFilter mặc định để xử lý tất cả các lỗi không được kiểm soát.

[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", 
    Justification = "This attribute is AllowMultiple = true and users might want to override behavior.")] 
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] 
public class GenericExceptionHandlerFilter : ActionFilterAttribute, IExceptionFilter 
{ 

    public Type ExceptionType { get; set;} 
    public string RedirectToAction { get; set;} 
    public string RedirectToController { get; set;} 

    protected bool ApplyFilter(ExceptionContext filterContext) 
    { 
     Type lExceptionType = filterContext.Exception.GetType(); 
     return (ExceptionType == null || 
       lExceptionType.Equals(ExceptionType)); 
    } 


    #region IExceptionFilter Members 
    public void OnException(ExceptionContext filterContext) 
    { 

     if (ApplyFilter(filterContext)) 
     { 
      IbfControllerLogger.Log(filterContext.Exception); 

      filterContext.ExceptionHandled = true; 

      #region Calculate Action Controller Error 
      RouteValueDictionary lRoutes = new RouteValueDictionary(new 
       { 
        action = RedirectToAction, 
        controller = String.IsNullOrEmpty(RedirectToController) ? (string)filterContext.RouteData.Values["controller"] : RedirectToController 
       }); 
      UrlReWriterUtils.UrlReWriter(filterContext.Controller.ViewData, lRoutes); 
      #endregion 

      filterContext.Controller.TempData[TempDataName.C_TEMPDATA_EXCEPTIONERROR] = filterContext.Exception; 
      filterContext.Result = new RedirectToRouteResult(lRoutes); 
     } 
    } 
    #endregion