|
|||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionI wanted to display a bulleted list of items ( I noticed that there is a It worked — sort of. The bulleted list displayed the content of each string in my list, but it insisted on HTML-encoding every item. As I had hyperlinks within the list (<a href="somepage.htm">click me</a>), it was rendering to the output stream as <a href="somepage.htm">click me</a> such that I did not get a hyperlink in the page. Frustrating. Thanks for that auto-encoding, Microsoft! BackgroundI spent a little while looking into the I threw my hands up at another short-sighted "feature" of the framework, and went out to enjoy a meatball sub and oatmeal and raisin cookie, with a diet coke on the side. In the sandwich shop, whilst watching the July rain driving at the pavements outside, I decided to just write a control myself to do what I wanted — I thought I had quite a basic requirement here, and decided that in the time I spent Googling for the solution, I could have solved it myself. Now, all I had to do was get back across the road to the office, in a short sleeved shirt, in the pouring rain. I love Manchester. Developing the CodeMy first step was to create a .vb class file, which I called BulletedList.vb. I put the class inside a namespace to make it easy to register it later on, and made it inherit from Next, I created a property called " Public Property Items() As List(Of String)
Get
If IsNothing(ViewState("Items")) Then
' Instantiate the list of items to a new list; which will allow us to do ".Items.Add" from elsewhere in code without
' having to worry about null values checks.
ViewState("Items") = New list(Of String)
End If
Return DirectCast(ViewState("Items"), List(Of String))
End Get
Set(ByVal value As List(Of String))
ViewState("Items") = value
End Set
End Property
So, I can now hold a list of the strings I want to display on the page. The next thing is to tell the control how it should render them. I simply overrode the " Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
' Only output something if there are items in the collection:
If Items.Count > 0 Then
' Output start tag <ul>
writer.RenderBeginTag(HtmlTextWriterTag.Ul)
' Output all the items
For Each s As String In Items
writer.RenderBeginTag(HtmlTextWriterTag.Li)
writer.Write(s)
writer.RenderEndTag()
writer.WriteLine()
Next
' Output end tag </ul>
writer.RenderEndTag()
End If
MyBase.Render(writer)
End Sub
As you can see, it is reasonably straightforward. If there are any items in the list, then I create the opening HTML Encoding the TextI appreciate the sentiment of HTML-encoding the text from a security point of view; that HTML data retrieved from data stores (especially where that data has come from an unknown source) should always be HTML-encoded before it is displayed out onto web pages to help prevent injection attacks. For this reason, I provided another property, Public Property EncodeHtml() As Boolean
Get
If IsNothing(ViewState("EncodeHtml")) Then
Return False
Else
Return DirectCast(ViewState("EncodeHtml"), Boolean)
End If
End Get
Set(ByVal value As Boolean)
ViewState("EncodeHtml") = value
End Set
End Property
I then amended the Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
' Only output something if there are items in the collection:
If Items.Count > 0 Then
' Output start tag <ul>
writer.RenderBeginTag(HtmlTextWriterTag.Ul)
' Output all the items
For Each s As String In Items
writer.RenderBeginTag(HtmlTextWriterTag.Li)
If EncodeHtml Then
writer.Write(HttpContext.Current.Server.HtmlEncode(s))
Else
writer.Write(s)
End If
writer.RenderEndTag()
writer.WriteLine()
Next
' Output end tag </ul>
writer.RenderEndTag()
End If
MyBase.Render(writer)
End Sub
Using the CodeUsing the code is simple. First, register the control at the top of the .aspx file: <%@ Register TagPrefix="SCC" Namespace="SCC.WebUserControls" %>
Next, add the control into the .aspx markup where you want the bulleted list to appear: <SCC:BulletedList ID="blHyperlinks" runat="server" /> <!-- Render all items "as-is" -->
<SCC:BulletedList ID="blSafeHtml" runat="server" EncodeHtml="true" /> <!-- Encode HTML -->
Finally, in Dim Hyperlinks As New List(Of String)
Me.blHyperlinks.Items = Hyperlinks
and that's it. "Should just work". The downloadable file contains a fully XML-commented code listing for your perusal. Any comments welcome (particularly, if you can tell me whether the History
|
||||||||||||||||||||||||||||||||