ASP.NET маршрутизация MVC через атрибуты метода [закрыто]
на Подкаст StackOverflow #54, Джефф упоминает, что они регистрируют свои маршруты URL в кодовой базе StackOverflow через атрибут над методом, который обрабатывает маршрут. Звучит как хорошая концепция (с оговоркой, что Фил Хаак поднял вопрос о приоритетах маршрута).
может ли кто-нибудь предоставить образец, чтобы это произошло?
кроме того, любые "лучшие практики" для использования этого стиля маршрутизации?
6 ответов:
обновление: это было опубликовано на codeplex. Полный исходный код, а также предварительно скомпилированная сборка доступны для загрузки. У меня еще не было времени разместить документацию на сайте, поэтому этого сообщения SO будет достаточно на данный момент.
обновление: я добавил некоторые новые атрибуты для обработки 1) упорядочение маршрута, 2) ограничения параметров маршрута и 3) Значения параметров маршрута по умолчанию. Текст ниже отражено это обновление.
Я на самом деле сделал что-то подобное для моих проектов MVC (я понятия не имею, как Джефф делает это с stackoverflow). Я определил набор пользовательских атрибутов: UrlRoute, UrlRouteParameterConstraint, UrlRouteParameterDefault. Они могут быть присоединены к методам действий контроллера MVC, чтобы автоматически привязывать к ним маршруты, ограничения и значения по умолчанию.
пример использования:
(обратите внимание, что этот пример несколько надуманный, но он демонстрирует эту особенность)
public class UsersController : Controller { // Simple path. // Note you can have multiple UrlRoute attributes affixed to same method. [UrlRoute(Path = "users")] public ActionResult Index() { return View(); } // Path with parameter plus constraint on parameter. // You can have multiple constraints. [UrlRoute(Path = "users/{userId}")] [UrlRouteParameterConstraint(Name = "userId", Regex = @"\d+")] public ActionResult UserProfile(int userId) { // ...code omitted return View(); } // Path with Order specified, to ensure it is added before the previous // route. Without this, the "users/admin" URL may match the previous // route before this route is even evaluated. [UrlRoute(Path = "users/admin", Order = -10)] public ActionResult AdminProfile() { // ...code omitted return View(); } // Path with multiple parameters and default value for the last // parameter if its not specified. [UrlRoute(Path = "users/{userId}/posts/{dateRange}")] [UrlRouteParameterConstraint(Name = "userId", Regex = @"\d+")] [UrlRouteParameterDefault(Name = "dateRange", Value = "all")] public ActionResult UserPostsByTag(int userId, string dateRange) { // ...code omitted return View(); }
определение атрибута UrlRouteAttribute:
/// <summary> /// Assigns a URL route to an MVC Controller class method. /// </summary> [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class UrlRouteAttribute : Attribute { /// <summary> /// Optional name of the route. If not specified, the route name will /// be set to [controller name].[action name]. /// </summary> public string Name { get; set; } /// <summary> /// Path of the URL route. This is relative to the root of the web site. /// Do not append a "/" prefix. Specify empty string for the root page. /// </summary> public string Path { get; set; } /// <summary> /// Optional order in which to add the route (default is 0). Routes /// with lower order values will be added before those with higher. /// Routes that have the same order value will be added in undefined /// order with respect to each other. /// </summary> public int Order { get; set; } }
определение атрибута UrlRouteParameterConstraintAttribute:
/// <summary> /// Assigns a constraint to a route parameter in a UrlRouteAttribute. /// </summary> [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class UrlRouteParameterConstraintAttribute : Attribute { /// <summary> /// Name of the route parameter on which to apply the constraint. /// </summary> public string Name { get; set; } /// <summary> /// Regular expression constraint to test on the route parameter value /// in the URL. /// </summary> public string Regex { get; set; } }
определение UrlRouteParameterDefaultAttribute:
/// <summary> /// Assigns a default value to a route parameter in a UrlRouteAttribute /// if not specified in the URL. /// </summary> [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class UrlRouteParameterDefaultAttribute : Attribute { /// <summary> /// Name of the route parameter for which to supply the default value. /// </summary> public string Name { get; set; } /// <summary> /// Default value to set on the route parameter if not specified in the URL. /// </summary> public object Value { get; set; } }
изменения в глобальном.асакс.cs:
замените вызовы MapRoute, с помощью одного вызова маршруту служебная программа.RegisterUrlRoutesFromAttributes функция:
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); RouteUtility.RegisterUrlRoutesFromAttributes(routes); }
определение Маршрутности.RegisterUrlRoutesFromAttributes:
полный источник на codeplex. Пожалуйста, зайдите на сайт если у вас есть какие-либо отзывы или отчеты об ошибках.
вы также можете попробовать AttributeRouting, который доступен github или через nuget.
это бесстыдная вилка, так как я автор проекта. Но черт возьми, если я не очень счастлив, используя его. Возможно, и ты тоже. В репозитории github есть много документации и примеров кода wiki.
с этой библиотекой, вы можете сделать много:
- украсьте свои действия с GET, POST, PUT и Удалите атрибуты.
- сопоставьте несколько маршрутов с одним действием, упорядочив их с помощью свойства Order.
- укажите маршрут по умолчанию и ограничения с помощью атрибутов.
- укажите необязательные параметры с помощью простого ? знак перед именем параметра.
- Укажите имя маршрута для поддержки именованных маршрутов.
- определите области MVC на контроллере или базовом контроллере.
- сгруппируйте или вложите свои маршруты вместе, используя префиксы маршрутов применяется к контроллеру или базовому контроллеру.
- поддержка устаревших ссылках.
- установите приоритет маршрутов среди маршрутов, определенных для действия, внутри контроллера, а также между контроллерами и базовыми контроллерами.
- автоматически создавать исходящие URL-адреса в нижнем регистре.
- определите свои собственные пользовательские соглашения о маршруте и примените их на контроллере для создания маршрутов для действий внутри контроллера без стандартных атрибутов (подумайте RESTful стиль.)
- отладка маршрутов с помощью прилагаемого HttpHandler.
Я уверен, что есть некоторые другие вещи я забыл. Проверить его. Это безболезненно установить через nuget.
примечание: с 4/16/12 AttributeRouting также поддерживает новую инфраструктуру Web API. на всякий случай вы ищете что-то, что может справиться с этим. спасибо subkamran!
1. Скачать RiaLibrary.Сеть.dll и ссылаться на него в вашем ASP.NET проект сайта MVC
2. Методы контроллера Decoreate с атрибутами [Url]:
public SiteController : Controller { [Url("")] public ActionResult Home() { return View(); } [Url("about")] public ActionResult AboutUs() { return View(); } [Url("store/{?category}")] public ActionResult Products(string category = null) { return View(); } }
кстати, '?'войдите' {?параметр category} ' означает, что он необязателен. Вам не нужно будет указывать это явно в Route defaults, что равно этому:
routes.MapRoute("Store", "store/{category}", new { controller = "Store", action = "Home", category = UrlParameter.Optional });
3. Обновление Глобальное.асакс.цезий файл
public class MvcApplication : System.Web.HttpApplication { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoutes(); // This does the trick } protected void Application_Start() { RegisterRoutes(RouteTable.Routes); } }
Как установить значения по умолчанию и ограничения? Пример:
public SiteController : Controller { [Url("admin/articles/edit/{id}", Constraints = @"id=\d+")] public ActionResult ArticlesEdit(int id) { return View(); } [Url("articles/{category}/{date}_{title}", Constraints = "date=(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])")] public ActionResult Article(string category, DateTime date, string title) { return View(); } }
Как установить заказ? Пример:
[Url("forums/{?category}", Order = 2)] public ActionResult Threads(string category) { return View(); } [Url("forums/new", Order = 1)] public ActionResult NewThread() { return View(); }
этот пост предназначен только для расширения ответа DSO.
при преобразовании моих маршрутов в атрибуты мне нужно было обработать атрибут ActionName. Так что в GetRouteParamsFromAttribute:
ActionNameAttribute anAttr = methodInfo.GetCustomAttributes(typeof(ActionNameAttribute), false) .Cast<ActionNameAttribute>() .SingleOrDefault(); // Add to list of routes. routeParams.Add(new MapRouteParams() { RouteName = routeAttrib.Name, Path = routeAttrib.Path, ControllerName = controllerName, ActionName = (anAttr != null ? anAttr.Name : methodInfo.Name), Order = routeAttrib.Order, Constraints = GetConstraints(methodInfo), Defaults = GetDefaults(methodInfo), });
также я нашел название маршрута не подходит. Имя строится динамически с controllerName.RouteName. Но мои имена маршрутов-это строки const в классе контроллера, и я использую эти const для вызова Url.RouteUrl. Вот почему мне действительно нужно имя маршрута в атрибуте чтобы быть фактическим названием маршрута.
еще одна вещь, которую я сделаю, это преобразовать атрибуты по умолчанию и ограничения в AttributeTargets.Параметр, чтобы я мог вставить их в params.
Я объединил эти два подхода в Франкенштейновскую версию для всех, кто этого хочет. (Мне понравилась необязательная нотация param, но также подумал, что они должны быть отдельными атрибутами от default/constraints, а не все смешанные в один).
http://github.com/djMax/AlienForce/tree/master/Utilities/Web/
мне нужно, чтобы получить ITCloud маршрутизации, работающие в asp.net в MVC 2 с помощью AsyncController -- для этого просто измените маршруту служебная программа.класс cs в исходнике и перекомпилировать. Вы должны удалить "завершено" из имени действия в строке 98
// Add to list of routes. routeParams.Add(new MapRouteParams() { RouteName = String.IsNullOrEmpty(routeAttrib.Name) ? null : routeAttrib.Name, Path = routeAttrib.Path, ControllerName = controllerName, ActionName = methodInfo.Name.Replace("Completed", ""), Order = routeAttrib.Order, Constraints = GetConstraints(methodInfo), Defaults = GetDefaults(methodInfo), ControllerNamespace = controllerClass.Namespace, });
затем, в AsyncController, украсьте XXXXCompleted ActionResult знакомым
UrlRoute
иUrlRouteParameterDefault
атрибуты:[UrlRoute(Path = "ActionName/{title}")] [UrlRouteParameterDefault(Name = "title", Value = "latest-post")] public ActionResult ActionNameCompleted(string title) { ... }
надеюсь, что это поможет кому-то с той же проблемой.
Comments