ASP.NET MVC 2 RC2 Routing - Как очистить низкоуровневые значения при использовании ActionLink для обращения к более высокому уровню? - PullRequest
2 голосов
/ 23 марта 2010

[ПРИМЕЧАНИЕ: я использую ASP.NET MVC2 RC2.]

У меня есть такие URL:

/ клиентов / 123 / заказы / 456 / пункты / индекс

/ клиентов / 123 / заказы / 456 / пункты / 789 / редактировать

В моей таблице маршрутизации сначала перечислены наиболее специфичные маршруты, поэтому я получил:

// customers/123/orders/456/items/789/edit
routes.MapRoute(
    "item", // Route name
    "customers/{customerId}/orders/{orderId}/items/{itemId}/{action}", // URL with parameters
    new { controller = "Items", action = "Details" }, // Parameter defaults
    new { customerId = @"\d+", orderId = @"\d+", itemId = @"\d+" } // Constraints
);

// customers/123/orders/456/items/index
routes.MapRoute(
    "items", // Route name
    "customers/{customerId}/orders/{orderId}/items/{action}", // URL with parameters
    new { controller = "Items", action = "Index" }, // Parameter defaults
    new { customerId = @"\d+", orderId = @"\d+" } // Constraints
);

Когда я попадаю на страницу «Изменить», я хочу получить ссылку обратно на страницу «Индекс». Итак, я использую:

ActionLink("Back to Index", "index")

Однако, поскольку есть идентификатор элемента окружения, это приводит к URL:

/ клиентов / 123 / заказы / 456 / пункты / 789 / индекс

... тогда как я хочу, чтобы он "забыл" идентификатор элемента и просто использовал:

/ клиентов / 123 / заказы / 456 / пункты / индекс

Я пытался переопределить идентификатор элемента следующим образом:

ActionLink("Back to Index", "index", new { itemId=string.empty })

... но это не совсем работает. Что это дает мне:

/ клиентов / 123/456 / заказы / пункты? Itemid = 789

Как мне убедить ActionLink "забыть" идентификатор предмета?


РЕДАКТИРОВАТЬ : фиксированный вопрос - я имел в виду «заказ», где я имел в виду «элемент».

РЕДАКТИРОВАТЬ : добавлено подробное описание того, почему itemId = string.empty не работает.

Ответы [ 4 ]

2 голосов
/ 24 марта 2010

В вашем ограничении вы можете удалить любые значения routeValues, которые вам не нужны.

values.Remove("itemId");

Затем создайте класс, который наследуется от IRouteConstraint.

Затем в методе Match очистите значение вашего маршрута ивернуть true (указывает на совпадение маршрутов).

public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{

    values.Remove("itemId");    
    return true;
}

, затем в Global.asax.cs изменить

new { customerId = @"\d+", orderId = @"\d+" }

на

new { customerId = @"\d+", orderId = @"\d+", custom=new MyNewConstraint() }
1 голос
/ 17 марта 2011

Решение в корне проблемы

Похоже, что оптимальное решение (которое не пахнет как обходной путь) - это то, которое решает проблему там, где у него есть корни, а именно в маршрутизации.

Я написал собственный класс Route с именем RouteWithExclusions, который может определять имена значений маршрутов, которые следует исключать / удалять при создании URL-адресов.

Вся проблема подробно описана и объяснена в моем блоге , и весь код предоставлен там же. Проверьте это, это может помочь вам решить эту проблему маршрутизации без использования ограничений, но с маршрутом, который делает то, что требуется.

1 голос
/ 24 марта 2010

ОК, я думаю, у меня есть это, чтобы делать то, что я хочу, используя RouteLink вместо ActionLink:

RouteLink("Back to Index", "items", new { action="index" })

... где 2-й параметр - это название маршрута, который я хочуявно вызвать.


РЕДАКТИРОВАТЬ : я действительно не хотел просматривать все свои десятки ActionLinks и помещать их в эту форму, поэтому вместо этого я изменилправило "item" для включения ограничения на параметр {action}, чтобы "index" не соответствовал этому маршруту.Таким образом, он соответствует маршруту "items" - у которого нет параметра itemId.Это кажется более простым способом сделать это, так как большая часть моего кода остается неизменной.

1 голос
/ 23 марта 2010

Я удалил свой предыдущий ответ, не заметил, что это был один и тот же контроллер. Попробуйте установить itemId = string.empty. Это приведет к сбою первого маршрута, так как для него требуется цифра в этой позиции.

ActionLink("Back to Index", "index", new { itemId=string.empty })

При желании вы можете вручную создать ссылку с названием маршрута "пункт"

<%= Url.RouteUrl("item", new { controller="Items", action="Index", orderId=3 ... }) %>
...