Я разрабатываю концепции для нового проекта, в котором мне нужно поддерживать многоязычные URL-адреса.В идеале все URL должны быть на родном языке пользователя.Поэтому мы не хотим использовать domain.com / en / contact и domain.com / es / contact , но нам нравится domain.com / contact и domain.com / contactar (для контакта контактная информация - испанский).Внутренне оба должны быть направлены в один и тот же класс ContactController .
Это можно сделать, добавив несколько статических маршрутов в Global.asax.cs для каждого языка, но мы хотели бы сделать это оченьдинамический и хотел бы, чтобы пользователь системы мог изменять перевод URL через систему управления контентом.Поэтому нам нужно какое-то динамическое сопоставление URL-адресов с контроллерами и действиями.
Просматривая исходный код MVC3, я обнаружил, что ProcessRequestInit метод MvcHandler отвечает за определение, какой контроллер создать.Он просто смотрит в RouteData , чтобы получить имя контроллера.Один из способов переопределить маршрутизацию MVC по умолчанию - создать простой маршрут по умолчанию, который использует пользовательский RouteHandler .Этот RouteHandler заставляет MVC использовать мою собственную пользовательскую версию MvcHandler , которая переопределяет метод ProcessRequestInit .Этот переопределенный метод вставляет мой собственный динамически найденный контроллер и действие в RouteData перед обратным вызовом исходного ProcessRequestInit .
Я пробовал это:
Global.asax.cs
routes.Add(
new Route("{*url}", new MultilingualRouteHandler())
{
Defaults = new RouteValueDictionary(new { controller = "Default", action = "Default" })
}
);
MultilingualRouteHandler.cs
public class MultilingualRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new MultilingualMVCHandler(requestContext);
}
}
MultilingualMvcHandler.cs
public class MultilingualMVCHandler : MvcHandler
{
public MultilingualMVCHandler(RequestContext context) : base(context)
{
}
protected override void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
{
if (RequestContext.RouteData.Values.ContainsKey("controller"))
{
RequestContext.RouteData.Values.Remove("controller");
}
if (RequestContext.RouteData.Values.ContainsKey("action"))
{
RequestContext.RouteData.Values.Remove("action");
}
RequestContext.RouteData.Values.Add("controller", "Product");
RequestContext.RouteData.Values.Add("action", "Index");
base.ProcessRequestInit(httpContext, out controller, out factory);
}
}
В этом обработчике я жестко закодировал контроллер и действие для целей тестирования с некоторыми фиксированными значениями, но это не сложно сделать динамическим.Это работает, но единственная проблема заключается в том, что мне пришлось изменить исходный код ASP.NET MVC3, чтобы заставить его работать.Проблема заключается в том, что метод ProcessRequestInit для MvcHandler является закрытым и поэтому не может быть переопределен.Я изменил исходный код и изменил его на защищенный виртуальный, что позволяет мне переопределять его.
Это все замечательно, но, возможно, не лучшее решение.Обременительно, что мне всегда нужно будет распространять свою собственную версию System.Web.Mvc.dll.Было бы намного лучше, если бы он работал с RTM-версией.
Я упускаю какие-либо другие возможности подключения к ASP.NET MVC, которые позволили бы мне динамически определять контроллер и действие для запуска, в зависимости отURL?Еще один способ, о котором я подумал, - это динамически создать RouteCollection на * Application_Start *, но я думаю, что это усложнит его изменение на лету.
Буду признателен за любые советыкрючки, которые я еще не нашел.