ASP.NET MVC视图引擎解析序列

int*_*e02 10 asp.net-mvc viewengine spark-view-engine

我创建了一个简单的ASP.NET MVC 1.0版应用程序.我有一个ProductController,它有一个动作索引.在视图中,我在Product子文件夹下创建了相应的Index.aspx.

然后我引用了Spark dll并在同一Product视图文件夹下创建了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());

    }
Run Code Online (Sandbox Code Playgroud)

我的期望是,由于Spark引擎在默认WebFormViewEngine之前注册,当浏览Product controller中的Index操作时,应该使用Spark引擎,并且WebFormViewEngine应该用于所有其他URL.

但是,测试显示Product控制器的Index操作也使用WebFormViewEngine.

如果我注释掉WebFormViewEnginer的注册(代码中的最后一行),我可以看到Index动作由Spark引擎呈现,其余的URL生成错误(因为defualt引擎已经消失),它证明了我所有的Spark代码是正确的.

现在我的问题是视图引擎是如何解决的?为什么注册序列不生效?

Aar*_*ght 19

注册视图引擎的顺序并不重要(很多).相反,视图引擎采用一组ViewLocationFormats,如果特定视图路径符合格式化名称,则将使用该引擎.只有当您的格式存在冲突时,注册顺序才会起作用.

在spark的情况下,视图应该具有.spark扩展名. WebFormViewEngine将回复任何有.aspx.ascx扩展.当然,如上所述,您可以通过更改ViewLocationFormats提供给各个视图引擎来覆盖任何此类操作.


更新:

我把通过两个来源看SparkViewFactoryWebFormViewEngine(或者更具体地说,VirtualPathProviderViewEngine,后者从导出),我可以告诉你为什么你看到这种奇怪的行为.

首先,类中的Find方法ViewEngineCollection就像这样(简化):

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

foreach (IViewEngine engine in Items) {
    // Query engine for uncached view
}
Run Code Online (Sandbox Code Playgroud)

换句话说,在使用非缓存模式之前,它总是会尝试在任何引擎中查找缓存视图.

各个视图引擎实现此FindView方法的方法是方法的第二个重载,它接受一个bool名为的参数useCache.

然而,这里的地方这一切会很奇怪-的VirtualPathProviderViewEngineSparkViewEngine具有的东西非常不同的看法useCache说法指.这里有太多代码要重新发布,但基本思路是:

  • SparkViewFactory看起来如果高速缓存useCachetrue.如果它没有找到任何内容,它会自动返回"缓存未命中结果" - 即没有.另一方面,如果useCachefalse,它根本不会查看缓存,它将跳过缓存检查步骤并通过正常运动来解析并创建实际视图.

  • VirtualPathProviderViewEngine,另一方面,看上去在缓存中,如果useCachetrue的,如果它没有找到在缓存中的观点,它熄灭,并创建一个新的,并补充说,到缓存中.

这两种方法都适用于ViewEngineCollection执行搜索的方式.

  • 在spark的情况下,它在视图引擎的第一次迭代中"未命中",但在第二次迭代时"命中",之后视图被添加到缓存中.没问题.

  • 在这种情况下VirtualPathProviderViewEngine,它在内部"未命中"但在第一次迭代时仍然返回"命中",此时视图现在被缓存.

所以你应该能够看到问题出在哪里.该VirtualPathProviderViewEngine似乎要优先于SparkViewEngine因为前者总是成功的第一(缓存)迭代,但仅Spark成功的第二个(未缓存)迭代.

用简单的英语,星火确实会首先询问,但回答:"不,我没有这样的观点尚未.尝试没有缓存来代替." WebForms被问到第二,但自动说"我没有那个视图,但无论如何我去为你做了一个,就在这里." .从那时起,WebFormViewEngine始终获得优先级,因为它具有缓存的视图,而Spark则没有.


总结:Spark 正在获得优先权,但由于Spark处理这个useCache论点的方式有些怪癖,当Web Form引擎同时处于活动状态时,它就会陷入困境.根据您的观点,WebForm过于热切或Spark很懒惰.

简单地说,解决方案不是有冲突的观点! 如果您已经注册了多个视图引擎,那么您应该将任何视图名称视为未定义的行为,这些视图名称可由其中一个/两个处理.