使用ActionFilters检查对象访问

时间:2013-03-21 07:43:47

标签: asp.net-mvc action-filter

我一直很高兴地使用带有自定义ActionFilterAtribute的BaseController类,重写OnActionExecuting()。我将这个BaseController类用于所有控制器,作为传递给Controller时检查id路由值的便捷方法。

这很好......我检查了一个id值,如果它存在,我检查一下控制器名称,它确定了id所属的对象类型。

但是......我开始得到在ControllerB中调用PartialView时创建的错误,并在用于父Controller / View的FilterContext中显示相同的id。例如,假设我有一个localhost / Project / Details / 5的url,其中Project是控制器,详细说明id = 5的操作。控制器“Notes”由于PartialView而被调用,此次为Controller“Notes”和原始“Project”id触发了我的ActionFilter。允许用户访问ProjectId = 5但不允许访问NoteId = 5

我希望这是有道理的 - 我正在努力解释。我现在需要找到一些方法来忽略PartialView,或者处理它,或者完全使用不同的方法。我的最终目标是能够根据对象的id检查我的应用程序中的对象访问。这种问题有“最佳方法”吗?也许我需要为每个控制器编写一个过滤器?或者也可以检查动作名称,以便我知道何时忽略“id”?

我的BaseController ......

public class AccessCheckAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        int id;

        if (filterContext.RouteData.Values["id"] != null)
        {
            if (int.TryParse(filterContext.RouteData.Values["id"].ToString(), out id))
            {
                SPTdb db = new SPTdb();

                switch (filterContext.RouteData.Values["Controller"].ToString().ToLower())
                {
                    case "project":
                        project = db.Projects.Find(id);

2 个答案:

答案 0 :(得分:0)

您决定ID来自哪个实体的方法非常有问题。您将遇到许多类似于当前问题的复杂情况。您可以使用通用基类来避免它,它仍然是一个有问题的方法

此外,如果您在任何地方扩展数据库访问逻辑,则无法利用实体框架的缓存功能。例如:如果您对动作中的有效id的查询过滤了上下文,并且您应该使用不同的上下文查询控制器中的同一实体以显示使用实际结果。在你的情况下,它可能不会导致任何问题,但它仍然是一个非常不必要的事情。

要解决您的问题,您应该摆脱动作过滤器并使用像存储库模式这样的简单结构:

public class ProjectController : Controller{
private GenericRead<Project> _projects;

//you may use DI of course
public ProjectController(){
    _projects = new ....
}

public ViewResult Details(int id){
    var project = _projects.Get(id);
    if(project == null)
      return ViewResult(); 
....
}

答案 1 :(得分:0)

我认为可以通过使用SQL查询来解决此问题。您传递表名以及对象标识的[键/值]。