更新:2007 年 11 月
通过定义要由可视化设计器使用的合适的设计时属性,可以使自定义服务器控件在 Visual Studio 工具箱中可用。以下过程创建了一个名为 MailLink 的简单的控件,将其包括在工具箱中,并使用它通过呈现带有 mailto: URL 的超链接 <a> 元素在网页中创建电子邮件链接。
创建包含设计时属性的自定义控件
在 Visual Studio 中,创建库项目并定义从 WebControl 派生的自定义类,如下面的示例所示。
说明:“示例”部分列出了完整的源代码。
<Assembly: TagPrefix("Samples.AspNet", "Sample")> Namespace Samples.AspNet < _ ToolboxData("<{0}:MailLink ID='MailLinkID' Text='WebMaster' runat=""server""> </{0}:MailLink>")> _ Public Class MailLink Inherits WebControl ' Custom code goes here. End Class End Namespace[assembly:TagPrefix("Samples.AspNet", "Sample")] namespace Samples.AspNet { [ ToolboxData("<{0}:MailLink ID='MailLinkID' Text='WebMaster' runat=\"server\"> </{0}:MailLink>") ] public class MailLink : WebControl { // Custom code goes here. } }添加设计时属性以提供将用于在设计时在可视化设计器中显示控件的自定义元数据。使 MailLink 控件在 Visual Studio 工具箱中可用只需下列两个设计属性。
TagPrefix 属性指定控件名称 MailLink 前面的前缀。该前缀和控件名称一同定义自定义控件的标记名称(在此例中为 <Sample:MailLink> </Sample:MailLink>)。
<Assembly: TagPrefix("Samples.AspNet", "Sample")>[assembly:TagPrefix("Samples.AspNet", "Sample")]ToolboxData 属性指定在设计时将 MailLink 控件从工具箱拖到页中时为该控件生成的默认标记。
<ToolboxData("<{0}:MailLink ID='MailLinkID' Text='Mail Webmaster' runat='server'"> </{0}:MailLink>")>[ToolboxData("<{0}:MailLink ID='MailLinkID' Text='Mail Webmaster' runat=\"server\"> </{0}:MailLink>")]在库中编译 MailLink 控件并将其命名为 MaiLink.Dll。
将自定义控件添加到工具箱
在**“视图”菜单上单击“工具箱”**。
在“工具箱”中右击并选择**“选择项”**。
在**“选择工具箱项”对话框中选择“.NET Framework 组件”选项卡,然后单击“浏览”**按钮以找到刚生成的 MailLink.Dll。
选中 MailLink 控件的复选框并单击**“确定”**。
自定义 MailLink 控件将出现在工具箱中。
在页中引用 MailLink 控件
创建新的 Web 项目。然后创建名为 MailLink.aspx 的页。此页将包含下列指令之一,具体取决于为项目选择的语言。
<%@ page language="VB" %><%@ page language="C#" %>添加以下基本页结构以承载 MailLink 控件。
<html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Using the MailLink control</title> </head> <body> <h1>Using the MailLink Custom Server Control</h1> <form id="form1" runat="server"> <div> </div> </form> </body> </html>切换到“设计”视图并将 MailLink 控件拖到页上。
Visual Studio 将以下两项添加到页上:MailLink 控件的 Register 指令,以及要在该页中使用的 MailLink 控件的标记名称。
在浏览器中运行该页,然后单击**“邮件网站管理员”**链接。
将会打开一封邮件,该邮件将发送到控件的 Email 属性指定的地址。
示例
MailLink 控件重写 TagKey 属性以呈现 <a> 元素,而不会呈现 WebControl 类所呈现的默认 <span> 元素。
Imports System
Imports System.ComponentModel
Imports System.Security
Imports System.Security.Permissions
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
<Assembly: TagPrefix("Samples.AspNet", "Sample")> 
Namespace Samples.AspNet
    <AspNetHostingPermission( _
    SecurityAction.Demand, _
    Level:=AspNetHostingPermissionLevel.Minimal), _
    AspNetHostingPermission( _
    SecurityAction.InheritanceDemand, _
    Level:=AspNetHostingPermissionLevel.Minimal), _
    ParseChildren(True, "Text"), _
    DefaultProperty("Email"), _
    ToolboxData("<{0}:MailLink ID='MailLinkID' Text='Mail Web Master' runat=""server""> </{0}:MailLink>")> _
    Public Class MailLink
        Inherits WebControl
        <Browsable(True), Category("Appearance"), _
        DefaultValue("webmaster@contoso.com"), _
        Description("The e-mail address.")> _
        Public Overridable Property Email() As String
            Get
                Dim s As String = CStr(ViewState("Email"))
                If s Is Nothing Then s = "webmaster@contoso.com"
                Return s
            End Get
            Set(ByVal value As String)
                ViewState("Email") = value
            End Set
        End Property
        <Browsable(True), Category("Appearance"), _
        DefaultValue("Web Master"), _
        Description("The name to display."), _
        Localizable(True), _
        PersistenceMode(PersistenceMode.InnerDefaultProperty)> _
        Public Overridable Property [Text]() As String
            Get
                Dim s As String = CStr(ViewState("Text"))
                If s Is Nothing Then s = String.Empty
                Return s
            End Get
            Set(ByVal value As String)
                ViewState("Text") = value
            End Set
        End Property
        Protected Overrides ReadOnly Property TagKey() _
        As HtmlTextWriterTag
            Get
                Return HtmlTextWriterTag.A
            End Get
        End Property
        Protected Overrides Sub AddAttributesToRender(ByVal writer _
        As HtmlTextWriter)
            MyBase.AddAttributesToRender(writer)
            writer.AddAttribute( _
            HtmlTextWriterAttribute.Href, "mailto:" + Email)
        End Sub 'AddAttributesToRender
        Protected Overrides Sub RenderContents(ByVal writer _
        As HtmlTextWriter)
            If [Text] = String.Empty Then
                [Text] = Email
            End If
            writer.WriteEncodedText([Text])
        End Sub 'RenderContents
    End Class 'MailLink
