У нас была такая же проблема на IIS 6 после обновления с ASP.NET 3.5 до ASP.NET 4.0 с ASP.NET MVC. На IIS 7 все работало нормально, но с IIS 6 возникла проблема.
Проблема заключалась в том, что свойство HttpContext.Current.Request.CurrentExecutionFilePath давало разные результаты в IIS 6 и IIS 7:
- URL:
/Controller.mvc/Action/1/2
- IIS 6:
/Controller.mvc/Action/1/2
- IIS 7:
/Controller.mvc
Что привело к URL для диаграмм, таких как:
- IIS 6:
/Controller.mvc/Action/1/ChartImg.axd?i=chart_...
- IIS 7:
/ChartImg.axd?i=chart_...
В ChartHttpHandler есть функция, которая вычисляет путь на основе HttpContext.Current.Request.CurrentExecutionFilePath:
private static string GetHandlerUrl()
{
string str = Path.GetDirectoryName(HttpContext.Current.Request.CurrentExecutionFilePath ?? "").Replace(@"\", "/");
if (!str.EndsWith("/", StringComparison.Ordinal))
{
str = str + "/";
}
return (str + "ChartImg.axd?");
}
Способ работы ASP.NET UrlRewriting, поскольку в путях к ChartImg.axd по-прежнему содержался .mvc, вместо обработчика Chart вызывался обработчик MVC.
Было найдено 3 способа справиться с этим (подробности см. Ниже):
- Добавить явную карту сценариев для ".mvc" в dll ASP.NET 4.0
- Добавить некоторые дополнительные маршруты игнорирования в таблицу маршрутов, чтобы покрыть перестановки
- Переопределите Execute () контроллера и поместите перенаправление обратно в /ChartImg.axd
(1) Оказывается, что если бы мы добавили карту сценариев для .mvc через IIS 6.0 для .mvc, то Request.CurrentExecutionFilePath будет рассчитываться как корневой путь, как мы хотели, а не как более глубокий путь
- Диспетчер IIS 6.0
- Свойства -> Домашний каталог -> Конфигурация
- Вкладка Mappings
- Исполняемый файл: c: \ winnt \ microsoft.net \ framework \ v4.0.30319 \ aspnet_isapi.dll, расширение: .mvc
(2) Мы обнаружили, что добавление некоторых записей таблицы маршрутов будет работать, но нам пришлось учесть все возможные глубины в путях, чтобы ASP.NET MVC игнорировал ChartImg.axd, если он был глубоко внедрен в путь, и не в корне:
RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
RouteTable.Routes.IgnoreRoute("{a}/{resource}.axd/{*pathInfo}");
RouteTable.Routes.IgnoreRoute("{a}/{b}/{resource}.axd/{*pathInfo}");
RouteTable.Routes.IgnoreRoute("{a}/{b}/{c}/{resource}.axd/{*pathInfo}");
RouteTable.Routes.IgnoreRoute("{a}/{b}/{c}/{d}/{resource}.axd/{*pathInfo}");
(3) Переопределив Execute () на всех наших контроллерах, сделав базовый контроллер, от которого наследуются все наши контроллеры, мы могли бы глобально переопределить Execute () для учета этой ситуации и перенаправить в /ChartImg.axd
public partial class MyController: Controller
{
protected override void Execute(RequestContext cc)
{
// the url for chartimg.axd to be in the application root. /Controller.mvc/Action/Param1/ChartImg.axd gets here first,
// but we want it to go to /ChartImg.axd, in which case the IgnoreRoute does work and the chart http handler does it's thing.
if (cc.HttpContext.Request.Url.AbsoluteUri.Contains("ChartImg.axd"))
{
var url = new UriBuilder(cc.HttpContext.Request.Url);
url.Path = "/ChartImg.axd";
cc.HttpContext.Response.Redirect(url.ToString());
return;
}
}
}