8

我遇到了将项目升级到 .Net 4.0 的问题......并且无法找到问题的任何原因(或者至少是导致它的更改)。鉴于 4.0 的新鲜度,还没有很多博客讨论问题,所以我希望这里有人有想法。前言:这是一个 Web Forms 应用程序,从 3.5 SP1 到 4.0。

如果Application_Start我们遍历 SiteMap 并根据那里的数据构建路由(美化 URL 主要是添加了一些实用程序),那部分并没有失败……或者至少没有走那么远。

似乎调用SiteMap.RootNode(在 application_start 内)会导致 4.0 吃掉它,因为XmlSiteMapProvider.GetNodeFromXmlNode方法已更改,查看反射器可以看到它在HttpResponse.ApplyAppPathModifier这里击中:

str2 = HttpContext.Current.Response.ApplyAppPathModifier(str2);

HttpResponse在 2.0 CLR 的这个方法中根本没有使用,所以我们工作得很好,但是在 4.0 中,这个方法被调用作为这个堆栈的结果:

[HttpException (0x80004005): Response is not available in this context.]
System.Web.XmlSiteMapProvider.GetNodeFromXmlNode(XmlNode xmlNode, Queue queue)
System.Web.XmlSiteMapProvider.ConvertFromXmlNode(Queue queue)
System.Web.XmlSiteMapProvider.BuildSiteMap()
System.Web.XmlSiteMapProvider.get_RootNode()
System.Web.SiteMap.get_RootNode()

由于Response在 4.0 中不可用,我们得到一个错误。要重现这一点,您可以将测试用例缩小到全局范围内:

protected void Application_Start(object sender, EventArgs e)
{
  var s = SiteMap.RootNode; //Kaboom!
  //or just var r = Context.Response; 
  //or var r = HttpContext.Current.Response;
  //all result in the same "not available" error
}

问题:我在这里遗漏了一些明显的东西吗? 或者,是否在 4.0 中添加了另一个推荐用于启动时与 SiteMap 相关的事件?

对于任何好奇/愿意提供帮助的人,我创建了一个非常小的项目(一个默认的 VS 2010 ASP.Net 4.0 站点,所有的花里胡哨都被删除了,只有一个空白的站点地图和Application_Start添加的代码)。这是一个 10kb 的小 zip,可在此处获得:http ://www.ncraver.com/Test/SiteMapTest.zip


更新:

不是一个很好的解决方案,但当前的解决方法是在 中完成工作Application_BeginRequest,如下所示:

private static bool routesRegistered = false;
protected void Application_BeginRequest(object sender, EventArgs e)
{
  if (!routesRegistered)
  {
    Application.Lock();
    if (!routesRegistered) RouteManager.RegisterRoutes(RouteTable.Routes);
    routesRegistered = true;
    Application.UnLock();
  }
}

我特别不喜欢这样,感觉像是滥用事件来绕过问题。有没有人至少有更好的解决方法,因为 SiteMap 的 .Net 4 行为不太可能改变?

4

1 回答 1

6

由于对此没有任何活动,因此将此作为稍后接受的答案,希望对其他人有所帮助:

我目前的迂回解决方案(真正的解决方法)是进行SiteMap相关的初始化工作,Application_BeginRequest并检查它是否发生一次,如下所示:

private static bool routesRegistered = false;
protected void Application_BeginRequest(object sender, EventArgs e)
{
  if (!routesRegistered)
  {
    Application.Lock();
    if (!routesRegistered) RouteManager.RegisterRoutes(RouteTable.Routes);
    routesRegistered = true;
    Application.UnLock();
  }
}

如果一周内没有人用更好的方法做出回应,我会接受这个,但我希望有更好的方法/我错过的东西。

于 2010-05-24T11:38:21.720 回答