10

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

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

    }

我的期望是,由于 Spark 引擎在默认 WebFormViewEngine 之前注册,所以当浏览 Product 控制器中的 Index 操作时,应该使用 Spark 引擎,而 WebFormViewEngine 应该用于所有其他 url。

但是,测试表明 Product 控制器的 Index 操作也使用了 WebFormViewEngine。

如果我注释掉 WebFormViewEnginer 的注册(代码中的最后一行),我可以看到 Index 操作由 Spark 引擎呈现,其余 url 生成错误(因为默认引擎消失了),这证明了我所有的火花代码是正确的。

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

4

2 回答 2

19

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

在 spark 的情况下,视图应该具有.spark扩展名。 WebFormViewEngine将响应任何带有.aspx.ascx扩展名的内容。当然,如上所述,您可以通过更改ViewLocationFormats提供给各个视图引擎的内容来覆盖其中的任何内容。


更新:

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

首先,类Find中的方法是ViewEngineCollection这样工作的(简化):

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

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

换句话说,它总是会尝试在任何引擎中找到缓存视图,然后再诉诸非缓存模式。

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

然而,这就是一切变得奇怪的地方 -VirtualPathProviderViewEngine并且对论点SparkViewEngine的含义有非常不同的想法。useCache这里有太多代码要重新发布,但基本思想是:

  • 如果是,则只会在缓存中SparkViewFactory查找。如果它没有找到任何东西,它会自动返回一个“缓存未命中结果”——即什么也没有。另一方面,如果是,它根本不会在缓存中查找,它会跳过缓存检查步骤并通过正常动作来解决并创建实际视图。useCachetrueuseCachefalse

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

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

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

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

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

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


总结:Spark正在获得优先权,但由于 Spark 处理useCache参数的方式有一个怪癖,当 Web 表单引擎同时处于活动状态时,它就会被抛在一边。取决于您的观点,WebForm 是过度渴望还是 Spark 是懒惰的。

简而言之,解决方案是不要有冲突的观点! 如果您已经注册了多个视图引擎,那么您应该将任何一个/两者都可以处理的视图名称视为未定义行为

于 2010-03-08T03:49:39.293 回答
1

嗯......不 - 当 useCache 为真时,所有应有的尊重 webforms 不会做任何超出缓存检查的事情。与火花相同。

实际上 - 我认为有人可能移动了我的奶酪...... Spark 可能添加了一个怪癖,导致在 useCache==true 传递期间出现错误的缓存未命中。如果这是真的,那么与应用于该参数的不同规则相比,它更像是一个错误。


更新:

我最初正在查看 MVC 2 - 这就是为什么我暗示 @Aaronaught 的结论是不正确的。MVC 2 不会在 useCache==true 的第一遍返回视图,这在 MVC 1.0 中是不同的,它将解析和填充。

所以区别在于 ASP.NET MVC 1.0 和 ASP.NET MVC 2 的实现方式。Spark 和 MVC 2 对 useCache 标志的处理是一样的,它们注册的顺序会赋予它们优先级。

于 2010-05-19T07:21:18.260 回答