以编程方式禁用服务器代码中的菜单项?

时间:2016-03-28 18:54:23

标签: asp.net asp.net-mvc

我是一个古老的ASP.NET Web Forms开发人员,他真的很生气,并试图让MVC,Razor和Bootstrap成为现实。

在我的_Layout.cshtml文件中,我有一个Hello World菜单。我想根据登录用户的安全性启用/禁用菜单项。

由于菜单是使用服务器端逻辑创建的,我正在根据Active Directory中的信息确定菜单项是否可用,并且也在服务器上,我认为我可以将服务器端共用例程根据成员身份或缺少全局组成员身份启用或禁用菜单项。

使用默认的自动生成的MVC _Layout.cshtml文件,只需添加一个下拉菜单"工具" item,如何按照上述方法以语法方式禁用菜单?我以为我想以编程方式添加一个"已禁用"如果不允许用户访问该函数,则将href属性设置为#以使其不可点击。

 <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>@ViewBag.Title - My ASP.NET Application</title>
        @Styles.Render("~/Content/css")
        @Scripts.Render("~/bundles/modernizr")
    </head>
    <body>
        <div class="navbar navbar-inverse navbar-fixed-top">
            <div class="container">
                <div class="navbar-header">
                    <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
                    @Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
                </div>
                <div class="navbar-collapse collapse">
                    <ul class="nav navbar-nav">
                        <li>@Html.ActionLink("Home", "Index", "Home")</li>
                        <li>@Html.ActionLink("About", "About", "Home")</li>
                        <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                        <li class="dropdown">
                            <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tools<span class="caret"></span></a>
                            <ul class="dropdown-menu" role="menu">
                                <li class="disabled">
                                    <a href="#">Show me the Contact Page</a>
                                </li>
                                <li role="separator" class="divider"></li>
                                <li>
                                    <a href="@Url.Action("About", "Home")">Show me the About Page!</a>
                                </li>
                            </ul>    
                        </li>
                    </ul>                                                          
                    <p class="nav navbar-text navbar-right">Hello, @User.Identity.Name!</p>
                </div>
            </div>
        </div>
        <div class="container body-content">
            @RenderBody()
            <hr />
            <footer>
                <p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>
            </footer>
        </div>

        @Scripts.Render("~/bundles/jquery")
        @Scripts.Render("~/bundles/bootstrap")
        @RenderSection("scripts", required: false)
    </body>
    </html>

抱歉是个菜鸟

1 个答案:

答案 0 :(得分:0)

首先,我首先将导航器放入其自己的局部视图中,因为它可能具有仅适用于导航的逻辑,因此我们可以保持_Layout清洁并减少混乱。

_layout

...
<div class="navbar-collapse collapse">
    @Html.Partial("_MainNav")
</div>
...

在该部分中,您可以使用Razor检查用户是否在角色中并以这种方式构建导航:

_MainNav

<ul class="nav navbar-nav">
    <li>@Html.ActionLink("Home", "Index", "Home")</li>
    <li>@Html.ActionLink("About", "About", "Home")</li>
    <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
    <li class="dropdown">
        <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tools<span class="caret"></span></a>
        <ul class="dropdown-menu" role="menu">
            @if (User.IsInRole("..."))
            {
                <li>
                    <a href="@Url.Action("Index", "Admin")">Admin Page</a>
                </li>
            }
            else
            {
                <li>
                    <a href="#" class="disabled">Admin Page</a>
                </li>
            }
        </ul>
    </li>
</ul> 

你真的不需要其他条件,但你说你想要添加一个禁用的类并将href设置为#。

另一种方法是制作一个控制器动作,动态构建菜单并将其作为HTML字符串返回到视图中。即_Layout导航区域中的@Html.Action("Home", "BuildNav")

第三种方法可能是创建自己的HtmlHelper,以根据您的自定义角色访问逻辑创建操作链接。它可能看起来像这样:

_layout

...
<li>@Html.RestrictedActionLink("Admin", "Index", "Admin")</li>
...

的HtmlHelper

public partial class HtmlHelpers {
    public static MvcHtmlString RestrictedActionLink(this HtmlHelper htmlHelper, string linkText, string actionName,
            string controllerName, RoleAccessLevels accessLevel, object routeValues = null, object htmlAttributes = null) {

            if (//check is user has access) 
               return MvcHtmlString.Create(string.Empty);

            var routeValuesDict = new RouteValueDictionary(routeValues);
            var customAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);

            var currentAction = htmlHelper.ViewContext.RouteData.GetRequiredString("action");
            var currentController = htmlHelper.ViewContext.RouteData.GetRequiredString("controller");

            if (actionName == currentAction && controllerName == currentController) {
                if (!customAttributes.ContainsKey("class"))
                    customAttributes.Add("class", "active");
                else 
                    customAttributes["class"] = string.Format("{0} active", customAttributes["class"]);
            }

            return MvcHtmlString.Create(string.Format("<li>{0}</li>", htmlHelper.ActionLink(linkText, actionName, controllerName, routeValuesDict, customAttributes).ToHtmlString()));
        }
}