Я столкнулся с проблемой при обновлении проекта до .Net 4.0 ... и не могу найти причину проблемы (или, по крайней мере, вызвавшее ее изменение). Учитывая свежесть 4.0, пока не так много блогов с описанием проблем, поэтому я надеюсь, что у кого-то есть идея. Предисловие: это приложение веб-форм, начиная с версии 3.5 SP1 до 4.0.
В событии Application_Start мы перебираем SiteMap и строим маршруты на основе имеющихся там данных (в основном уточняем URL-адреса с помощью некоторой добавленной утилиты), но эта часть не дает сбоев ... или, по крайней мере, не заходит так далеко.
Похоже, что вызов SiteMap.RootNode (внутри application_start) заставляет 4.0 его съесть, поскольку метод XmlSiteMapProvider.GetNodeFromXmlNode был изменен, глядя в отражатель, вы можете увидеть, что он попадает в _ 3_ здесь:
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). Это небольшой zip-архив размером 10 КБ, который доступен здесь: 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();
}
}
Мне это особенно не нравится, это похоже на злоупотребление мероприятием, чтобы обойти проблему. У кого-нибудь есть хотя бы лучший обходной путь, поскольку поведение .Net 4 с SiteMap вряд ли изменится?