用于在MVC中访问ViewData的集中功能

时间:2016-06-08 07:00:58

标签: c# asp.net-mvc asp.net-mvc-4 razor

我希望以不同的方式显示某些内容,具体取决于用户拥有的权限。要获得当前会话用户的所有权限列表,我已将它们放入ViewData

现在,我在MainMenu.cshtml中创建了一个函数(HasPrivilege)来检查列表中是否有特定的权限。此信息用于以不同方式显示切片。

@functions {
    public bool HasPrivilege(Type privilege)
    {
        string name = privilege.Name;
        if (name.EndsWith("Attribute"))
        {
            name = name.Substring(0, name.Length - "Attribute".Length);
        }

        return ((ISet<string>)ViewData[ViewDataKeys.Privileges]).Contains(name);
    }
}

@helper RenderTile(string targetUrl, string imageUrl, string title, bool isDouble = false, string bgColor = "Gray", bool enabled = true)
{
    string linkTitle = enabled ? "" : " title=\"" + Resources.Resources.PromptNotAuthorized + "\"";
    string linkCss = enabled ? "" : " disabled";
    <a href="@(enabled ? targetUrl : "#")" class="tile @(isDouble ? "double " : "")bg-succest@(bgColor)@(linkCss)"@Html.Raw(linkTitle)>
        <div class="tile-content icon">
            <img src="@imageUrl">
        </div>
        <div class="tile-status">
            <span class="name">@title</span>
        </div>
    </a>
}

@RenderTile(Url.Action(null, "User"), "../Images/User.png", Resources.Resources.NavUsers, true, enabled : HasPrivilege(typeof(UserViewReadAttribute)))
@RenderTile(Url.Action(null, "SapXslt"), "../Images/document_gear.png", Resources.Resources.NavXSLTs, enabled : HasPrivilege(typeof(SapXsltViewReadAttribute)))
@RenderTile(Url.Action(null, "Requirements"), "../Images/clipboard_checks.png", Resources.Resources.NavRequirements, enabled : HasPrivilege(typeof(RequirementViewReadAttribute)))

我遇到的问题是:我希望在没有代码重复的情况下在每个页面上都有这个功能。由于我很懒,我不想将ViewData提交到函数中,它应该可以从上下文中获得。

关于如何做到这一点的任何想法?

我发现了一些建议将代码放入App_Code的帖子。但是哪个代码呢?我是否必须延长课程?如果是这样,哪一个?

祝你好运,    卡斯滕

2 个答案:

答案 0 :(得分:1)

您可以将@helper函数集中到一个新的cshtml文件中,该文件位于MVC的App_Code目录中。然后可以使用<CSHTML FIle Name>.Method调用它们,例如如果您将@helper RenderTile放入名为RenderHelpers.cshtml的文件中,则可以调用RenderHelpers.RenderTile(...)

集中代码的另一种方法是编写扩展方法,例如对于ViewData:

public static class ViewDataExtensions {

    public static bool HasPrivilege(this ViewDataDictionary viewData, Type privilege) {
       // ...
    }
}

然后像if(ViewData.HasPrivilege(typeof(someAttribute)) {/* ... */}

一样使用它

但我建议为tile添加一个ViewModel,它具有一个由控制器设置的属性IsAuthorized,用于决定是启用还是禁用它。然后,您可以使用此ViewModel的View(或DisplayTemplate)而不是@helper函数渲染切片。

答案 1 :(得分:0)

感谢Georg,这是最终的解决方案。

MainMenu.cshtml中的来电:

@RenderTile(Url.Action(null, "User"), "../Images/User.png", Resources.Resources.NavUsers, true, enabled : Functions.HasPrivilege(ViewData, typeof(UserViewReadAttribute)))
@RenderTile(Url.Action(null, "SapXslt"), "../Images/document_gear.png", Resources.Resources.NavXSLTs, enabled : Functions.HasPrivilege(ViewData, typeof(SapXsltViewReadAttribute)))
@RenderTile(Url.Action(null, "Requirements"), "../Images/clipboard_checks.png", Resources.Resources.NavRequirements, enabled : Functions.HasPrivilege(ViewData, typeof(RequirementViewReadAttribute)))

Functions.cshtml中的文件App_Code

@using System.Collections.Generic;
@using System.Web.Mvc;
@using TestcaseRepository.Controllers;

@functions {
    public static bool HasPrivilege(ViewDataDictionary<dynamic> privileges, Type privilege)
    {
        string name = privilege.Name;
        if (name.EndsWith("Attribute"))
        {
            name = name.Substring(0, name.Length - "Attribute".Length);
        }

        return ((ISet<string>)privileges[ViewDataKeys.Privileges]).Contains(name);
    }
}