2011-05-13 80 views
4

这可能是天上的馅饼,但我想知道是否可以使用自定义控制器属性完成以下操作。.NET MVC 3自定义控制器属性

对于我的大多数控制器,我将传递一个名为“r”的URL参数给控制器中的每个动作。 “r”与我的数据库中的比赛表中的种族id相关联。

我想要发生的是,任何时候调用控制器操作时,它都会自动检查“r”是否存在,查询数据库以确保“r”属于登录用户并设置称为ViewBag.RaceId等于“r”的viewbag变量。

如果任何这些条件不符合,它会将它们重定向回登录页面。

我试图让我的代码尽可能干。

任何指导将不胜感激。

回答

6

你可以写一个自定义的Authorize属性:

public class MyAuthorizeAttribute : AuthorizeAttribute 
{ 
    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     var isAuthorized = base.AuthorizeCore(httpContext); 
     if (isAuthorized) 
     { 
      var request = httpContext.Request; 
      // Fetch "r" from the route data or request 
      var r = request.RequestContext.RouteData.Values["r"] 
       ?? request["r"]; 
      var currentUser = httpContext.User.Identity.Name; 
      if (!CheckIfRBelongsToTheCurrentLoggedInUser(currentUser, r)) 
      { 
       return false; 
      } 
     } 
     return isAuthorized; 
    } 
} 

现在,所有剩下的就是这个自定义属性来装饰你的控制器/动作:

[MyAuthorize] 
public ActionResult Foo() 
{ 
    //... 
} 

如果你希望把东西放到ViewBag可以暂时将其存储在AuthorizeCore方法中的httpContext.Items以防万一成功,然后重写OnAuthorization方法,并检查c中是否存在此项ontext。如果存在,则可以将其存储在filterContext.Controller.ViewBag中。

+0

Pure Awesome。关于ViewBag的一个问题。在我的自定义属性中,我添加了:httpContext.Items.Add(“RaceId”,r.ToString());并在我的重写OnAuthorization我添加了filterContext.Controller.ViewBag.RaceId = filterContext.HttpContext.Items [“RaceId”];那是对的吗?新的重写OnAuthorization。 – Mike 2011-05-13 18:09:40

+0

没关系。我有ilterContext.Controller.ViewBag.RaceId = filterContext.HttpContext.Items [“RaceId”]之前base.OnAuthorization(filterContext);它现在有效! – Mike 2011-05-13 18:55:49

+0

请注意任何使用Darin建议通过'httpContext.Items'传递数据的人:在检查'httpContext.Items'之前,您需要'OnAuthorization'调用'base.OnAuthorization(filterContext)'。直到我做到这一点,我才能开始工作。 – 2013-06-05 19:43:59