ASP.Net 4.0 - Ответ требуется при создании SiteMap? - PullRequest
8 голосов
/ 03 мая 2010

Я столкнулся с проблемой при обновлении проекта до .Net 4.0 ... и не могу найти причину проблемы (или, по крайней мере, изменения, вызывающие ее). Учитывая свежесть 4.0, пока не так много блогов, поэтому я надеюсь, что у кого-то есть идея. Предисловие: это приложение веб-форм, начиная с версии 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). Это небольшой 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 вряд ли изменится?

1 Ответ

6 голосов
/ 24 мая 2010

Поскольку по этому вопросу не было никаких действий, оставьте это как ответ, который нужно принять позже, надеясь, что это поможет кому-то еще:

Мое текущее решение для обхода (действительно обходной путь) состоит в том, чтобы выполнить 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();
  }
}

Если за неделю никто не ответит лучшим методом, я приму это, но я надеюсь, есть лучший способ / то, что я пропустил.

...