2010-03-08 30 views
10

我創建了一個簡單的ASP.NET MVC 1.0版應用程序。我有一個ProductController,它有一個操作索引。在該視圖中,我在Product子文件夾下創建了相應的Index.aspx。ASP.NET MVC視圖引擎分辨率序列

然後我引用了Spark dll並在相同的Product view文件夾下創建了Index.spark。在的Application_Start看起來像

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

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

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

    } 

我的期望是,由於默認WebFormViewEngine前的星火引擎註冊,瀏覽產品控制器中的索引操作時,星火引擎應該被使用,WebFormViewEngine應該用於其他所有網址。

但是,測試顯示產品控制器的Index操作也使用WebFormViewEngine。

如果我註釋掉WebFormViewEnginer(代碼中的最後一行)的註冊,我可以看到Index操作由Spark引擎呈現,其餘的urls生成一個錯誤(因爲defualt引擎已經消失),它證明我的所有Spark代碼都是正確的。

現在我的問題是如何解決視圖引擎?爲什麼註冊順序不生效?

回答

18

您註冊視圖引擎的順序並不重要(很多)。相反,視圖引擎需要一組ViewLocationFormats,如果某個特定的視圖路徑符合格式化的名稱,則將使用該引擎。只有在格式衝突的情況下,註冊訂單纔有意義。

在火花的情況下,意見應該有.spark擴展名。 WebFormViewEngine將回應任何與.aspx.ascx擴展名。當然,如上所述,您可以通過更改提供給各個視圖引擎的ViewLocationFormats來覆蓋這些內容。


更新時間:

我通過兩個SparkViewFactoryWebFormViewEngine源(或者更具體地說,VirtualPathProviderViewEngine,從後者導出)接過來一看,我可以告訴你爲什麼你看到這種奇怪的行爲。

首先,在ViewEngineCollection類的Find方法是這樣的(簡化):

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

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

換句話說,它總是試圖找到一個緩存的視圖,在任何引擎,前訴諸未緩存模式。

個別視圖引擎執行此操作的方式是FindView方法的第二次重載,該方法採用名爲useCachebool參數。

然而,這裏是在這一切會很奇怪 - 在VirtualPathProviderViewEngineSparkViewEngine具有的useCache說法的意思完全不同的想法。有太多的代碼在這裏重新發布,但基本思路是:

  • SparkViewFactory看起來只有在緩存中,如果useCachetrue。如果它找不到任何東西,它會自動返回「緩存未命中結果」 - 即沒有任何結果。另一方面,如果useCachefalse,它根本不會查看緩存,它將跳過緩存檢查步驟,並通過正常運動來解析並創建實際視圖。

  • VirtualPathProviderViewEngine,另一方面,看上去在緩存中,如果useCachetrue,如果它沒有找到在緩存中的觀點,它熄滅,並創建一個新的,並補充說,到緩存。

這些方法的兩個方面工作,以ViewEngineCollection執行其搜索的方式。

  • 在火花的情況下,在視圖引擎的第一次迭代,但在第二「命中」,並且該視圖被添加到高速緩存之後「未命中」。沒問題。

  • VirtualPathProviderViewEngine的情況下,它在內部「未命中」,但在第一次迭代中返回「命中」,此時視圖現在被緩存。

所以你應該能夠看到問題出在哪裏。該VirtualPathProviderViewEngine只有出現要優先於SparkViewEngine因爲前者總是在第一(緩存)迭代成功,但僅Spark成功的第二(非高速緩存)迭代。

用簡單的英文,Spark確實會被問到,但回覆:「不,我沒有那個視圖。試試它沒有緩存來代替。 WebForms被問到第二,但自動說「我沒有有這樣的觀點,但我去了,無論如何,爲你做了一個,在這裏。」。從那時起,WebFormViewEngine總是獲得優先權,因爲它具有緩存的視圖,而Spark沒有。


摘要:星火獲得優先權,但由於方式星火一個怪癖對待useCache的說法,這是越來越拋在後面,當Web窗體引擎是在同一時間激活。根據您的觀點,WebForm或者是懶惰的WebForm。

簡而言之,解決方案是不會有衝突的意見!如果您已經註冊了多個視圖引擎,那麼您應該將任何視圖名稱都視爲未定義的行爲

+0

總結:刪除文件的Index.aspx會讓Index.spark使用。 – LukLed

+0

我還是不太明白。 ViewLocationFormats在VirtualPathProviderViewEngine中定義,它是特定於視圖引擎的內部實現。 如果ASP.NET MVC已經註冊了多個視圖引擎,它會查詢逐一查看視圖引擎是否可以處理請求。第一個視圖引擎回答是處理請求。在我的情況下,既然Index.aspx和Index.spark在那裏,Spark和WebFormViewEngine都可以處理這個請求。那麼爲什麼WebForViewEngine alwasy優先? – intangible02

+0

@ intangible02:測試和驗證,我通過源挖出,現在有針對的解釋,一起來看看。 – Aaronaught

1

嗯......沒有 - 當useCache爲true時,所有應有的尊重webforms都不會執行超出緩存檢查的任何操作。和Spark一樣。

其實 - 我想可能是有人動了我的奶酪?星火可能有一個怪癖添加useCache將==真傳中造成錯誤高速緩存未命中。如果這是真的,那麼它就比應用於該參數的不同規則更具缺陷。


更新時間:

我一直在尋找MVC 2原來 - 這就是爲什麼我暗示@ Aaronaught的結論是不正確的。 MVC 2不返回useCache == true的第一遍視圖,這在MVC 1.0中會有所不同,它將解析和填充。

所以差是這樣的ASP.NET MVC 1.0和ASP.NET MVC 2被實現之間。 Spark和MVC 2將useCache標誌視爲相同,並且它們註冊的順序將賦予它們優先級。