ASP.Net MVC3: настроить маршрутизацию для обработки нескольких уникальных идентификаторов?

Я создаю приложение MVC, состоящее из объектов, на которые можно ссылаться двумя разными уникальными идентификаторами, уродливым идентификатором, сгенерированным системой, и более удобным для пользователя 5-символьным «коротким кодом». Например, я хотел бы, чтобы мои конечные пользователи могли вводить следующие URL-адреса в своих браузерах:

http://intranet/PRJ2011004

http://intranet/DEP42

Опять же, оба кода уникальны. У меня правильно настроена маршрутизация для первого URL. Когда пользователь вводит этот URL-адрес, он получает соответствующую страницу, отображающую индексную страницу для объекта: PRJ201104.

Как настроить маршрут для обработки второго сценария? Желательно, чтобы был способ «обмануть» MVC, чтобы он изменил значение, которое он передает контроллеру, из короткого кода в проект.

Я хотел бы перехватить 5-символьный маршрут с коротким кодом, взять предоставленное значение и найти его в моей таблице сущностей, а затем, если я найду соответствующую запись, я хотел бы либо (в порядке предпочтения):

  1. Отображать индексную страницу объектов, сохраняя при этом короткий код в URL-адресе. В этом сценарии я хотел бы «обмануть» контроллер, обрабатывающий маршрут, заставив его думать, что переданный «id» на самом деле является уникальным идентификатором, а не коротким кодом (чтобы не пришлось рефакторить мой существующий код)
  2. Перенаправьте URL-адрес на тот, у которого есть работающий уникальный (уродливый) идентификатор.

И если я не найду подходящую сущность, используя это значение короткого кода, я позволю продолжить свою стандартную обработку маршрута (так, например, мои контроллеры «Ошибка» и «Администратор», которые также состоят из 5 символов, но не короткие коды , будет продолжать работать надлежащим образом).

ТИА


person lamarant    schedule 29.09.2011    source источник


Ответы (1)


Пользовательский маршрут может выполнить эту работу:

public class MyRoute : Route
{
    public MyRoute(string url, object defaults)
        : base(url, new RouteValueDictionary(defaults), new MvcRouteHandler())
    { }

    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        var rd = base.GetRouteData(httpContext);
        var id = rd.Values["id"] as string;
        if (id == null)
        {
            return rd;
        }

        // TODO: if you think that the id provided is a pretty id
        // query the database to fetch the other id

        if (IsPrettyId(id))
        {
            id = FetchCorrespondingId(id);
            rd.Values["id"] = id;
        }
        return rd;
    }
}

а затем зарегистрируйте этот пользовательский маршрут:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.Add(
        "Default",
        new MyRoute(
            "{controller}/{action}/{id}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        )
    );
}

Теперь внутри действия контроллера у вас всегда будет длинный уродливый идентификатор:

public ActionResult Index(string id)
{

}
person Darin Dimitrov    schedule 29.09.2011
comment
Я думаю, это близко. URL-адрес: intranet/ABCDE разрешается правильно. Но теперь URL intranet/Dashboard не работает. Есть ли способ добавить ограничения к пользовательскому маршруту, чтобы он выбирал только совпадения с регулярным выражением? - person lamarant; 29.09.2011
comment
@ Леон, конечно, просто используйте другую перегрузку конструктора Route, которая принимает ограничения. - person Darin Dimitrov; 29.09.2011
comment
Небольшая помощь в том, как реализовать эту перегрузку, пожалуйста? Я не могу понять правильный синтаксис. Так близко. - person lamarant; 29.09.2011
comment
@ Леон, когда вы вызываете конструктор :base, есть другие перегрузки. - person Darin Dimitrov; 29.09.2011
comment
Это помогло мне в пути. Было несколько дополнительных вещей, которые мне нужно было сделать, но этот подход творил чудеса. Еще раз спасибо. - person lamarant; 30.09.2011