MVC 4, MapRoute для /{параметра} URL
Как я могу сопоставить URL в этом формате
http://DOMAIN/{userID}
но не переопределяет формат по умолчанию {controller}/{action}/{id}??
Я попробовал это, но это не работает:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute("Users", "{userID}", new { controller = "Users", action = "GetUser" });
2 ответа
Вставьте этот ДО маршрута по умолчанию
routes.MapRoute("Users", "{userID}", new { controller = "Users", action = "GetUser", userID=UrlParameter.Optional });
Тогда метод GetUser должен иметь параметр с именем userID
для того, чтобы обработчик маршрута мог правильно проложить маршрут.
Обновить:
public class UsernameUrlConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values,
RouteDirection routeDirection)
{
if (values[parameterName] != null)
{
// check if user exists in DB
// if it does, return true
}
return false;
}
}
В ваших маршрутах:
routes.MapRoute("Users",
"{userID}",
new { controller = "Users", action = "GetUser" },
new {IsUser=new UsernameUrlConstraint()}
);
Пожалуйста, обратите внимание, что это будет попадать в БД каждый раз, поэтому может быть хорошей идеей реализовать некоторый кэш памяти (memcached или.net cache), где вы сохраняете имя пользователя и независимо от того, существует оно или нет, таким образом вы не сможете предотвратить только дб хиты от пользователей, которые существуют, но для пользователей, которые не существуют. Например, если кто-то решит обратиться к пользователю X 1000 раз, таким образом вы будете использовать только кэшированную версию вместо 1000 дБ.
Вы действительно не можете на основе информации, которую вы предоставили. Если идентификатор пользователя имеет определенный формат, который вы можете сопоставить с помощью регулярных выражений, вы можете использовать параметр фильтра маршрутов и фильтровать его по ним. Этот маршрут также должен быть указан над маршрутом по умолчанию.
routes.MapRoute(
name: "Users",
url: "{userID}",
defaults: new
{
controller = "Users",
action = "GetUser",
},
new {postId = @"[\w]{3,7}" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Тем не менее, поскольку \ w - это любой символ слова, он все равно будет соответствовать любым именам контроллера, которые содержат от 3 до 7 символов. Если бы вы могли использовать более конкретное регулярное выражение, это можно было бы выполнить.