MVC Session全局变量

时间:2016-06-10 11:54:37

标签: asp.net-mvc

这是我想要实现的目标。仅当用户具有"下属"时,导航栏上的某些选项才可用。在数据库中。

所以,在导航栏我有: enter image description here

应该为某些用户隐藏审批,但其他人可以使用。对于那些应该可用的用户,用户必须: A)成为主管或者, B)在数据库表中有一个subornidate

因此,对于" A"它很简单。我做了:

                    @if (User.IsInRole("Supervisor"))
                    {
                        <li>@Html.ActionLink("Approvals", "Index", "Approval")</li>
                    }

对于&#34; B&#34;,我被建议使用Sessions。好吧,太好了。所以我提出了一个问题:如何向数据库发出单个请求并将其分配给会话[&#34; HasSubordinates&#34;]以便我可以进行此检查?

                    @if (User.IsInRole("Supervisor") || (bool)Session["HasSubordinates"])
                    {
                        <li>@Html.ActionLink("Approvals", "Index", "Approval")</li>
                    }

我尝试的是:

Session["HasSubordinates"] = _uow.ApprovalService.GetSubordinates(User.Identity.Name).Count() > 0;

对于每一个控制器,但这并没有很好地工作,因为有时我得到空指针,它看起来绝对垃圾。

我知道这对某些人(或大多数人)来说听起来像是一个微不足道的问题,但我真的被困住了,我真的很感激任何帮助。

2 个答案:

答案 0 :(得分:1)

查看您的代码,获取用户下属应该只发生一次。在您的登录方法中:

Session["HasSubordinates"] = _uow.ApprovalService.GetSubordinates(User.Identity.Name).Count() > 0;

创建一个新类以扩展IPrincipal:

public class IPrincipalExtensions
{
  public bool HasSubordinates(this IPrincipal user)
  {
    return Session != null && Session["HasSubordinates"] != null && Session["HasSubordinates"] > 0;
  }
}

现在,在视图中:

@if (User.IsInRole("Supervisor") || User.HasSubordinates() )
{
}

从记忆中写作,可能会遗漏一些东西,但这应该是最干净的。

答案 1 :(得分:1)

请勿使用此会话。你需要的是一个儿童行动。

[ChildActionOnly]
public ActionResult Nav()
{
    var model = new NavViewModel
    {
        IsSupervisor = User.IsInRole("Supervisor");
        HasSubordinates = _uow.ApprovalService.GetSubordinates(User.Identity.Name).Count() > 0;
    }

    return ParialView("_Nav", model);
}

然后,只需创建一个局部视图_Nav.cshtml,然后利用视图模型上的属性来渲染您喜欢的导航。

如果需要,您甚至可以对子操作使用输出缓存,因此每个用户只评估一次。没有内置的方法来改变用户的缓存,因此首先,您需要在Global.asax中覆盖以下方法:

public override string GetVaryByCustomString(System.Web.HttpContext context, string custom)
{
    var args = custom.ToLower().Split(';');
    var sb = new StringBuilder();

    foreach (var arg in args)
    {
        switch (arg)
        {
            case "user":
                sb.Append(User.Identity.Name);
                break;
            case "ajax":
                if (context.Request.Headers["X-Requested-With"] != null)
                {
                    // "XMLHttpRequest" will be appended if it's an AJAX request
                    sb.Append(context.Request.Headers["X-Requested-With"]);
                }
                break;
            default:
                continue;
        }
    }

    return sb.ToString();
}

然后,您可以使用以下命令装饰您的子操作:

[OutputCache(Duration = 3600, VaryByCustom = "User")]