Asp.net mvc 3 自定义筛选器属性或调用方法-在请求管道中较早,但性能如何?

Asp.net mvc 3 自定义筛选器属性或调用方法-在请求管道中较早,但性能如何?,asp.net-mvc-3,asp.net-mvc-4,action,Asp.net Mvc 3,Asp.net Mvc 4,Action,我有一个家庭控制器,大约有8或9种动作方法 其中大约7种方法需要检查用户是否有特殊设置,或者是否允许他们访问这些方法和相关视图 如果不是,则会重定向回常用的操作方法和视图 public class HomeController : Controller { public ActionResult Index() { UserManager um = new UserManager(); um.Punter p = um.GetPunter(User.Ident

我有一个家庭控制器,大约有8或9种动作方法

其中大约7种方法需要检查用户是否有特殊设置,或者是否允许他们访问这些方法和相关视图

如果不是,则会重定向回常用的操作方法和视图

public class HomeController : Controller
{
    public ActionResult Index() {
       UserManager um = new UserManager();
       um.Punter p = um.GetPunter(User.Identity.Name);
       return View(p);
    }
    public ActionResult PunterList() {
       UserManager um = new UserManager();
       um.Punter p = um.GetPunter(User.Identity.Name);
       if (p.isPunter) {
           return RedirectToAction("Index", "Home");
       } else {
           return View(p);
       }
    }
}
“PunterList”的签入是在其他操作方法中完成的,我正在考虑创建一个FilterAttribute来执行此检查。根据以下规定:

public class NoPunterAttribute : FilterAttribute, IActionFilter {
    public void OnActionExecuting(ActionExecutingContext filterContext) {
       UserManager um = new UserManager();
       um.Punter p = um.GetPunter(User.Identity.Name);
       if (p.isPunter) {
           filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary { { "controller", "Home" }, { "action", "Index" } });
       }
    }
    public void OnActionExecuted(ActionExecutedContext filterContext) { }
}
然后将此属性放在该类型用户无法访问的操作方法上

[NoPunter]
    public ActionResult PunterList() {
       UserManager um = new UserManager();
       um.Punter p = um.GetPunter(User.Identity.Name);
       return View(p);
    }
这会将此代码置于
1
位置,但是如果
User.isPunter=false
,则会调用
UserManager.GetPunter
。对于MVCWeb应用程序的性能或内存节约来说,这可能不是一个好主意

好处是在请求管道中更早地进行检查,但可能在action方法内部调用的方法意味着.GetPunter只调用一次,但会沿着请求管道进一步调用。不确定这一点,在早期与性能/内存问题上存在分歧


任何建议或想法都会很有趣。大概这取决于在
UserManager.GetPunter
中执行的操作。此调用中有一些缓存,但它确实会重新查询缓存。

您可以编写一个自定义授权属性,该属性将注入投注者作为操作的参数:

public class HomeController : Controller
{
    public ActionResult Index() 
    {
        UserManager um = new UserManager();
        um.Punter p = um.GetPunter(User.Identity.Name);
        return View(p);
    }

    [NoPunterAuthorize]
    public ActionResult PunterList(Punter punter) 
    {
       return View(punter);
    }
}
和自定义授权属性:

public class NoPunterAuthorize: AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var authorized = base.AuthorizeCore(httpContext);
        if (!authorized)
        {
            return false;
        }

        var um = new UserManager();
        var p = um.GetPunter(httpContext.User.Identity.Name);
        var routeData = httpContext.Request.RequestContext.RouteData;
        routeData.Values["punter"] = p;
        return !p.IsPunter;
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        filterContext.Result = new RedirectToRouteResult(
            new RouteValueDictionary 
            { 
                { "controller", "Home" }, 
                { "action", "Index" } 
            }
        );
    }
}

一个未经授权的请求应该显示一个页面,上面写着他们是不被允许的。投注者仍然可以登录并使用其中两种操作方法,而管理员可以使用所有方法,所以我不想覆盖HandleUnauthorizedRequest。然而,问题更多的是关于两次加载自定义用户对象的性能,而不是在请求管道中更早地捕获它。我知道AuthorizeAttribute出现在FilterAttribute之前。@magister,在我的示例中,您在哪里看到punter对象被加载了两次?您注意到自定义授权属性如何将结果添加到RouteData中了吗?您是否注意到
PunterList
控制器操作的签名?就Punter和Admin角色而言,您可以简单地调整属性实现,使其从属性的roles属性中读取。啊,好的,不,我忽略了一个事实,即您正在将var p=um.GetPunter放入routeData.Values[“Punter”]=p;你的意思是我可以将我的对象存储在那里,然后在Action方法中使用它,而不必再次调用该方法?是的,这正是我的意思。将Punter传递到AuthorizeAttribute中的RouteValues集合是有效的,但当使用FilterAttribute加载它时,ActionMethod会加载空Punter。羞耻。在authorized属性中处理这个问题可能更好,但是必须等待另一个属性来实现一些安全性,并且在实现Identity Manager之前,使用FilterAttribute是一个临时修复。