2010-03-08 46 views
10

Tôi đã tạo một ứng dụng ASP.NET MVC phiên bản 1.0 đơn giản. Tôi có một ProductController có một chỉ số hành động. Trong khung nhìn, tôi đã tạo một Index.aspx tương ứng trong thư mục con của Product.ASP.NET MVC View Engine Resolution Sequence

Sau đó, tôi đã tham chiếu tệp dll Spark và tạo Index.spark trong cùng một thư mục Chế độ xem sản phẩm. Các Application_Start trông giống như

protected void Application_Start() 
    { 
     RegisterRoutes(RouteTable.Routes); 

     ViewEngines.Engines.Clear(); 
     ViewEngines.Engines.Add(new Spark.Web.Mvc.SparkViewFactory()); 

     ViewEngines.Engines.Add(new WebFormViewEngine()); 

    } 

Kỳ vọng của tôi là kể từ khi đăng ký cơ Spark trước WebFormViewEngine mặc định, khi duyệt các hành động Index trong điều khiển sản phẩm, động cơ Spark nên được sử dụng, và WebFormViewEngine nên được sử dụng cho tất cả các url khác.

Tuy nhiên, thử nghiệm cho thấy hành động Chỉ mục cho Bộ điều khiển sản phẩm cũng sử dụng WebFormViewEngine.

Nếu tôi nhận xét việc đăng ký WebFormViewEnginer (dòng cuối cùng trong mã), tôi có thể thấy rằng hành động Index được kết xuất bởi công cụ Spark và các url còn lại tạo ra lỗi (vì động cơ defualt biến mất), chứng minh rằng tất cả mã Spark của tôi là chính xác.

Bây giờ câu hỏi của tôi là cách công cụ xem được giải quyết? Tại sao chuỗi đăng ký không có hiệu lực?

Trả lời

18

Thứ tự mà bạn đăng ký công cụ xem không quan trọng (nhiều). Thay vào đó, công cụ xem có một bộ ViewLocationFormats và nếu đường dẫn chế độ xem cụ thể phù hợp với tên được định dạng, công cụ đó sẽ được sử dụng. Chỉ khi bạn có các định dạng xung đột thì vấn đề đặt hàng là vấn đề.

Trong trường hợp phát ra tia lửa, lượt xem phải có phần mở rộng .spark. WebFormViewEngine sẽ phản hồi với bất kỳ tiện ích nào có các tiện ích mở rộng .aspx hoặc .ascx. Và tất nhiên, như đã đề cập ở trên, bạn có thể ghi đè lên bất kỳ điều này bằng cách thay đổi ViewLocationFormats được cung cấp cho các công cụ xem riêng lẻ.


Cập nhật:

Tôi đã xem qua nguồn gốc của cả hai SparkViewFactoryWebFormViewEngine (hay cụ thể hơn, VirtualPathProviderViewEngine, đó Xuất phát sau từ), và tôi có thể cho bạn biết lý do tại sao bạn thấy hành vi kỳ lạ này.

Trước hết, các Find phương thức trong lớp ViewEngineCollection làm việc như thế này (giản thể):

foreach (IViewEngine engine in Items) { 
    // Query engine for cached view 
} 

foreach (IViewEngine engine in Items) { 
    // Query engine for uncached view 
} 

Nói cách khác, nó sẽ luôn luôn cố gắng tìm một cái nhìn lưu trữ, trong bất kỳ công cụ, trước khi sử dụng chế độ uncached.

Cách thức các công cụ xem cá nhân thực hiện điều này là quá tải thứ hai của phương pháp FindView, có một đối số bool có tên useCache.

Tuy nhiên, và đây là nơi mà tất cả trở nên kỳ lạ - những VirtualPathProviderViewEngineSparkViewEngine có những ý tưởng rất khác nhau về những gì đối số useCache nghĩa.Có quá nhiều mã để repost ở đây nhưng ý tưởng cơ bản là:

  • Các SparkViewFactory sẽ xem xét chỉ trong bộ nhớ cache nếu useCachetrue. Nếu nó không tìm thấy bất cứ điều gì, nó sẽ tự động trả về một "kết quả bỏ lỡ bộ nhớ cache" - nghĩa là không có gì. Mặt khác, nếu useCachefalse, nó sẽ không nhìn vào bộ nhớ cache chút nào, nó sẽ bỏ qua bước kiểm tra bộ nhớ cache và thực hiện các chuyển động thông thường để giải quyết và tạo chế độ xem thực.

  • Các VirtualPathProviderViewEngine, mặt khác, trông trong bộ nhớ cache nếu useCachetrue, và nếu nó không tìm ra xem trong bộ nhớ cache, nó xuất phát và tạo ra một cái mới và cho biết thêm rằng vào bộ nhớ cache .

