суббота, 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: }


среда, 17 декабря 2008 г.

Яндекс.Фотки для Picasa » Picasa 3.1


Вышел релиз Picasa 3 на русском языке. Наш плагин всё также прекрасно работает. :)