Как перенаправить запрос на каталог, который существует на диске, в ASP.NET MVC?
У меня есть приложение ASP.NET MVC 4 (с использованием .NET framework 4.5) с неограниченными URL-адресами. Сайт содержит некоторые статические файлы, но все запросы без расширения должны переходить на маршрутизацию MVC.
Все работает отлично для запросов вроде:
Однако, если я делаю запрос для /fr, я получаю ошибку:
HTTP Error 403.14 - Forbidden,
The Web server is configured to not list the contents of this directory.
Я понимаю, что это потому, что на диске существует каталог /fr, но я все же хочу сопоставить этот запрос с моим MVC-приложением. Это не вариант удаления каталога fr, поскольку он содержит некоторые статические файлы.
Возможно ли это? Я попытался добавить runAllManagedModulesForAllRequests="true"
в элемент modules в system.webServer(я действительно не хочу этого делать, но это все равно не помогло).
Изменить - в случае, если это полезно, вот маршрут:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("cid/{*pathInfo}");
routes.MapRoute(
"Page",
"{*PageId}",
new { controller = "Page", action = "Page" }, // Parameter defaults
new { pageId = @"^(.*)?$" } // Parameter constraints
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Ответы
Ответ 1
Самый простой способ предотвратить доступ к локальным папкам и файлам - установить флаг RouteCollection.RouteExistingFiles
, чтобы ASP.NET обрабатывал URL-адреса, ориентированные на физические файлы. Поэтому измените свой регистр маршрута на:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("cid/{*pathInfo}");
routes.RouteExistingFiles = true;
routes.MapRoute(
"Page",
"{*PageId}",
new { controller = "Page", action = "Page" }, // Parameter defaults
new { pageId = @"^(.*)?$" } // Parameter constraints
);
}
Ваш маршрут "Default"
не требуется, так как "Page"
- это действительно все-таки случай.
Другой метод - изменить конфигурацию IIS, чтобы предоставить ASP.NET MVC более высокий приоритет, чем список каталогов IIS. В IIS7, добравшись до вашего веб-сайта, выберите "Модули из раздела IIS", а затем "Просмотреть упорядоченный список из вкладки" Действия ". Переместите UrlRoutingModule выше DirectoryListingModule.
Как замечание, из ваших комментариев я понимаю, что у вас есть один контроллер с одним действием. Действие будет обслуживать все запросы, кроме статических ресурсов, определенных с помощью IgnoreRoute
. Это не рекомендуется, так как вы теряете все преимущества архитектуры MVC. Кроме того, вы обнаружите, что ваша страница будет быстро расти, чтобы включать все больше и больше случаев. Это именно то, для чего были разработаны маршрутизаторы и контроллеры.
Если вы считаете, что единственный метод catch-all является лучшим решением для вас, вам не нужен MVC, и вам будет лучше использовать веб-API, который имеет гораздо меньшие накладные расходы.
Ответ 2
РЕДАКТИРОВАТЬ: Первоначально я думал, что необходимо удалить DirectoryListingModule, но это не так, мой пользовательский HttpModule переписывает перед этим, поэтому его можно оставить.
Обходной путь, который я использовал для исправления, состоял в том, чтобы добавить некоторую логику в пользовательский HttpModule, который выполнял некоторую обработку запроса. Здесь я обнаруживаю, соответствует ли запрос корню одной из моих локализаций (/fr//es/и т.д.), И если это так, перепишите URL-адрес по умолчанию /fr/index, для которого маршрутизация работает как обычно.
private void BeginRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
var url = context.Request.Url.AbsolutePath;
if (IsLocalizationRoot(url))
{
context.RewritePath(url + GetDefaultPageName());
}
}
Если вы заинтересованы в том, как удалить DirectoryListingModule (как упоминалось выше, это необязательно, но его полезная информация в любом случае):
Как ссылается StaticFileHandler, вам нужно удалить его и удалить и повторно добавить StaticFileHandler (без DirectoryListingModule) в ваш web.config:
<system.webServer>
<handlers>
<remove name="StaticFile"/>
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule"
resourceType="Either" requireAccess="Read" />
</handlers>
<modules>
<remove name="DirectoryListingModule"/>
</modules>
</system.webServer>
Это, вероятно, вызовет ошибку HTTP 500 из-за нарушения блокировки. Вам нужно разблокировать его в IIS applicationHost.config:
откройте командную строку (запустите ее как Администратор) и перейдите в папку C:\Windows\system32\inetsrv
appcmd set module DirectoryListingModule /lockItem:false