ASP.NET MVC: маршрут с дополнительным параметром, но если он указан, должен соответствовать \ d +

Я пытаюсь написать маршрут с нулевым int в нем. Должно быть возможно перейти на оба параметра /profile/ но также и /profile/\d+ .

 routes.MapRoute("ProfileDetails", "profile/{userId}", new {controller = "Profile", action = "Details", userId = UrlParameter.Optional}, new {userId = @"\d+"}); 

Как вы можете видеть, я говорю, что userId является необязательным, но также должен соответствовать регулярному выражению \d+ . Это не работает, и я понимаю, почему.

Но как мне построить маршрут, который соответствует только /profile/ но также /profile/ за которым следует число?

Самый простой способ – просто добавить еще один маршрут без параметра userId , поэтому у вас есть резерв:

 routes.MapRoute("ProfileDetails", "profile/{userId}", new {controller = "Profile", action = "Details", userId = UrlParameter.Optional}, new {userId = @"\d+"}); routes.MapRoute("Profile", "profile", new {controller = "Profile", action = "Details"}); 

Насколько я знаю, единственный способ, которым вы можете это сделать, – это создать собственное ограничение. Таким образом, ваш маршрут станет следующим:

 routes.MapRoute("ProfileDetails", "profile/{userId}", new {controller = "Profile", action = "Details", userId = UrlParameter.Optional}, new {userId = new NullableConstraint()); 

И код пользовательского ограничения будет выглядеть так:

 using System; using System.Web; using System.Web.Routing; using System.Web.Mvc; namespace YourNamespace { public class NullableConstraint : IRouteConstraint { public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { if (routeDirection == RouteDirection.IncomingRequest && parameterName == "userId") { // If the userId param is empty (weird way of checking, I know) if (values["userId"] == UrlParameter.Optional) return true; // If the userId param is an int int id; if (Int32.TryParse(values["userId"].ToString(), out id)) return true; } return false; } } } 

Я не знаю, что NullableConstraint – лучшее имя здесь, но это зависит от вас!

Возможно, что-то изменилось, поскольку на этот вопрос был дан ответ, но я смог изменить это:

 routes.MapPageRoute( null, "projects/{operation}/{id}", "~/Projects/ProjectWizard.aspx", true, new RouteValueDictionary(new { operation = "new", id = UrlParameter.Optional }), new RouteValueDictionary(new { id = new NullableExpressionConstraint(@"\d+") }) ); 

С этим:

 routes.MapPageRoute( null, "projects/{operation}/{id}", "~/Projects/ProjectWizard.aspx", true, new RouteValueDictionary(new { operation = "new", id = UrlParameter.Optional }), new RouteValueDictionary(new { id = @"\d*" }) ); 

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

ASP.NET MVC 3 решил эту проблему, и, как Алекс Форд вывел , вы можете использовать \d* вместо написания пользовательского ограничения. Если ваш шаблон более сложный, например, поиск года с помощью \d{4} , просто убедитесь, что ваш шаблон соответствует тому, что вам нужно, и пустой строке, например (\d{4})? или \d{4}|^$ . Все, что делает тебя счастливым.

Если вы все еще используете ASP.NET MVC 2 и хотите использовать пример Mark Bell или пример NYCChris , помните, что маршрут будет соответствовать, если параметр URL содержит совпадение с вашим шаблоном. Это означает, что шаблон \d+ будет соответствовать таким параметрам, как abc123def . Чтобы этого избежать, оберните шаблон с помощью ^( и )$ либо при определении маршрутов, либо в пользовательском ограничении. (Если вы посмотрите на System.Web.Routing.Route.ProcessConstraint в Reflector , вы увидите, что он делает это для вас при использовании встроенного ограничения, а также устанавливает параметры CultureInvariant, Compiled и IgnoreCase .)

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

 public class OptionalConstraint : IRouteConstraint { public OptionalConstraint(Regex regex) { this.Regex = regex; } public OptionalConstraint(string pattern) : this(new Regex("^(" + pattern + ")$", RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase)) { } public Regex Regex { get; set; } public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { if(routeDirection == RouteDirection.IncomingRequest) { object value = values[parameterName]; if(value == UrlParameter.Optional) return true; if(this.Regex.IsMatch(value.ToString())) return true; } return false; } } 

И вот пример маршрута:

 routes.MapRoute("PostsByDate", "{year}/{month}", new { controller = "Posts", action = "ByDate", month = UrlParameter.Optional }, new { year = @"\d{4}", month = new OptionalConstraint(@"\d\d") }); 

должно ли ваше регулярное выражение быть \ d *?

Спасибо Марку Белу за этот ответ, это помогло мне совсем немного.

Мне интересно, почему вы жестко закодировали чек на «userId» в ограничении? Я немного переписал ваш class, как пользователь, parameterName parameterName, и, похоже, он работает нормально.

Я что-то пропустил, делая это так?

 public class OptionalRegExConstraint : IRouteConstraint { private readonly Regex _regEx; public OptionalRegExConstraint(string matchExpression=null) { if (!string.IsNullOrEmpty(matchExpression)) _regEx = new Regex(matchExpression); } public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { if (routeDirection == RouteDirection.IncomingRequest) { if (values[parameterName] == UrlParameter.Optional) return true; return _regEx != null && _regEx.Match(values[parameterName].ToString()).Success; } return false; } } 

Мне нужно было проверить некоторые вещи с помощью не только RegEx, но и по-прежнему возникала проблема, подобная этому. Мой подход заключался в том, чтобы написать оболочку ограничений для любых пользовательских ограничений маршрута, которые у меня уже есть:

 public class OptionalRouteConstraint : IRouteConstraint { public IRouteConstraint Constraint { get; set; } public bool Match ( HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection ) { var value = values[parameterName]; if (value != UrlParameter.Optional) { return Constraint.Match(httpContext, route, parameterName, values, routeDirection); } else { return true; } } } 

А затем, в constraints по маршруту в RouteConfig.cs , он будет выглядеть так:

 defaults: new { //... other params userid = UrlParameter.Optional } constraints: new { //... other constraints userid = new OptionalRouteConstraint { Constraint = new UserIdConstraint() } } 
  • ASP.NET MVC Html.DropDownList, заполненный вызовом Ajax для controllerа?
  • Как реализовать правильную обработку ошибок HTTP в .NET MVC 2?
  • Как добиться динамического controllerа и метода действий в ASP.NET MVC?
  • Когда `PostAuthenticateRequest` получает выполнение?
  • Добавление подкаталога в папку «View / Shared» в ASP.Net MVC и вызов представления
  • Как установить маршрут по умолчанию (в зону) в MVC
  • ASP.NET MVC - Поймать весь маршрут и маршрут по умолчанию
  • В чем разница (если есть) между Html.Partial (view, model) и Html.RenderPartial (view, model) в MVC2?
  • Отображение разницы между двумя значениями datetime в часах
  • ASP.NET MVC - получение имени текущей области в представлении или controllerе
  • Как указать имя области в ссылке действия?
  • Interesting Posts

    Запросить tags EC2 изнутри экземпляра

    Создать ярлык на рабочем столе

    Функция замены строки xslt 1.0

    Как генерировать и автоматически увеличивать Id с Entity Framework

    Не удается подключиться к общему сетевому диску.

    jQuery или CSS-селектор, чтобы выбрать все идентификаторы, начинающиеся с некоторой строки

    Каким персонажем это (𝒲)

    Автоматизировать диалог сохранения для IE9 (vba)

    ALT + левый клик для перетаскивания и ALT + правая Нажмите, чтобы изменить размер окон в Windows?

    Что означает префикс точки в домене cookie?

    Можно ли создать экземпляр вложенного classа с помощью Java Reflection?

    использование Tor в качестве прокси

    Как я могу установить Linux на жесткий диск другого компьютера (тот, который не загружается с компакт-диска)

    Java – загрузка DLL по относительному пути и скрыть их внутри банки

    Почему Runtime.exec (String) работает для некоторых, но не для всех команд?

    Давайте будем гением компьютера.