我的MVC 3 webapp有不同的部分需要检查用户是用户还是管理员,他们都可以访问相同的页面,除了一些页面有只有管理员可以看到的控制器(按钮和文本框)。我通过将用户的访问级别放入我的viewmodel并进行检查来进行检查:
@if (Model.UserAccess != "Viewer")
{
[do something]
}
我在行动中检查登录用户的访问权限。如果会话超时,我会将它们重定向到登录页面。
我的动作从项目页面视图调用并作为部分加载:
@{Html.RenderAction("CategoryList", "Home", new { categoryId = Model.CategoryId });}
我的控制器:
public PartialViewResult CategoryList(int categoryid = 0)
{
var useraccess = GetUseraccess();
[blablabla stuff done here]
var model = new CategoryViewModel()
{
CategoryList = categorylist
UserAccess = useraccess
};
return PartialView(model);
}
public string GetUseraccess()
{
var useraccess = "viewer"; //default
var check = SessionCheck();
if (check == "expired")
{
ModelState.AddModelError("", "Session expired. Please login again.");
Response.Redirect("/Account/LogOn");
}
else if (check == "admin")
{
useraccess = "admin";
}
return useraccess;
}
public string SessionCheck()
{
if (Session["UserAccess"] == null)
{
return "expired";
}
else if ((string)Session["UserAccess"] == "admin")
{
return "admin";
}
else // viewer
{
return "viewer";
}
}
现在工作正常。但是我一直在尝试实现一个自定义属性,在触发控制器之前检查会话的到期时间:
public class CheckUserAccessSessionAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var useraccess = filterContext.HttpContext.Session["UserAccess"];
if ((string)useraccess == null)
{
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Account", action = "LogOn" }));
}
}
}
[CheckUserAccessSession]
public PartialViewResult CategoryList(int categoryid = 0)
{
[same stuff as above here]
}
我收到错误
Exception Details: System.InvalidOperationException: Child actions are not allowed to perform redirect actions.
我理解错误发生的原因。但我还没有找到如何绕过它。同样地,我想向我的操作发送一些来自另一个自定义属性的数据,但由于RedirectToRouteResult而无法正常工作。
答案 0 :(得分:2)
您的问题是,您正在返回该操作方法的PartialViewResult,根据定义,该操作方法的输出将只是IIS提供的完整请求的一部分。您应该对提供部分视图所在的完整视图的操作方法进行权限检查。
从技术上讲,当您在初始实现中调用Response.Redirect时,您将远离ASP.NET MVC设计约定;即使它有效,但设计也不好。
答案 1 :(得分:0)
使用这段代码。它会起作用。
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
PartialViewResult result = new PartialViewResult();
result.ViewName = "noaccess";
filterContext.Result = result;
}