Asp.net mvc 3 自定义筛选器属性或调用方法-在请求管道中较早,但性能如何?
我有一个家庭控制器,大约有8或9种动作方法 其中大约7种方法需要检查用户是否有特殊设置,或者是否允许他们访问这些方法和相关视图 如果不是,则会重定向回常用的操作方法和视图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
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是一个临时修复。