Как добавить параметр маршрута до того, как MVC выберет маршрут - PullRequest
7 голосов
/ 08 февраля 2012

Я пытаюсь добавить поддержку различных языков в существующее приложение MVC 3. Пока мои ссылки были

oldUrl -> myapp.com/Item/Details/5/some-title

И есть ссылки на сайт из разных мест в сети. Но теперь я хочу изменить URL, чтобы включить язык:

newUrl -> kmyapp.com/en/Item/Details/5/some-title

Однако я хочу, чтобы ссылки oldUrl были действительными. И вопрос в том, как мне это сделать ... Самый простой способ - добавить другой маршрут, но у меня их уже слишком много, и он становится уродливым, и когда я создаю URL со страницы, которая не У меня есть язык, у ссылок тоже нет языка, поэтому я должен сделать что-то еще.

Другим способом было бы переопределить то, что стоит перед тем, как MVC пытается сопоставить запрос с конкретным маршрутом, но уже проанализировал URL-адрес запроса и заполнил словарь routeValues. Поэтому я могу просто проверить язык и, если он не включен в параметры маршрута, я могу добавить его самостоятельно и вызвать реализацию родительского класса для продолжения. Это возможно? Что я должен посмотреть - UrlRoutingModule , MvcHttpHandler или что-то еще? Что я могу переопределить и как указать MVC использовать мою версию?

Любые другие идеи также будут оценены!

Ответы [ 2 ]

11 голосов
/ 09 февраля 2012

Есть, конечно, много решений.Я собираюсь показать вам два:

  • тот, который вы контролируете в своем приложении
  • , который вы контролируете вне своего приложения (в IIS)

Решение первое - маршрутизация Asp.net MVC

Обеспечение маршрутизации, охватывающей старую и новую маршрутизацию:

routes.MapRoute(
    "New",
    "{lang}/{controller}/{action}/{id}",
    new { lang = "en", controller = "Home", action = "Index", id = UrlParameter.Optional },
    new { lang = "en|de|it|es|fr" }
);
routes.MapRoute(
    "NewEx",
    "{lang}/{controller}/{action}/{id}/{title}",
    new { lang = "en", controller = "Home", action = "Index", id = UrlParameter.Optional, title = UrlParameter.Optional },
    new { lang = "en|de|it|es|fr" }
);

routes.MapRoute(
    "Old",
    "{controller}/{action}/{id}",
    new { lang = "en", controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
    "OldEx",
    "{controller}/{action}/{id}/{title}",
    new { lang = "en", controller = "Home", action = "Index", id = UrlParameter.Optional, title = UrlParameter.Optional }
);

Как видите, У меня естьтакже предоставляется язык по умолчанию для старых маршрутов , так как он отсутствует в URL.Хотите вы того или нет, это ваше собственное решение, но этот вид маршрутизации позволяет не дублировать действия вашего контроллера.В любом случае вам придется определить язык по умолчанию, который может быть предоставлен таким образом.

Возникает более серьезный вопрос, хотите ли вы по-прежнему поддерживать старые URL-адреса или предпочитаете их перенаправлять (HTTP Redirect Permanent Status 301).

Постоянное перенаправление

Измените старые маршруты на:

routes.MapRoute(
    "Old",
    "{controllerOld}/{actionOld}/{idOld}",
    new { controller = "Redirect", action = "Permanent", id = UrlParameter.Optional }
);
routes.MapRoute(
    "OldEx",
    "{controllerOld}/{actionOld}/{idOld}/{titleOld}",
    new { controller = "Redirect", action = "Permanent", id = UrlParameter.Optional, title = UrlParameter.Optional }
);

Затем напишите класс контроллера, который выполняет перенаправление:

public class RedirectController : Controller
{
    public ActionResult Permanent(string controllerOld, string actionOld, string idOld, string titleOld)
    {
        return RedirectToRoutePermanent(new {
            lang = "en",
            controller = controllerOld,
            action = actionOld,
            id = idOld,
            title = titleOld
        });
    }
}

Решение второе- Модуль перезаписи URL IIS

Это решение основано на модуле перезаписи URL IIS, в котором вы можете переписывать любые запросы без выбора языка по умолчанию.

Я не буду писать, как перезапись URLработает здесь, потому что есть много веб-ресурсов с подробной информацией об этом.

4 голосов
/ 09 февраля 2012

Другим способом было бы переопределить то, что стоит перед тем, как MVC пытается сопоставить запрос с конкретным маршрутом, но уже проанализировал URL-адрес запроса и заполнил словарь routeValues. Поэтому я могу просто проверить язык и, если он не включен в параметры маршрута, я могу добавить его самостоятельно и вызвать реализацию родительского класса для продолжения. Это возможно?

Да, это возможно.

Вы можете переопределить GetRouteData в RouteBase , в котором будут указаны детали URL.

public override RouteData GetRouteData(HttpContextBase httpContext)
{
        string url = httpContext.Request.AppRelativeCurrentExecutionFilePath;
}

и в global.aspx добавьте код ниже.

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.Add(new MyUrlRoute()); // Add before your default Routes

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
    );

Для более подробной реализации - см. blog URL-манипуляция реализующее-routebase.html

...