MVC3 Route сдерживает различие между параметрами - PullRequest
1 голос
/ 16 февраля 2012

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

me.com / один / два / три / четыре / ProductDetail

хотя в некоторых случаях существует пятый узел после четвертого, поэтому ссылка:

me.com / один / два / три / четыре / пять / ProductDetail

как мне, в моем методе действия, отличить этот пятый «сегмент» от детали изделия, если они обе являются строками?

public ActionResult Products (строка одна, строка два, строка три, строка четыре, строка productdetail, строка пять = ноль) { }

Теперь у меня есть маршруты, определенные так:

{контроллер} / {действие} / {один} / {два} / {три} / {четыре} / {productdetail}

{контроллер} / {действие} / {один} / {два} / {три} / {четыре} / {пять} / {ProductDetail}

(где {один} до {пять} - UrlParameter.Optional)

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

это вообще возможно?

Ответы [ 4 ]

1 голос
/ 18 февраля 2012

Самый простой способ исправить это - зарегистрировать маршруты для 5, 4,3 и 2 параметров.Зарегистрируйте их в этом порядке.

 {controller}/{one}/{two}/{three}/{four}/{five}/{productdetail} 
 {controller}/{one}/{two}/{three}/{four}/{productdetail} 
 {controller}/{one}/{two}/{three}/{productdetail} 
 {controller}/{one}/{two}/{productdetail}

Невозможно зарегистрировать маршрут для {controller} / {one} / {productdetail} без создания ограничения маршрута, чтобы убедиться, что {one} не является действием {контроллер}.

Я бы настоятельно рекомендовал, чтобы, если у вас есть списки вариантов 1 - 5, МОЖЕТ БЫТЬ, что вы создаете пользовательское ограничение маршрута, которое будет проверять их, чтобы вы случайно не соответствовали маршруту, который вы не намеревались, новы должны быть в безопасности с указанными выше маршрутами.

Создание IRouteConstraint не сложно.Ниже приведен код, который я ранее использовал для ограничения маршрута, которое позволяло бы вызывать действие из определенного контроллера без необходимости указывать контроллер.Примером может служить контроллер под названием Home с действием для «О программе», это ограничение позволит вам вызывать / about вместо /home/about.

Это относится к тому, что вы хотите сделать, потому что оно показываеткак выполнить некоторую проверку, чтобы определить разницу между {one} и {action}, если вам нужно.

Ограничение маршрута:

public class IsRootActionConstraint : IRouteConstraint
{
    private List<string> _actions;

    public IsRootActionConstraint(): this( "homecontroller")
    {

    }
    public IsRootActionConstraint(string ControllerName)
    {
        Type _type = Assembly
                            .GetCallingAssembly()
                            .GetTypes()
                            .Where(type => type.IsSubclassOf(typeof(Controller)) && type.Name.ToLower() == ControllerName.ToLower())
                            .SingleOrDefault();
        if (_type != null)
        {
            _actions = (from methods in _type.GetMethods() where typeof(ActionResult).IsAssignableFrom(methods.ReturnType) select methods.Name.ToLower()).ToList();
        }
    }

    #region IRouteConstraint Members

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        return _actions.Contains((values["action"] as string).ToLower());
    }

    #endregion
}

И когда вы регистрируете свой маршрут вglobal.asax:

 routes.MapRoute(
            "Home",
            "{action}/{id}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            new { IsRootAction = new CAA.Utility.Constraints.IsRootActionConstraint() }  // Route Constraint
        );


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

В вашем случае проверка того, что {one} не соответствует маршруту в {controller}, не должна быть слишком сложной.Вы можете переместить код отражения в метод Match и использовать имя из значений маршрута для контроллера, чтобы найти действия.

0 голосов
/ 16 февраля 2012

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

  1. Не указывайте от одного до пяти в качестве необязательных параметров.
  2. MapRoot {контроллер} / {действие} / {один} / {два} / {три} / {четыре} / {пять} / {productdetail} должен предшествовать {контроллер} / {действие} / {один} / {два} / {три} / {четыре} / {ProductDetail}
  3. По умолчанию следует maproute. {controller} / {action} / {id} идентификатор необязательный

Сейчас

  1. Запрос на me.com / один / два / три / четыре / пять / productdetail будет соответствовать только первый маршрут.
  2. Запрос на me.com / один / два / три / четыре / productdetail будет соответствовать только второй маршрут.
0 голосов
/ 18 февраля 2012

Если в вашем случае вы не можете установить ограничения маршрута, то ваш лучший вариант - немного изменить маршруты, чтобы ASP.NET MVC мог точно знать, что является аргументом детализации вашего продукта, чтобы избежать путаницы. с необязательным {пять}.

Перед вашей деталью продукта должна стоять какая-то конкретная строка, которая НИКОГДА не может встречаться в диапазоне от одного до пяти значений, например:

{controller}/{action}/{one}/{two}/{three}/{four}/p/{productdetail}

{controller}/{action}/{one}/{two}/{three}/{four}/{five}/p/{productdetail}

Это решит вашу проблему.

0 голосов
/ 16 февраля 2012

Имея два отдельных маршрута, один с пятью элементами, а другой с четырьмя элементами, эти маршруты могут просто идти в одно и то же место.Один проходит через {пять}, другой - нет.

РЕДАКТИРОВАТЬ: Если оба шаблона идентичны, то единственный способ - использовать ограничение для различения различных значений.

...