End Namespace
using System;
using System.ComponentModel;
using System.Security;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
[assembly:TagPrefix("Samples.AspNet", "Sample")]
namespace Samples.AspNet
{
    [
        AspNetHostingPermission(SecurityAction.Demand,
        Level = AspNetHostingPermissionLevel.Minimal),
        AspNetHostingPermission(SecurityAction.InheritanceDemand,
        Level = AspNetHostingPermissionLevel.Minimal),
        ParseChildren(true, "Text"),
        DefaultProperty("Email"),
        ToolboxData("<{0}:MailLink ID='MailLinkID' Text='Mail Web Master' runat=\"server\"> </{0}:MailLink>")
    ]
    public class MailLink : WebControl
    {
        [
            Browsable(true),
            Category("Appearance"),
            DefaultValue("webmaster@contoso.com"),
            Description("The e-mail address.")
        ]
        public virtual string Email
        {
            get
            {
                string s = (string)ViewState["Email"];
                return (s == null) ? "webmaster@contoso.com" : s;
            }
            set
            {
                ViewState["Email"] = value;
            }
        }
        [
            Browsable(true),
            Category("Appearance"),
            DefaultValue("Web Master"),
            Description("The name to display."),
            Localizable(true),
            PersistenceMode(PersistenceMode.InnerDefaultProperty)
        ]
        public virtual string Text
        {
            get
            {
                string s = (string)ViewState["Text"];
                return (s == null) ? String.Empty : s;
            }
            set
            {
                ViewState["Text"] = value;
            }
        }
        protected override HtmlTextWriterTag TagKey
        {
            get
            {
                return HtmlTextWriterTag.A;
            }
        }
        protected override void AddAttributesToRender(
            HtmlTextWriter writer)
        {
            base.AddAttributesToRender(writer);
            writer.AddAttribute(HtmlTextWriterAttribute.Href,
                "mailto:" + Email);
        }
        protected override void RenderContents(HtmlTextWriter writer)
        {
            if (Text == String.Empty)
            {
                Text = Email;
            }
            writer.WriteEncodedText(Text);
        }
    }
}
MailLink 控件还演示内部文本持久性。通过 MailLink,页开发人员可以在控件的标记内指定 Text 属性,如下面的示例所示。
<Sample:MailLink id="MaillinkID" Email="Webmaster@contoso.com" 
    runat="server">
 Mail Support Team
</Sample:MailLink>
内部持久性与控件的开始标记上的默认持久性相反,如下面的示例所示。
<Sample:MailLink Text="Mail Webmaster" runat="server" > </Sample:MailLink>
前面的代码是在将控件从工具箱拖到页中的时候为其生成的默认标记。
编译代码
在 Visual Studio 中,创建库项目并定义从 WebControl 派生的自定义类,如上述过程中所示。前面的代码部分列出了完整的源代码。
安全性
自定义服务器控件扩展了 ASP.NET 的功能,而且必须遵循某些安全准则。具体而言,您需要考虑下列内容:
运行时和设计时安全性。
具有强名称的程序集中的自定义控件。
承载自定义服务器控件的服务器上的操作系统安全性和访问控制列表 (ACL)。
用于限制控件可访问的资源的代码访问安全性。
全局程序集缓存中的托管程序集。