2009-07-23 30 views
5

Tôi có trang web asp.net mvc 1.0 phục vụ một số nội dung từ hệ thống phân cấp 2 cấp /category/articleLàm thế nào để xử lý 'Xem không tìm thấy' InvalidOperationException trong asp.net MVC?

Khi mọi thứ hoạt động đúng với bản đồ sẽ được hiển thị. Tuy nhiên, khi url đáp ứng điều kiện định tuyến nhưng khung nhìn không tồn tại một ngoại lệ được nêu lên mà tôi không thể bẫy trong hành động Bộ điều khiển.

Routing:

routes.MapRoute(
    "Article", 
    "{category}/{article}.aspx", 
    new { controller = "MyController", action = "Article" } 
); 

MyController Hành động:

public ActionResult Article(string category, string article) 
{ 
    string path = string.Format("~/Views/{0}/{1}.aspx", category, article); 
    ViewResult vr = View(path); 
    return vr; 
} 

Tuy nhiên, khi xem không được tìm thấy, một System.InvalidOperationException được tạo ra mà tôi không thể bắt trong Action Controller.

Ngoại lệ chi tiết: System.InvalidOperationException: Quan điểm '~/Views/my-loại/my-article-với-dài-name.aspx' không thể tìm được hoặc thạc sĩ của nó . Các vị trí sau được tìm kiếm: ~/Views/my-loại/my-article-với-dài-name.aspx

tôi có thể bẫy lỗi trong phương pháp Application_Error() trong global.asax.cs nhưng:

  1. không biết cách chuyển hướng đến chế độ xem lỗi từ đó
  2. tự hỏi nếu có một nơi tốt hơn gần hơn với nơi ngoại lệ là được nêu ra.

Trả lời

7

xandy, Greg, Tôi đánh giá cao câu trả lời của bạn. Bài viết này (Strategies For Resource Based 404 Errors in aspnet mvc) đã giúp tôi lấy được giải pháp mà tôi đang tìm kiếm một cách khá rõ ràng. Tất cả những gì tôi cần làm là ghi đè lên Bộ điều khiển.OnException. Vì tôi chỉ có một bộ điều khiển mà tôi cần hành vi, tôi chỉ phải ghi đè OnException trong bộ điều khiển đó.

Điều đó đang được nói, giải pháp của tôi xử lý các triệu chứng không phải là bệnh và như cả hai bạn đề xuất, nó sẽ là tốt hơn để kiểm tra sự tồn tại của tập tin trước khi gọi this.View trên một con đường.

Đây là mã tôi đã sử dụng để điều trị các triệu chứng :)

protected override void OnException(ExceptionContext filterContext) 
{ 
    //InvalidOperationException is thrown if the path to the view 
    // cannot be resolved by the viewengine 
    if (filterContext.Exception is InvalidOperationException) 
    { 
     filterContext.ExceptionHandled = true; 
     filterContext.Result = View("~/Views/Error/NotFound.aspx"); 
     filterContext.HttpContext.Response.StatusCode = 404; 
    } 

    base.OnException(filterContext); 
} 

Một vấn đề tôi không thể giải quyết là làm thế nào để hiển thị notfound Xem theo một cách sạch sẽ. Nó thường được truy cập thông qua ErrorController NotFound Action. Tôi đã phải hardcode đường dẫn đến nó. Tôi có thể sống với điều này nhưng muốn biết nếu nó có thể w/o đường dẫn HC.

+0

Tôi đã thử và thích giải pháp. Vấn đề duy nhất là nếu bạn nhận được một InvalidOperationException do một lý do khác nhau nó sẽ dẫn đến một 404. Tôi đã có một ngoại lệ như vậy xảy ra khi cố gắng serialize một cái gì đó. – Bealer

0

Tôi nghĩ rằng nơi tốt nhất để kiểm tra xem chế độ xem có tồn tại trong bộ điều khiển hay không. Nếu bạn đóng gói hàm tạo của khung nhìn không hoạt động, thì có thể ASP.net trì hoãn việc tạo ra khung nhìn bên ngoài hàm tạo (không chắc chắn nếu nó là). Một điều bạn có thể thử là kiểm tra bằng tay và xem liệu đường dẫn có tồn tại hay không, sử dụng Server.MapPath() để lấy đường dẫn tệp tuyệt đối và kiểm tra xem nó có tồn tại hay không.

0

Tôi chỉ trả lại chế độ xem mặc định, có lẽ phản hồi 404 sẽ phù hợp. Tất nhiên để thực hiện công việc này, bạn sẽ cần phải thay đổi kiến ​​trúc của bạn một chút.

AFAIK bạn sẽ cần phải có một số mã để kiểm tra xem tệp có tồn tại hay không, như trong tệp ASPX nếu bạn không muốn hành vi khung mặc định. Bạn có thể phải sử dụng ResolveURL or Url.Content để giải quyết đường dẫn từ đường dẫn ứng dụng của bạn.

Như một lưu ý, nói chung, không an toàn để làm cho tên miền của bạn (tên tệp) được tiếp xúc với thế giới. Nếu ASPX chỉ là dữ liệu, thì bạn nên đặt văn bản vào cơ sở dữ liệu hoặc các tệp văn bản thuần túy, không thể thực thi được. Nếu bạn đang xây dựng một số loại CMS (tức là bạn thực sự muốn một cách 'cài đặt' chức năng), thì bạn có thể cân nhắc việc sử dụng chế độ xem ASPX để chứa một phần lượt xem để đóng gói các đoạn mã ASP.NET.

Để truy cập trang 404, this answer có thể hữu ích.

3

Có một nơi phù hợp để xử lý việc này. Nếu bạn triển khai ViewEngine của riêng mình, bạn có thể ghi đè phương thức "FileExists".

public class ViewEngine : RazorViewEngine 
{ 
    protected override bool FileExists(ControllerContext context, string path) 
    { 
     if(!base.FileExists(context, path)) 
      throw new NotFoundException(); 

     return true; 
    } 

}

Bạn chỉ cần đăng ký công cụ xem trong Global.asax của bạn như vậy,

ViewEngines.Engines.Clear(); 
ViewEngines.Engines.Add(new ViewEngine()); 

Trong Application_Error bạn có thể thực hiện một handler mà bắt NotFoundExceptions, ghi họ, sau đó trả về một thông điệp thân thiện thông qua việc thực hiện một ErrorController.

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