суббота, 20 декабря 2008 г.

Типизированный путь к действию контроллера в ASP.NET MVC

В ASP.NET MVC для генерации путей (url) для действий (action) контроллеров (controller) можно использовать методы-расширения объекта UrlHelper, такой как Url.Action(string actionName, string controllerName). Но этот метод использует нетипизированные параметры, просто имена action и controller, где легко можно ошибиться. А главный недостаток – нет поддержки рефакторинга, и если вы захотите переименовать действие контроллера – вам придется нудно и без гарантий от ошибки переименовывать их вручную.

Но если внимательно посмотреть – то можно найти замечательный класс – ExpressionHelper и его метод GetRouteValuesFromExpression, который по лямбде-выражению (expression) получит необходимые параметры роутинга. Потом, уже на основе этих параметров можно получить и путь. И конечно, с лямбда-выраженями полная поддержка рефакторинга (спасибо ReSharper за наше счастливое настоящее).

Все бы хорошо – но этот метод не принимает во внимание атрибут ActionName, с помощью которого можно изменить имя действия. Встроенная функция всегда возвращает имя метода, которое в 99% совпадает с именем действия, но не всегда.

Ниже представлен небольшой класс-хелпер, который решает проблему генерации путей к действиям контроллеров по типизированному выражению с учетом аттрибута ActionName.

   1: using System;


   2: using System.Linq;


   3: using System.Linq.Expressions;


   4: using System.Web.Mvc;


   5: using System.Web.Routing;


   6:  


   7: using Microsoft.Web.Mvc.Internal;


   8:  


   9: namespace MediaOnline.Web.Helpers


  10: {


  11:     public static class UrlExtensions


  12:     {


  13:         public static string Action<T>(this UrlHelper url, Expression<Action<T>> action) where T : Controller


  14:         {


  15:             return Action(url, null, action);


  16:         }


  17:  


  18:         public static string Action<T>(this UrlHelper url, string name, Expression<Action<T>> action) where T : Controller


  19:         {


  20:             return RouteTable.Routes.GetVirtualPath(url.RequestContext, name,


  21:                 GetRouteValuesFromExpression(action)).VirtualPath;


  22:         }


  23:  


  24:         public static RouteValueDictionary GetRouteValuesFromExpression<TController>(Expression<Action<TController>> action) where TController : Controller


  25:         {


  26:             var route = ExpressionHelper.GetRouteValuesFromExpression(action);


  27:  


  28:             var body = (MethodCallExpression)action.Body;


  29:             var customName = (body.Method.GetCustomAttributes(typeof (ActionNameAttribute), false))


  30:                 .Cast<ActionNameAttribute>().FirstOrDefault();


  31:  


  32:             if (customName != null)


  33:             {


  34:                 route["Action"] = customName.Name;


  35:             }


  36:             return route;


  37:         }


  38:     }


  39: }


1 комментарий:

Анонимный комментирует...

Строительство жилых и индустриальных многоуровневых объектов влечет за собой привлечение специальной строительной техники, оснащенной для выполнения определенных задач. Проведение строительных работ происходит по стадиям, в связи, с чем, задействовать строительную технику тоже доводится по шагам, в зависимости от поставленных задач.
Но закупка таковой особой техники влечет огромные расходы. Поскольку стоит она дорого, компания "Сапрос" предлагает предложение аренды строительной техники. Наш автопарк укомплектован всем необходимым для строительства автотранспортом. Быстрый заказ спецтехники можно создать через интернет, заполнив заявку онлайн на сайте фирмы. В Самаре мы пользуемя популярностью именно за высококачесвенное и быстрое сопровождение заказчиков, предоставляя такую услугу, как аренда экскаватора в самаре. Наши специалисты при необходимости в полном объеме проконсультируют Вас о более подходящем под запросы автотранспорте, что позволит сэкономить и время и финансы.
Sapros Ru: [url=http://sapros.ru]аренда гидромолота в самаре[/url]