我可以向razor视图添加自定义元数据类型吗?

我可以向razor视图添加自定义元数据类型吗?,razor,asp.net-mvc-5,Razor,Asp.net Mvc 5,目前,我使用一个继承自WebViewPage的抽象类来为MVC项目中的razor视图提供函数。我们正在使用自定义登录类/解决方案。我的班级是这样的: public abstract class AuthenticatedViewPageBase : WebViewPage { private Login _user; protected override void InitializePage() { _user = Session["User"] as

目前,我使用一个继承自
WebViewPage
的抽象类来为MVC项目中的razor视图提供函数。我们正在使用自定义登录类/解决方案。我的班级是这样的:

public abstract class AuthenticatedViewPageBase : WebViewPage
{
    private Login _user;

    protected override void InitializePage()
    {
        _user = Session["User"] as Login;
    }

    public bool HasPermission(Permissions permission)
    {
        return HasPermission(new List<Permissions> { permission });
    }
    public bool HasPermission(List<Permissions> permissions)
    {
        if (_user == null)
            _user = Session["User"] as Login;

        return _user != null && permissions.Any(thisPerm => _user.Permissions.Any(p => p.PermissionId == (int)thisPerm));
    }

    public bool HasPermission(List<Permissions> permissions, List<PermissionGroups> groups)
    {
        if (_user == null)
            _user = Session["User"] as Login;

        return _user != null &&
            (
                permissions.Any(thisPerm => _user.Permissions.Any(p => p.PermissionId == (int)thisPerm))
                ||
                groups.Any(thisPerm => _user.Permissions.Any(p => p.PermissionGroupId == (int)thisPerm))
            );
    }
}
@using PublicationSystem.Model.Enums
@model IEnumerable<PublicationSystem.Model.Profile>

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_LayoutSmBanner.cshtml";
}

@if (HasPermission(new List<Permissions>
{
    Permissions.userCreate
}))
{
    <p>
        @Html.ActionLink("Create New", "Create")
    </p>
}
public abstract class AuthenticatedViewPageBase : WebViewPage
{
    //...
    public List<Permissions> ViewPermissions { get; set; }
    //...
}
[Authorize(Permission="userCreate")]
public ActionResult Create()
{
    //...
}

但是我希望是权限级别,而不是角色级别,并且我希望根据具有必要权限的用户启用隐藏/可见链接。

您可以使用自定义HTML帮助器轻松完成此任务。下面是一个接受角色参数的示例
SecureLink
。如果用户已登录并处于指定的任何角色,则链接将可见,否则它将不可见

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Web.Mvc;
using System.Web.Routing;

public static class HtmlHelperExtensions
{
    public static MvcHtmlString SecureLink(this HtmlHelper htmlHelper, string linkText, 
        string roles, string actionName)
    {
        return htmlHelper.SecureLink(linkText, roles, actionName, null, 
            new RouteValueDictionary(), new RouteValueDictionary());
    }

    public static MvcHtmlString SecureLink(this HtmlHelper htmlHelper, string linkText, 
        string roles, string actionName, object routeValues)
    {
        return htmlHelper.SecureLink(linkText, roles, actionName, null, 
            new RouteValueDictionary(routeValues), new RouteValueDictionary());
    }

    public static MvcHtmlString SecureLink(this HtmlHelper htmlHelper, string linkText, 
        string roles, string actionName, string controllerName)
    {
        return htmlHelper.SecureLink(linkText, roles, actionName, controllerName, 
            new RouteValueDictionary(), new RouteValueDictionary());
    }

    public static MvcHtmlString SecureLink(this HtmlHelper htmlHelper, string linkText, 
        string roles, string actionName, RouteValueDictionary routeValues)
    {
        return htmlHelper.SecureLink(linkText, roles, actionName, null, 
            routeValues, new RouteValueDictionary());
    }

    public static MvcHtmlString SecureLink(this HtmlHelper htmlHelper, string linkText, 
        string roles, string actionName, object routeValues, object htmlAttributes)
    {
        return htmlHelper.SecureLink(linkText, roles, actionName, null, 
            new RouteValueDictionary(routeValues), 
            HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public static MvcHtmlString SecureLink(this HtmlHelper htmlHelper, string linkText, 
        string roles, string actionName, RouteValueDictionary routeValues, 
        IDictionary<string, object> htmlAttributes)
    {
        return htmlHelper.SecureLink(linkText, roles, actionName, null, 
            routeValues, htmlAttributes);
    }

    public static MvcHtmlString SecureLink(this HtmlHelper htmlHelper, string linkText, 
        string roles, string actionName, string controllerName, 
        object routeValues, object htmlAttributes)
    {
        return htmlHelper.SecureLink(linkText, roles, actionName, controllerName, 
            new RouteValueDictionary(routeValues), 
            HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public static MvcHtmlString SecureLink(this HtmlHelper htmlHelper, string linkText, 
        string roles, string actionName, string controllerName, 
        RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes)
    {
        if (string.IsNullOrEmpty(linkText))
        {
            throw new ArgumentNullException("linkText");
        }
        if (!htmlHelper.IsInAnyRole(roles))
        {
            return MvcHtmlString.Create("");
        }
        return MvcHtmlString.Create(HtmlHelper.GenerateLink(
            htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, 
            null, actionName, controllerName, routeValues, htmlAttributes));
    }

    public static MvcHtmlString SecureLink(this HtmlHelper htmlHelper, string linkText, 
        string roles, string actionName, string controllerName, string protocol, 
        string hostName, string fragment, object routeValues, object htmlAttributes)
    {
        return htmlHelper.SecureLink(linkText, roles, actionName, controllerName, 
            protocol, hostName, fragment, new RouteValueDictionary(routeValues), 
            HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public static MvcHtmlString SecureLink(this HtmlHelper htmlHelper, string linkText, 
        string roles, string actionName, string controllerName, string protocol, 
        string hostName, string fragment, RouteValueDictionary routeValues, 
        IDictionary<string, object> htmlAttributes)
    {
        if (string.IsNullOrEmpty(linkText))
        {
            throw new ArgumentNullException("linkText");
        }
        if (!htmlHelper.IsInAnyRole(roles))
        {
            return MvcHtmlString.Create("");
        }
        return MvcHtmlString.Create(HtmlHelper.GenerateLink(
            htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, 
            null, actionName, controllerName, protocol, hostName, fragment, routeValues, 
            htmlAttributes));
    }

    private static bool IsInAnyRole(this HtmlHelper htmlHelper, string roles)
    {
        var user = htmlHelper.ViewContext.HttpContext.User;
        if (user == null || user.Identity == null || !user.Identity.IsAuthenticated)
        {
            return false;
        }
        if (string.IsNullOrEmpty(roles))
        {
            return true;
        }
        return user.IsInAnyRole(SplitString(roles));
    }

    private static bool IsInAnyRole(this IPrincipal user, IEnumerable<string> roles)
    {
        foreach (var role in roles)
        {
            if (user.IsInRole(role))
            {
                return true;
            }
        }
        return false;
    }

    private static string[] SplitString(string original)
    {
        if (String.IsNullOrEmpty(original))
        {
            return new string[0];
        }

        var split = from piece in original.Split(',')
                    let trimmed = piece.Trim()
                    where !String.IsNullOrEmpty(trimmed)
                    select trimmed;
        return split.ToArray();
    }
}
另一个选项是使用,它将自动使用
authorized属性
(或其任何子类)来控制导航链接的可见性

全面披露:我是
MvcSiteMapProvider
项目的主要贡献者

但是,无论您如何完成任务,您都应该使用MVC的内置
i原则
i密度
接口和
AuthorizeAttribute
,而不是重新发明轮子。您可以轻松地扩展
authorized属性
,以使用任何权限方案


向视图基类添加这种额外的混乱不是一个好方法。

这很好,但我仍然需要在链接中列出权限/角色。我希望链接查看视图,并让视图定义自己的权限。授权不是视图的责任。这是(
AuthorizeAttribute
是其中之一)的责任。隐藏链接的问题在于,实际上没有为操作方法(公共端点)提供任何安全性。“一次写入”方法是使用授权筛选器定义您的权限,然后让自定义HTML帮助程序使用该授权筛选器来确定链接是否应可见。这是在
MvcSiteMapProvider
中采用的方法。
[Authorize(Permission="userCreate")]
public ActionResult Create()
{
    //...
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Web.Mvc;
using System.Web.Routing;

public static class HtmlHelperExtensions
{
    public static MvcHtmlString SecureLink(this HtmlHelper htmlHelper, string linkText, 
        string roles, string actionName)
    {
        return htmlHelper.SecureLink(linkText, roles, actionName, null, 
            new RouteValueDictionary(), new RouteValueDictionary());
    }

    public static MvcHtmlString SecureLink(this HtmlHelper htmlHelper, string linkText, 
        string roles, string actionName, object routeValues)
    {
        return htmlHelper.SecureLink(linkText, roles, actionName, null, 
            new RouteValueDictionary(routeValues), new RouteValueDictionary());
    }

    public static MvcHtmlString SecureLink(this HtmlHelper htmlHelper, string linkText, 
        string roles, string actionName, string controllerName)
    {
        return htmlHelper.SecureLink(linkText, roles, actionName, controllerName, 
            new RouteValueDictionary(), new RouteValueDictionary());
    }

    public static MvcHtmlString SecureLink(this HtmlHelper htmlHelper, string linkText, 
        string roles, string actionName, RouteValueDictionary routeValues)
    {
        return htmlHelper.SecureLink(linkText, roles, actionName, null, 
            routeValues, new RouteValueDictionary());
    }

    public static MvcHtmlString SecureLink(this HtmlHelper htmlHelper, string linkText, 
        string roles, string actionName, object routeValues, object htmlAttributes)
    {
        return htmlHelper.SecureLink(linkText, roles, actionName, null, 
            new RouteValueDictionary(routeValues), 
            HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public static MvcHtmlString SecureLink(this HtmlHelper htmlHelper, string linkText, 
        string roles, string actionName, RouteValueDictionary routeValues, 
        IDictionary<string, object> htmlAttributes)
    {
        return htmlHelper.SecureLink(linkText, roles, actionName, null, 
            routeValues, htmlAttributes);
    }

    public static MvcHtmlString SecureLink(this HtmlHelper htmlHelper, string linkText, 
        string roles, string actionName, string controllerName, 
        object routeValues, object htmlAttributes)
    {
        return htmlHelper.SecureLink(linkText, roles, actionName, controllerName, 
            new RouteValueDictionary(routeValues), 
            HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public static MvcHtmlString SecureLink(this HtmlHelper htmlHelper, string linkText, 
        string roles, string actionName, string controllerName, 
        RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes)
    {
        if (string.IsNullOrEmpty(linkText))
        {
            throw new ArgumentNullException("linkText");
        }
        if (!htmlHelper.IsInAnyRole(roles))
        {
            return MvcHtmlString.Create("");
        }
        return MvcHtmlString.Create(HtmlHelper.GenerateLink(
            htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, 
            null, actionName, controllerName, routeValues, htmlAttributes));
    }

    public static MvcHtmlString SecureLink(this HtmlHelper htmlHelper, string linkText, 
        string roles, string actionName, string controllerName, string protocol, 
        string hostName, string fragment, object routeValues, object htmlAttributes)
    {
        return htmlHelper.SecureLink(linkText, roles, actionName, controllerName, 
            protocol, hostName, fragment, new RouteValueDictionary(routeValues), 
            HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public static MvcHtmlString SecureLink(this HtmlHelper htmlHelper, string linkText, 
        string roles, string actionName, string controllerName, string protocol, 
        string hostName, string fragment, RouteValueDictionary routeValues, 
        IDictionary<string, object> htmlAttributes)
    {
        if (string.IsNullOrEmpty(linkText))
        {
            throw new ArgumentNullException("linkText");
        }
        if (!htmlHelper.IsInAnyRole(roles))
        {
            return MvcHtmlString.Create("");
        }
        return MvcHtmlString.Create(HtmlHelper.GenerateLink(
            htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, 
            null, actionName, controllerName, protocol, hostName, fragment, routeValues, 
            htmlAttributes));
    }

    private static bool IsInAnyRole(this HtmlHelper htmlHelper, string roles)
    {
        var user = htmlHelper.ViewContext.HttpContext.User;
        if (user == null || user.Identity == null || !user.Identity.IsAuthenticated)
        {
            return false;
        }
        if (string.IsNullOrEmpty(roles))
        {
            return true;
        }
        return user.IsInAnyRole(SplitString(roles));
    }

    private static bool IsInAnyRole(this IPrincipal user, IEnumerable<string> roles)
    {
        foreach (var role in roles)
        {
            if (user.IsInRole(role))
            {
                return true;
            }
        }
        return false;
    }

    private static string[] SplitString(string original)
    {
        if (String.IsNullOrEmpty(original))
        {
            return new string[0];
        }

        var split = from piece in original.Split(',')
                    let trimmed = piece.Trim()
                    where !String.IsNullOrEmpty(trimmed)
                    select trimmed;
        return split.ToArray();
    }
}
@Html.SecureLink("Logged In Users Will See This", "", "About", "Home")
@Html.SecureLink("Admins and Managers Will See This", "Admin,Manager", "About", "Home")
@Html.ActionLink("Everyone Will See This", "About", "Home")