将可重用的 ASP.NET WebControl 连接到加载数据的方法

Posted

技术标签:

【中文标题】将可重用的 ASP.NET WebControl 连接到加载数据的方法【英文标题】:Connect reusable ASP.NET WebControl to a method for loading data 【发布时间】:2011-06-22 08:45:23 【问题描述】:

我正在尝试创建一个控件,该控件可以扩展其他 web 控件并根据用户权限设置一些属性,例如可见和启用。

这是一个示例,您的用户角色需要包含“CanSave”权限:

<asp:Button ID="btn1" runat="server" Text="Save"/>
<myControls:PermissionsExtender runat="server" ControlToSet="btn1" Permission="CanSave"/>

我试图保持这个可重用,这就是为什么 PermissionExtender 位于一个单独的项目中,不能与其他项目有任何依赖关系。为了做出决定,控制当然需要从其他地方(数据库或其他东西)获取此信息。我制作了另一个控件,并且使用事件,上述扩展器将由主控件设置,因此只需要知道在哪里查找信息。

现在需要对主控件进行配置,以了解有关角色和权限的信息的来源。我的想法是在可重用项目中有一个接口,并在其他地方实现它,然后配置我的控件去找到实现我需要的方法的类并通过反射加载它。但我不清楚这是如何工作的。我可能会将主控件放在母版页中,并为其提供一个类名,如 PermissionClass="SecurityLibrary.PermissionsClass"。有点像 ObjectDatasource 这样做,但欢迎提出其他建议。

方法签名如下: bool HasPermission(string permission) 它会知道当前用户的角色并使用该组合,查找角色是否包含权限。

如何将控件的调用连接到我的主项目中的一个方法,该方法可以提供必要的信息而不使它们相互依赖。

【问题讨论】:

【参考方案1】:

我想我有一些对你有用的东西(测试对我来说很好,但我可能误解了你正在寻找的部分内容)。使用此实现,asp.net 设计器代码将如下所示:

    <web:PermissionMasterControl runat="server" ID="masterController" PermissionClass="SecurityLibrary.RandomPermissionClass" />

    <asp:Button ID="btnSave" runat="server" Text="save" />
    <web:PermissionExtender runat="server" ControlToSet="btnSave" Permission="CanSave" MasterControllerID="masterController" />

现在是 SecurityLibrary。很简单,我包含了一个简单的“RandomPermissionClass”,它随机返回真/假。

Namespace SecurityLibrary
    Public MustInherit Class PermissionClass
        Public MustOverride Function HasPermission(ByVal permission As String) As Boolean
    End Class

    Public Class RandomPermissionClass
        Inherits PermissionClass

        Private rand As New Random()

        Public Overrides Function HasPermission(permission As String) As Boolean
            Return If(rand.Next(2) = 0, False, True)
        End Function
    End Class
End Namespace

现在我们有了“myControls”库,其中不包含对 SecurityLibrary 的引用。我创建了两个控件和一个委托。控件是“PermissionMasterControl”和“PermissionExtender”。委托用于实际执行对反射对象的检查。

Namespace myControls
    Public Delegate Function HasPermissionDelegate(ByVal permission As String) As Boolean

    Public Class PermissionMasterControl
        Inherits System.Web.UI.Control

        Public Property PermissionClass As String
            Get
                Return If(ViewState("PermissionClass") Is Nothing, "", ViewState("PermissionClass").ToString())
            End Get
            Set(value As String)
                ViewState("PermissionClass") = value
            End Set
        End Property

        Private ReadOnly Property PermissionDelegate As HasPermissionDelegate
            Get
                If _permissionDel Is Nothing Then
                    If Not String.IsNullOrEmpty(PermissionClass) Then
                        Dim t = Type.GetType(PermissionClass, False)

                        If t IsNot Nothing Then
                            _permissionObj = Activator.CreateInstance(t)

                            Dim mi As MethodInfo = _
                                    t.GetMethod("HasPermission", BindingFlags.Public Or BindingFlags.Instance)

                            _permissionDel = [Delegate].CreateDelegate(GetType(HasPermissionDelegate), _permissionObj, mi)

                        End If
                    End If
                End If

                Return _permissionDel
            End Get
        End Property

        Private _permissionObj As Object = Nothing
        Private _permissionDel As HasPermissionDelegate = Nothing

        Public Function HasPermission(ByVal permission As String) As Boolean
            If PermissionDelegate Is Nothing Then
                Throw New NullReferenceException("The specified permission class (" + PermissionClass + ") could not be loaded/found.")
            End If

            Return PermissionDelegate(permission)
        End Function
    End Class

    Public Class PermissionExtender
        Inherits System.Web.UI.Control

        Public Property ControlToSet As String
            Get
                Return If(ViewState("ControlToSet") Is Nothing, "", ViewState("ControlToSet").ToString())
            End Get
            Set(value As String)
                ViewState("ControlToSet") = value
            End Set
        End Property

        Public Property Permission As String
            Get
                Return If(ViewState("Permission") Is Nothing, "", ViewState("Permission").ToString())
            End Get
            Set(value As String)
                ViewState("Permission") = value
            End Set
        End Property

        Public Property MasterControllerID As String
            Get
                Return If(ViewState("MasterControllerID") Is Nothing, "", ViewState("MasterControllerID").ToString())
            End Get
            Set(value As String)
                ViewState("MasterControllerID") = value
            End Set
        End Property

        Protected ReadOnly Property MasterController As PermissionMasterControl
            Get
                If _mastercontroller Is Nothing Then
                    _mastercontroller = Me.Page.FindControl(MasterControllerID)
                End If

                Return _mastercontroller
            End Get
        End Property

        Protected ReadOnly Property ManagedControl As Control
            Get
                If _controlToSet Is Nothing Then
                    _controlToSet = Me.NamingContainer.FindControl(ControlToSet)
                End If

                Return _controlToSet
            End Get
        End Property

        Private _controlToSet As Control = Nothing
        Private _mastercontroller As PermissionMasterControl = Nothing


        Protected Overrides Sub OnLoad(e As System.EventArgs)
            MyBase.OnLoad(e)

            Dim bResult As Boolean = MasterController.HasPermission(Permission)

            ManagedControl.Visible = bResult
        End Sub
    End Class
End Namespace

【讨论】:

感谢您为我指明了正确的方向,我现在有一个与您的示例非常相似的解决方案。我使用事件将 MasterController 连接到页面上的多个控件。感觉完整时,我会在这里发布我的解决方案

以上是关于将可重用的 ASP.NET WebControl 连接到加载数据的方法的主要内容,如果未能解决你的问题,请参考以下文章

如何在asp.net mvc中将Webcontrol表导出到excel

将可选参数传递给 ASP.NET API 的 GET 方法

为啥不重用“ASP.NET_SessionId”?

在asp.net网站中动态加载用户控件(ascx)

在 ASP.NET 页面上多次重用变量

ASP.NET vNext - 重用现有的 nuget 包