Web Control Rendering Example
This example shows how to create a control named MailLink that creates an email link in a Web page by rendering a hyperlink (<a>) element with a mailto: URI. The control demonstrates the tasks that you will generally perform when rendering a control that derives from the WebControl class.
The MailLink control exposes an Email property for the email address and a Text property for the text to display on the hyperlink. A page developer can set these properties as shown by the highlighted text:
<aspSample:MailLink id="maillink1" Email="someone@example.com"
runat="server">
Mail Webmaster
</aspSample:MailLink>
If the markup rendered by the control is viewed on the client, it will appear as the following:
<a id="maillink1" href="mailto:someone@example.com">
Mail Webmaster
</a>
The behavior of a mailto: URI can be different in different browsers. In Internet Explorer, when a user clicks a mailto: hyperlink, the browser launches the user's default email client (if the email client is installed and compatible with the browser). The code for the MailLink control is described in the "Code Discussion" section later in this topic.
Code Listing for the MailLink Control
' MailLink.vb
Option Strict On
Imports System
Imports System.ComponentModel
Imports System.Security
Imports System.Security.Permissions
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Namespace Samples.AspNet.VB.Controls
< _
AspNetHostingPermission(SecurityAction.Demand, _
Level:=AspNetHostingPermissionLevel.Minimal), _
AspNetHostingPermission(SecurityAction.InheritanceDemand, _
Level:=AspNetHostingPermissionLevel.Minimal), _
DefaultProperty("Email"), _
ParseChildren(True, "Text"), _
ToolboxData("<{0}:MailLink runat=""server""> </{0}:MailLink>") _
> _
Public Class MailLink
Inherits WebControl
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue(""), _
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 = String.Empty
Return s
End Get
Set(ByVal value As String)
ViewState("Email") = value
End Set
End Property
< _
Bindable(True), _
Category("Appearance"), _
DefaultValue(""), _
Description("The text to display on the link."), _
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
Protected Overrides Sub RenderContents( _
ByVal writer As HtmlTextWriter)
If (Text = String.Empty) Then
Text = Email
End If
writer.WriteEncodedText(Text)
End Sub
End Class
End Namespace
// MailLink.cs
using System;
using System.ComponentModel;
using System.Security;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Samples.AspNet.CS.Controls
{
[
AspNetHostingPermission(SecurityAction.Demand,
Level = AspNetHostingPermissionLevel.Minimal),
AspNetHostingPermission(SecurityAction.InheritanceDemand,
Level=AspNetHostingPermissionLevel.Minimal),
DefaultProperty("Email"),
ParseChildren(true, "Text"),
ToolboxData("<{0}:MailLink runat=\"server\"> </{0}:MailLink>")
]
public class MailLink : WebControl
{
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("The e-mail address.")
]
public virtual string Email
{
get
{
string s = (string)ViewState["Email"];
return (s == null) ? String.Empty : s;
}
set
{
ViewState["Email"] = value;
}
}
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("The text to display on the link."),
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);
}
}
}
Code Discussion
The MailLink control example illustrates these tasks:
Rendering a non-default element for the control.
Rendering attributes on the control's opening tag.
Rendering content within the control's tags.
The MailLink control overrides the TagKey property to render an <a> element instead of the default <span> element rendered by the WebControl class. You should override the TagKey property if the element you want to render is a member of the HtmlTextWriterTag enumeration. Many common HTML element tags are mapped to values of the HtmlTextWriterTag enumeration. For example, HtmlTextWriterTag.A corresponds to an <a> element and HtmlTextWriterTag.Table corresponds to a <table> element. If the element you want to render is not represented by a member of the HtmlTextWriterTag enumeration, override the TagName property and return the string to render as the element.
The MailLink control overrides the following rendering methods of the WebControl class:
AddAttributesToRender to add an href attribute on the opening tag rendered by the control. When overriding AddAttributesToRender, you should always invoke the corresponding method of the base class, as the MailLink control demonstrates. The AddAttributesToRender method of the WebControl class implements logic to add styles and other attributes on the element rendered by the Web control and is called by the RenderBeginTag method of WebControl. Attributes must be added before the opening tag is rendered. This means that calls to AddAttributesToRender or AddAttribute come before calls to RenderBeginTag.
RenderContents to write the text for the hyperlink (specified by the Text property) within the control's tags. The MailLink control invokes the WriteEncodedText method of the HtmlTextWriter instance to HTML-encode the text entered by the page developer. In general, for security, you should HTML-encode text provided by users.
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 by the highlighted text:
<aspSample:MailLink id="maillink1" Email="someone@example.com"
runat="server">
Mail Webmaster
</aspSample:MailLink>
Inner persistence is in contrast to default persistence on the control's opening tag, as in this example:
<aspSample:MailLink Text="Mail Webmaster" runat="server" />
Default persistence and inner persistence are functionally identical. To enable inner persistence, MailLink is marked with the ParseChildren(true, "Text") attribute. The first argument of the ParseChildrenAttribute constructor specifies that the page parser should parse content within the control's tags as properties rather than as child controls. The second argument provides the name of the inner default property of the control (in this example, Text). When the ParseChildrenAttribute constructor is called with these two parameters, the content within the control's tags must correspond to the inner default property. The PersistenceMode(PersistenceMode.InnerDefaultProperty) attribute on the Text property specifies that a visual designer should serialize the property as inner content within the control's tags.
WebControl is marked with the PersistChildren(false) and ParseChildren(true) attributes, which govern design-time and parse-time property persistence. These are inherited with the control and need to be applied only if you want to change the inherited settings. The PersistChildrenAttribute tells the designer whether the child controls of a server control should be persisted as nested inner controls. The argument false indicates that inner content corresponds to properties and not to child controls. The ParseChildrenAttribute was described in the previous paragraph. If the design-time and parse-time persistence of the WebControl class is appropriate for your control, you do not have to override the PersistChildrenAttribute and ParseChildrenAttribute attributes inherited from WebControl.
Test Page for the MailLink Control
The following example shows an ASP.NET Web page (.aspx file) that uses the MailLink control.
<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="https://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>MailLink test page</title>
</head>
<body>
<form id="Form1" runat="server">
<aspSample:MailLink id="maillink1" Font-Bold="true"
ForeColor="Green" Email="someone@example.com" runat="server">
Mail Webmaster
</aspSample:MailLink>
</form>
</body>
</html>
<%@ page language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="https://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>MailLink test page</title>
</head>
<body>
<form id="Form1" runat="server">
<aspSample:MailLink id="maillink1" Font-Bold="true"
ForeColor="Green" Email="someone@example.com" runat="server">
Mail Webmaster
</aspSample:MailLink>
</form>
</body>
</html>
Building and Using the Example
For information about building the control and using it in a page, see Building the Custom Server Control Examples.