views:

142

answers:

1

I'm running into an issue upgrading a project to .Net 4.0...and having trouble finding any reason for the issue (or at least, the change causing it). Given the freshness of 4.0, not a lot of blogs out there for issues yet, so I'm hoping someone here has an idea. Preface: this is a Web Forms application, coming from 3.5 SP1 to 4.0.

In the Application_Start event we're iterating through the SiteMap and constructing routes based off data there (prettifying URLs mostly with some utility added), that part isn't failing though...or at least isn't not getting that far.

It seems that calling the SiteMap.RootNode (inside application_start) causes 4.0 to eat it, since the XmlSiteMapProvider.GetNodeFromXmlNode method has been changed, looking in reflector you can see it's hitting HttpResponse.ApplyAppPathModifier here:

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

HttpResponse wasn't used at all in this method in the 2.0 CLR, so what we had worked fine, in 4.0 though, that method is called as a result of this stack:

[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()

Since Response isn't available here in 4.0, we get an error. To reproduce this, you can narrow the test case down to this in global:

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
}

Question: Am I missing something obvious here? Or, is there another event added in 4.0 that's recommended for anything related to SiteMap on startup?

For anyone curious/willing to help, I've created a very minimal project (a default VS 2010 ASP.Net 4.0 site, all the bells & whistles removed and only a blank sitemap and the Application_Start code added). It's a small 10kb zip available here: http://www.ncraver.com/Test/SiteMapTest.zip


Update:

Not a great solution, but the current work-around is to do the work in Application_BeginRequest, like this:

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();
  }
}

I don't like this particularly, feels like an abuse of the event to bypass the issue. Does anyone have at least a better work-around, since the .Net 4 behavior with SiteMap is not likely to change?

A: 

Since there has been no activity on this, leaving this as the answer to accept later, hoping it helps someone else:

My current round-about solution (workaround really) is to do the SiteMap related initialization work in Application_BeginRequest with a check for it to occur once, like this:

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();
  }
}

If no one responds with a better method in a week I'll accept this, but I'm hoping there's a better way/something I've missed.

Nick Craver