Маршрутизация устаревших запросов с и без строки запроса - PullRequest
6 голосов
/ 06 февраля 2012

(Перед началом: я знаю это и это . Я хотел бы найти более краткое решение - если возможно - для чуть более конкретной проблемы)

Я переписываю старое приложение Webforms в MVC.Как обычно, постоянные ссылки не должны быть нарушены.

Я использую стандартные {controller}/{action}/{id} маршруты.Устаревшие пути обычно SomePage.aspx?ID=xxx, и у меня есть один конкретный случай, когда Foo.aspx - это список Bar (новый URL: / Bar или / Bar / Index ) иFoo.aspx?ID=xxx - это деталь Bar (новый URL: / Bar / View / xxx )

Один из возможных способов - добавить следующее перед значением по умолчанию MapRoute:

routes.MapRoute("Bar View", "Foo.aspx",
                new { controller = "Bar", action = "View" });

И затем определение соответствующего действия в BarController:

public ActionResult View(int? id)
{
    if (id == null)
        return RedirectToAction("Index");
    return View();
}

С этим связаны две проблемы:

  • Теперь, если я создаю ActionLink, он используетустаревший формат
  • Я бы хотел обработать это на маршрутах;делать идентификатор обнуляемым и перенаправлять в контроллере просто неправильно

Я в порядке с отображением устаревших URL-адресов вручную (мне не нужно универсальное решение, и есть только около 8 страниц)

Это новый проект, поэтому я ни к чему не привязан.

Ответы [ 2 ]

3 голосов
/ 07 февраля 2012

Я смог решить эту проблему на основе Опасной 'идеи плюс ограничение на основе этого ответа .

Моя новая таблица маршрутов:

routes.MapRoute("Bar", "Bar/{action}/{id}",
                new
                {
                    controller = "Bar",
                    action = "Index",
                    id = UrlParameter.Optional
                });
routes.MapRoute("Bar View", "Foo.aspx",
                new {controller = "Bar", action = "View"},
                new {id = new QueryStringConstraint()});
routes.MapRoute("Bar Index", "Foo.aspx",
                new { controller = "Bar", action = "Index" });
routes.MapRoute("Default", /*...*/);

И QueryStringConstraint не может быть проще:

public class QueryStringConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route,
                      string parameterName, RouteValueDictionary values,
                      RouteDirection routeDirection)
    {
        return httpContext.Request.QueryString.AllKeys
            .Contains(parameterName, StringComparer.InvariantCultureIgnoreCase);
    }
}
2 голосов
/ 07 февраля 2012

Полагаю, если вы укажете следующие маршруты:

routes.MapRoute(
    null,
    "Bar/{action}/{id}",
     new { controller = "Bar", action = "View", id = UrlParameter.Optional },
     new { action = "Index|Next" } //contrain route from being used by other action (if required)
);

routes.MapRoute(
    null,
    "Foo.aspx/{id}",
    new { controller = "Bar", action = "View", id = UrlParameter.Optional }
);

//specify other routes here for the other legacy routes you have.

Тогда это должно решить вашу первую проблему. Если пользователь указывает Foo.aspx в URL-адресе, он будет перенаправлен на действие «Просмотр».

Если ссылка действия:

@Html.ActionLink("Click me", "Index", "Bar")

указано, тогда будет использоваться первый маршрут (в зависимости от порядка).

Однако я не мог понять, как указать, если Foo.aspx?id=..., то перейти к одному маршруту, если указан Foo.aspx, а затем перейти к другому маршруту. Поэтому я бы проверил, является ли id пустым в действии. Однако, если вы это выясните, я бы очень хотел знать.

Надеюсь, это поможет.

...