Cả hai cách tiếp cận này hoạt động theo cách ViewEngineCollection thực hiện tìm kiếm.

  • Trong trường hợp của tia lửa, nó "bỏ lỡ" trên phiên đầu tiên của động cơ xem, nhưng "hit" ngày thứ hai, và sau đó quan điểm được bổ sung vào bộ nhớ cache. Không vấn đề gì.

  • Trong trường hợp VirtualPathProviderViewEngine, nó "bỏ lỡ" nội bộ nhưng vẫn trả về "lần truy cập" vào lần lặp đầu tiên, lúc này chế độ xem giờ được lưu vào bộ nhớ cache.

Vì vậy, bạn sẽ có thể biết được vấn đề ở đây. Các VirtualPathProviderViewEngine chỉ xuất hiện để được tham gia được ưu tiên hơn các SparkViewEngine vì cựu luôn thành công trên (cached) lặp đầu tiên , nhưng Spark chỉ thành công ngày thứ hai (uncached) lặp .

Bằng tiếng Anh đơn giản, Spark thực sự được hỏi trước, nhưng trả lời: "Không, tôi không có chế độ xem đó nhưng. Hãy thử nó mà không cần bộ nhớ cache thay thế." WebForms được yêu cầu thứ hai, nhưng tự động nói "I không có chế độ xem đó, nhưng tôi đã từng tạo và tạo một tài khoản cho bạn ở đây.". Và từ thời điểm đó, các WebFormViewEngine luôn được ưu tiên vì nó có chế độ xem được lưu trong bộ nhớ cache và Spark thì không.


Tóm tắt: Spark nhận được ưu tiên, nhưng do một đứa trong cách đối xử với Spark lập luận useCache, nó nhận được còn lại trong bụi khi động cơ Mẫu Web đang hoạt động cùng một lúc. Hoặc WebForm là quá háo hức hoặc Spark là lười biếng, tùy thuộc vào quan điểm của bạn.

Nói một cách đơn giản, giải pháp là không có chế độ xem xung đột! Nếu bạn đã đăng ký nhiều công cụ xem, thì bạn nên xử lý bất kỳ tên chế độ xem nào có thể được xử lý bởi một trong hai/hai trong số chúng là hành vi không xác định.

+0

Để tóm tắt: Xóa tệp Index.aspx sẽ tạo Index.spark được sử dụng. – LukLed

+0

Tôi vẫn chưa hiểu lắm. ViewLocationFormats được định nghĩa trong VirtualPathProviderViewEngine, nó là một thực hiện nội bộ cụ thể cho một công cụ xem. Nếu ASP.NET MVC có nhiều công cụ xem được đăng ký, nó sẽ truy vấn từng cái một để xem liệu một công cụ xem có thể xử lý yêu cầu đó hay không. Công cụ xem đầu tiên trả lời có xử lý yêu cầu. Trong trường hợp của tôi, cả Spark và WebFormViewEngine đều có thể xử lý yêu cầu này từ Index.aspx và Index.spark. Vậy tại sao WebForViewEngine alwasy lại được ưu tiên? – intangible02

+0

@ intangible02: Đã kiểm tra và xác minh, tôi đào qua nguồn và bây giờ có một lời giải thích cho điều đó, hãy xem. – Aaronaught

1

Hmmm ... Không - tất cả các biểu mẫu web tôn trọng không thực hiện bất kỳ điều gì ngoài kiểm tra bộ nhớ cache khi useCache là đúng. Giống như Spark.

Thực ra - Tôi nghĩ ai đó có thể đã di chuyển pho mát của tôi ... Spark có thể đã có một sự gian lận thêm gây ra một bộ nhớ cache sai-miss trong quá trình sử dụng passCache == true. Nếu đó là sự thật thì đó là lỗi nhiều hơn các quy tắc khác nhau được áp dụng cho tham số đó.


Cập nhật:

tôi đang tìm kiếm tại MVC 2 ban đầu - đó là lý do tôi ngụ ý @ kết luận Aaronaught của không chính xác. MVC 2 không trả về một lượt xem trên pass đầu tiên trong đó useCache == true, khác với MVC 1.0 sẽ giải quyết và cư trú.

Vì vậy, sự khác biệt nằm giữa cách ASP.NET MVC 1.0 và ASP.NET MVC 2 được triển khai. Spark và MVC 2 coi cờ useCache giống nhau, và thứ tự chúng được đăng ký sẽ ưu tiên cho chúng.

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