Custom IIdentity и передача данных из атрибута в контроллер - PullRequest
0 голосов
/ 07 апреля 2010

Вот мой сценарий:

Я успешно создал собственный IIdentity, который передаю GenericPrincipal. Когда я получаю доступ к этому IIdentity в моем контроллере, мне нужно наложить IIdentity, чтобы использовать пользовательские свойства. Пример:

public ActionResult Test()
{
    MyCustomIdentity identity = (MyCustomIdentity)User.Identity;
    int userID = identity.UserID;
    ...etc...
}

Поскольку мне нужно выполнять это приведение почти для каждого действия, я хотел бы обернуть эту функцию в атрибут ActionFilterAttribute. Я не могу сделать это в конструкторе контроллера, потому что контекст еще не инициализирован. Я подумал бы, чтобы ActionFilterAttribute заполнял частное свойство на контроллере, которое я могу использовать в каждом методе действия. Пример:

public class TestController : Controller
{
    private MyCustomIdentity identity;

    [CastCustomIdentity]
    public ActionResult()
    {
        int userID = identity.UserID;
        ...etc...
    }
}

Вопрос: возможно ли это и как? Есть ли лучшее решение? Я пытался понять, как передать общедоступные свойства, которые заполнены атрибутом, в контроллер, и я не могу его получить.

Ответы [ 2 ]

1 голос
/ 07 апреля 2010

Вы можете использовать связующее для пользовательской модели ...

Я не могу вспомнить, почему я использовал этот метод вместо метода базового контроллера, о котором упоминает @jfar (что также является хорошим вариантом), но он хорошо работает для меня, и мне на самом деле это нравится, потому что мои действия более самоописываются через их параметры.

MyCustomIdentityModelBinder.cs

public class MyCustomIdentityModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.Model != null)
            throw new InvalidOperationException("Cannot update instances");

        //If the user isn't logged in, return null
        if (!controllerContext.HttpContext.User.Identity.IsAuthenticated)
            return null;

        return controllerContext.HttpContext.User as MyCustomIdentity;
    }
}

Внутри вашего события запуска приложения в Global.asax.cs

System.Web.Mvc.ModelBinders.Binders.Add(typeof(MyCustomIdentity), new MyCustomIdentityModelBinder());

Тогда, когда у вас есть тип MyCustomIdentity в качестве параметра действия, он автоматически будет использовать MyCustomIdentityModelBinder.

Например.

public class TestController : Controller
{
    public ActionResult Index(MyCustomIdentity identity)
    {
        int userID = identity.UserID;
        ...etc...
    }
}

HTHS
Charles

1 голос
/ 07 апреля 2010

Все, что вам нужно сделать, - это получить доступ к ActionExecutingContext перегруженного метода OnActionExecuting () и сделать идентичность общедоступной, а не частной, чтобы ваш actionfilter мог получить к ней доступ.

public class CastCustomIdentity : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        ((TestController) filterContext.Controller).Identity = (MyCustomIdentity)filterContext.HttpContext.User;



        base.OnActionExecuting(filterContext);
    }
}

Это может быть еще проще, если использовать пользовательский базовый класс контроллеров, от которого наследуются все ваши контроллеры:

public class MyCustomController
{
    protected MyCustomIdentity Identity { get{ return (MyCustomIdentity)User.Identity; } }
}

и затем:

public class TestController : MyCustomController
{
    public ActionResult()
    {
        int userID = Identity.UserId
        ...etc...
    }
}
...