Asp.net mvc 自定义IIIdentity并将数据从属性传递到控制器

Asp.net mvc 自定义IIIdentity并将数据从属性传递到控制器,asp.net-mvc,asp.net-mvc-2,custom-attributes,iidentity,Asp.net Mvc,Asp.net Mvc 2,Custom Attributes,Iidentity,以下是我的设想: 我已成功创建了一个自定义身份,并将其传递给GenericPrincipal。当我在控制器中访问该IIdentity时,我必须强制转换IIdentity以使用自定义属性。例如: public ActionResult Test() { MyCustomIdentity identity = (MyCustomIdentity)User.Identity; int userID = identity.UserID; ...etc... } public c

以下是我的设想:

我已成功创建了一个自定义身份,并将其传递给GenericPrincipal。当我在控制器中访问该IIdentity时,我必须强制转换IIdentity以使用自定义属性。例如:

public ActionResult Test()
{
    MyCustomIdentity identity = (MyCustomIdentity)User.Identity;
    int userID = identity.UserID;
    ...etc...
}
public class TestController : Controller
{
    private MyCustomIdentity identity;

    [CastCustomIdentity]
    public ActionResult()
    {
        int userID = identity.UserID;
        ...etc...
    }
}
因为我几乎需要为每一个动作都进行此转换,所以我想将此功能包装在ActionFilterAttribute中。我无法在控制器的构造函数中执行此操作,因为上下文尚未初始化。我的想法是让ActionFilterAttribute填充控制器上的私有属性,我可以在每个action方法中使用该属性。例如:

public ActionResult Test()
{
    MyCustomIdentity identity = (MyCustomIdentity)User.Identity;
    int userID = identity.UserID;
    ...etc...
}
public class TestController : Controller
{
    private MyCustomIdentity identity;

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

问题:这可能吗?如何可能?有更好的解决办法吗?我绞尽脑汁想知道如何将填充在属性中的公共属性传递给控制器,但我无法获得它。

您所要做的就是访问重载OnActionExecuting()方法的ActionExecutingContext,并将标识设为公共而不是私有,以便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...
    }
}

您可以使用自定义模型活页夹

我不记得为什么我在@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

例如

HTHs,
查尔斯