我创建了一个简单的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());
}
我的期望是,由于Spark引擎在默认WebFormViewEngine之前注册,当浏览Product controller中的Index操作时,应该使用Spark引擎,并且WebFormViewEngine应该用于所有其他URL .
但是,测试显示Product控制器的Index操作也使用WebFormViewEngine .
如果我注释掉WebFormViewEnginer的注册(代码中的最后一行),我可以看到Index动作由Spark引擎呈现,其余的URL生成错误(因为defualt引擎已经消失),它证明了我所有的Spark代码是正确的 .
现在我的问题是视图引擎是如何解决的?为什么注册序列不生效?
2 回答
注册视图引擎的顺序并不重要(很多) . 相反,视图引擎采用一组
ViewLocationFormats
,如果特定视图路径符合格式化名称,则将使用该引擎 . 只有当您的格式存在冲突时,注册顺序才会起作用 .在spark的情况下,视图应该具有
.spark
扩展名 .WebFormViewEngine
将通过.aspx
或.ascx
扩展回复任何内容 . 当然,如上所述,您可以通过更改提供给各个视图引擎的ViewLocationFormats
来覆盖任何此类操作 .Updated:
我看了一下
SparkViewFactory
和WebFormViewEngine
(或者更具体地来说,VirtualPathProviderViewEngine
,后者来自)的来源,我可以告诉你为什么你会看到这种奇怪的行为 .首先,
ViewEngineCollection
类中的Find
方法的工作原理如下(简化):换句话说,在诉诸非缓存模式之前,它总是会尝试在 any 引擎中找到缓存视图 .
各个视图引擎实现此方法的方式是
FindView
方法的第二个重载,该方法采用名为useCache
的bool
参数 .However ,这里的一切都变得奇怪 -
VirtualPathProviderViewEngine
和SparkViewEngine
对useCache
论证的含义有着截然不同的看法 . 这里有太多代码要重新发布,但基本思路是:如果
useCache
是true
,SparkViewFactory
将在缓存中显示 only . 如果它没有找到任何东西,它会自动返回"cache miss result" - 即没有 . 另一方面,如果useCache
是false
,它根本不会查看缓存,它将跳过缓存检查步骤并通过正常运动来解析并创建实际视图 .另一方面,如果
useCache
是true
,VirtualPathProviderViewEngine
会在缓存中查找,如果它在缓存中找不到该视图, it goes off and creates a new one and adds that to the cache.这两种方法都适用于
ViewEngineCollection
执行搜索的方式 .在spark的情况下,它在视图引擎的第一次迭代中“未命中”,但在第二次迭代时“命中”,之后视图被添加到缓存中 . 没问题 .
在
VirtualPathProviderViewEngine
的情况下,它在内部"misses"但在第一次迭代时仍然返回"hit",此时视图现在被缓存 .所以你应该能够看到问题出在哪里 .
VirtualPathProviderViewEngine
似乎仅优先于SparkViewEngine
,因为前者总是在 first (缓存)迭代上成功,但Spark仅在 second (未缓存)迭代上成功 .用简单的英语,Spark确实首先被问到,但回复:“不,我没有那个视图 yet . 试着没有缓存而是 . ” WebForms被问到第二,但自动说“我 didn't 有那种观点,但无论如何我去为你做了一个,这里是 . ” . 从那时起,
WebFormViewEngine
总是获得优先权,因为它有缓存视图而Spark没有 .总结:Spark is 获得优先权,但由于Spark处理
useCache
参数的方式有些怪癖,当Web Form引擎同时处于活动状态时,它仍然处于灰尘状态 . 根据您的观点,WebForm过于热切或Spark很懒惰 .简单地说,解决方案是 not to have conflicting views! 如果您已经注册了多个视图引擎,那么您应该处理任何可以由两个/两个处理的视图名称他们是 undefined behaviour .
嗯...没有 - 当useCache为true时,所有应有的尊重webforms都不会执行任何超出缓存检查的操作 . 与Spark相同 .
实际上 - 我认为有人可能会移动我的奶酪...... Spark可能会在useCache == true pass期间添加一个怪癖导致错误的缓存缺失 . 如果这是真的,那么与应用于该参数的不同规则相比,它更像是一个错误 .
更新:
我最初看的是MVC 2 - 这就是为什么我暗示@Aaronaught的结论不正确 . MVC 2不会在第一次传递中返回一个视图,其中useCache == true,这与MVC 1.0中的不同将解析和填充 .
因此,ASP.NET MVC 1.0和ASP.NET MVC 2的实现方式之间存在差异 . Spark和MVC 2对useCache标志的处理方式相同,它们注册的顺序将赋予它们优先权 .