Web Control Rendering Example
This example shows how to create a control named MailLink
that
creates an e-mail 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 e-mail 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 e-mail client (if the e-mail 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, System.Web.UI.HtmlTextWriterTag.A corresponds to an <a> element and System.Web.UI.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. TheMailLink
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"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://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"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://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.