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

Asp.net mvc ASP.NET MVC视图引擎解析序列,asp.net-mvc,spark-view-engine,viewengine,Asp.net Mvc,Spark View Engine,Viewengine,我创建了一个简单的ASP.NET MVC 1.0版应用程序。我有一个ProductController,它有一个操作索引。在视图中,我在Product子文件夹下创建了相应的Index.aspx 然后,我引用了Spark dll并在同一产品视图文件夹下创建了Index.Spark。应用程序的启动看起来像 protected void Application_Start() { RegisterRoutes(RouteTable.Routes); V

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

然后,我引用了Spark dll并在同一产品视图文件夹下创建了Index.Spark。应用程序的启动看起来像

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

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

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

    }
我的期望是,由于Spark引擎在默认WebFormViewEngine之前注册,因此在Product controller中浏览索引操作时,应使用Spark引擎,而WebFormViewEngine应用于所有其他URL

但是,测试表明Product controller的索引操作也使用WebFormViewEngine

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


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

注册视图引擎的顺序无关紧要。相反,视图引擎采用一组
ViewLocationFormats
,如果特定的视图路径符合格式化名称,则将使用该引擎。只有在格式冲突的情况下,注册顺序才重要

对于spark,视图应具有
.spark
扩展名
WebFormViewEngine
将使用
.aspx
.ascx
扩展名响应任何请求。当然,如上所述,您可以通过更改提供给各个视图引擎的
ViewLocationFormats
来覆盖所有这些


更新:

我查看了
SparkViewFactory
WebFormViewEngine
(或者更具体地说,
VirtualPathProviderViewEngine
,后者的来源)的源代码,我可以告诉您为什么会看到这种奇怪的行为

首先,
ViewEngineCollection
类中的
Find
方法的工作原理如下(简化):

换句话说,它总是在任何引擎中尝试查找缓存视图,然后再求助于uncached模式

单个视图引擎实现这一点的方式是
FindView
方法的第二个重载,该方法使用名为
useCache
bool
参数

然而,
VirtualPathProviderViewEngine
SparkViewEngine
useCache
参数的含义有着截然不同的理解。这里有太多代码需要重新发布,但基本思想是:

  • 如果
    useCache
    true
    ,则
    SparkViewFactory
    将仅在缓存中查找。如果找不到任何内容,它会自动返回“缓存未命中结果”-即无。另一方面,如果
    useCache
    false
    ,它将根本不在缓存中查找,它将跳过缓存检查步骤,并通过正常动作解析并创建实际视图

  • 另一方面,如果
    useCache
    true
    ,则
    VirtualPathProviderViewEngine
    会在缓存中查找,如果在缓存中找不到视图,则会关闭并创建一个新视图,并将其添加到缓存中。

这两种方法都与
ViewEngineCollection
执行搜索的方式有关

  • 对于spark,它在视图引擎的第一次迭代中“未命中”,但在第二次迭代中“命中”,然后将视图添加到缓存中。没问题

  • VirtualPathProviderViewEngine
    的情况下,它在内部“未命中”,但在第一次迭代时仍返回“命中”,此时视图现在被缓存

所以你应该能看到问题在哪里。
VirtualPathProviderViewEngine
似乎优先于
SparkViewEngine
,因为前者总是在第一次(缓存)迭代中成功,而Spark只在第二次(未缓存)迭代中成功

用简单的英语说,Spark确实是第一个被问到的,但是回答:“不,我还没有那个视图,请在没有缓存的情况下试试。”WebForms被问到第二个问题,但自动说“我没有那个视图,但我还是去为你做了一个,在这里。”。从那时起,
WebFormViewEngine
总是获得优先权,因为它缓存了视图,而Spark没有


小结:Spark正在获得优先级,但由于Spark处理
useCache
参数的方式有一个怪癖,当Web表单引擎同时处于活动状态时,它就被抛在了后面。WebForm要么过于急切,要么Spark懒惰,这取决于您的视角


简单地说,解决方案是不要有冲突的观点如果您注册了多个视图引擎,那么您应该将其中一个/两个可以处理的任何视图名称视为未定义的行为。。。不-当useCache为true时,所有应有的尊重webforms除了缓存检查之外不会做任何事情。和Spark一样

事实上,我想可能有人动了我的奶酪。。。Spark可能添加了一个怪癖,导致在useCache==true过程中出现错误缓存未命中。如果这是真的,那么它更像是一个bug,而不是应用于该参数的不同规则


更新:

我最初是在看MVC2,这就是为什么我暗示@Aaronaught的结论是不正确的。MVC 2在第一次传递时不返回useCache==true的视图,这与MVC 1.0中的不同,MVC 1.0将解析和填充该视图

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