How to: Use Custom ASP.NET Server Controls in Visual Studio 

You can make your custom server controls available in the Visual Studio Toolbox by defining the appropriate design-time attributes to be used by the visual designer. The following procedures create a simple control named MailLink, include it in the Toolbox, and use it to create an e-mail link in a Web page by rendering a hyperlink <a> element with a mailto: URL.

To create a custom control that contains design-time attributes

  1. In Visual Studio, create a library project and define a custom class that derives from WebControl, as shown in the following example.

    NoteNote

    The complete source code is listed in the Example section.

    <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.
        }
    
    }
    
  2. Add design-time attributes to provide custom metadata that will be used to display the control in the visual designer at design time. The following two design attributes are the only ones needed to make the MailLink control available in the Visual Studio Toolbox.

    The TagPrefix attribute specifies the prefix in front of the control name MailLink. Together, the prefix and control name define the tag name for the custom control (in this case, <Sample:MailLink> </Sample:MailLink>).

    <Assembly: TagPrefix("Samples.AspNet", "Sample")> 
    
    [assembly:TagPrefix("Samples.AspNet", "Sample")]
    

    The ToolboxData attribute specifies the default tag generated for the MailLink control when it is dragged from the Toolbox into a page at design time.

    <ToolboxData("<{0}:MailLink ID='MailLinkID' Text='Mail Webmaster' runat='server'"> </{0}:MailLink>")> 
    [ToolboxData("<{0}:MailLink ID='MailLinkID' Text='Mail Webmaster' runat=\"server\"> </{0}:MailLink>")]
    
  3. Compile the MailLink control in a library and name it MaiLink.Dll.

To add the custom control to the Toolbox

  1. On the View menu, click Toolbox.

  2. In the Toolbox, right-click and select Choose Items.

  3. In the Choose Toolbox Items dialog box, select the .NET Framework Components tab, and then click the Browse button to locate the MailLink.Dll you just built.

  4. Select the check box for the MailLink control and click OK.

    The custom MailLink control appears in the Toolbox.

  1. Create a new Web project. Then create a page named MailLink.aspx. This page will contain one of the following directives, depending on the language you selected for the project.

    <%@ page language="VB" %>
    
    <%@ page language="C#" %>
    
  2. Add the following basic page structure to host the MailLink control.

    <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>
    
  3. Switch to Design view and drag the MailLink control onto your page.

    Visual Studio adds two items to the page: a Register directive for the MailLink control, and the tag name of the MailLink control to use in the page.

  4. Run the page in a browser, and click the Mail Webmaster link.

    A mail message opens, addressed to the address specified by the control's Email property.

Example

The MailLink control overrides the TagKey property to render an <a> element instead of the default <span> element rendered by the WebControl class.

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);
        }
    }
}

The MailLink control also demonstrates inner text persistence. MailLink enables a page developer to specify the Text property within the control's tags, as shown in the following example.

<Sample:MailLink id="MaillinkID" Email="Webmaster@contoso.com" 
    runat="server">
 Mail Support Team
</Sample:MailLink>

Inner persistence is in contrast to default persistence on the control's opening tag, as in the following example.

<Sample:MailLink Text="Mail Webmaster" runat="server" > </Sample:MailLink>

The preceding code is the default tag generated for the control when it is dragged from the Toolbox into a page.

Compiling the Code

In Visual Studio, create a library project and define a custom class that derives from WebControl, as shown in the procedure above. The complete source code is listed in the previous code section.

Security

Custom server controls extend the functionality of ASP.NET and must follow some precise security guidelines. In particular, you need to consider the following:

  • Run-time and design-time security.

  • Custom controls in strong-named assemblies.

  • Operating system security and access control lists (ACLs) on the server that hosts the custom server control.

  • Code access security to restrict the resources the control can access.

  • Managed assemblies in the global assembly cache.

See Also

Concepts

Design-Time Attributes for Components
Attributes and Design-Time Support
Securing Custom Server Controls

Other Resources

Developing Custom ASP.NET Server Controls