вторник, 21 сентября 2010 г.

ActionFilterAttribute наносит ответный удар

Несколько уточнений:



1) Само собой, эти самые атрибуты никто не мешает слегка параметризовать
public enum UserTypes
{
  Admin = 0,
  Moderator = 1,
  RegisteredUser = 2,
  Guest = 3
}
public sealed class AccessByTypeAttribute: ActionFilterAttribute
{
  private List<UserTypes> _types;

  public AccessByTypeAttribute(params UserTypes[] permissionedTypes)
  {
    _types = new List<UserTypes>();
    _types = permissionedTypes.ToList();
  }

  public override void OnActionExecuting(ActionExecutingContext filterContext)
  {
    base.OnActionExecuting(filterContext);

    //меняем на любой вариант получения прав текущего юзера
    UserTypes currentUserType = UserTypes.Admin;

    if (!_types.Contains(currentUserType))
    {
      throw new AccessViolationException("No way, dude!");
    }
  }
}
public class AdminController: Controller
{
  [AccessByType(UserTypes.Admin, UserTypes.Moderator)]
  public ActionResult SomeSecureAction()
  {
    return View();
  }
}

2) Достаточно часто в некоторый обработчик передаётся Id - юзера, записи в блоге, чего угодно, и сам Action Method начинается с проверки этого id на существование. Это тоже прекрасно параметризуется:

using System.Web.Mvc;
using System.Web.Routing;

public sealed class EntityExistsAttribute: ActionFilterAttribute
{
  private string _typeName;

  public EntityExistsAttribute(string entityType)
  {
    _typeName = entityType;
  }

  public override void OnActionExecuting(ActionExecutingContext filterContext)
  {
    base.OnActionExecuting(filterContext);

    //Тип для генерик-метода. К сожалению, сделать сам атрибут генериком не получится.
    System.Type entity = System.Type.GetType(_typeName);

    //Сам айдишник для проверки
    long targetId = (long) filterContext.ActionParameters["id"];

    bool neededEntityExists = (MyDbRepository.CheckExistance<entity.GetType()>(_paramId)) != null;
    if (!neededEntityExists)
    {
      filterContext.Result =
        new RedirectToRouteResult(new RouteValueDictionary
                       {
                       {"controller", "Home"},
                       {"action", "Error"},
                       {"name", "NotExists"}}
                       );
    }
  }
}
public class UserController:Controller
{
  [EntityExists("User")]
  public ActionResult ShowUserInfo(long id)
  {
    //бла-бла-бла
  }
}

3) В случае необходимости применения нескольких атрибутов для метода порядок их применения можно выставить с помощью параметра Order:
public class UserController:Controller
{
  [AccessByType(UserTypes.Admin, Order=1)]
  [EntityExists("User", Order = 2)]
  public ActionResult ShowUserInfo(long id)
  {
    //бла-бла-бла
  }
}

Комментариев нет:

Отправить комментарий