2010-03-08 31 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标志视为相同,并且它们注册的顺序将赋予它们优先级。