asp tutorials, asp.net tutorials, sample code, and Microsoft news from 15Seconds
Data Access  |   Troubleshooting  |   Security  |   Performance  |   ADSI  |   Upload  |   Email  |   Control Building  |   Component Building  |   Forms  |   XML  |   Web Services  |   ASP.NET  |   .NET Features  |   .NET 2.0  |   App Development  |   App Architecture  |   IIS  |   Wireless
 
Pioneering Active Server
 Power Search





Active News
15 Seconds Weekly Newsletter
• Complete Coverage
• Site Updates
• Upcoming Features

More Free Newsletters
Reference
News
Articles
Archive
Writers
Code Samples
Components
Tools
FAQ
Feedback
Books
Links
DL Archives
Community
Messageboard
List Servers
Mailing List
WebHosts
Consultants
Tech Jobs
15 Seconds
Home
Site Map
Press
Legal
Privacy Policy
internet.commerce














internet.com
IT
Developer
Internet News
Small Business
Personal Technology

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

HardwareCentral
Compare products, prices, and stores at Hardware Central!

Protecting Users from Suspect Textual Data
By Chris Sully
Rating: 3.4 out of 5
Rate this article


  • email this article to a colleague
  • suggest an article

    Introduction


    Consider the following scenario: you are writing an application for a Web site that takes textual user input and permanently stores it for later presentation on the site, perhaps in a database. A simple example application might be a discussion forum.

    If you have a diverse user population, consider whether there is a need to limit the possibility of offensive text being entered and returned via your Web site.

    Several solutions spring to mind:

    • Enforce a closed user group for the application, i.e. ask the user to login/register before using the facility. This should make a user less likely to break site rules as you are then able to associate submitted text to a registered user. So if they do misbehave, you will be able to track them, assuming they registered with accurate information. Note that you can track non-registered users by other means, but the information is not necessarily of the same quality and reliability.

    • Moderation: have text approved by an administrator before it is published on the site. This may be an unacceptable drain on limited resources.

    • Don't let the user submit offending text. This is the preferred option, halting the problem effectively at the source. How do we achieve this?

    The solution presented here is based on a composite control that utilises an XML file to specify the roots of suspect words. The implementation language shall be VB .NET, and I'll be using a text editor and the command line compiler (vbc) to write and compile the code.

    Controls, Controls, Controls

    Let's start by quickly revisiting the types of controls available within ASP.NET and then continue on to composite controls.

    All controls we'll look at are server controls. They run on the server, rendering HTML to the client. A sensible differentiating categorisation to start with is whether the control is embedded in a Web form page (and therefore compiled on demand) or whether it exists in a pre-compiled state.

    Microsoft classifies and distinguishes the following types as ASP.NET server controls, which exist in the former category:

  • HTML server controls
  • Web server controls
  • Validation controls
  • User controls

    The first three I shall assume the reader is familiar with. These are the simplest types, as far as the programmer is concerned, and are pre-programmed for us by Microsoft within ASP.NET. User controls are a little different.

    A user control is an .aspx page 'rebadged' as an .ascx page, the functionality of which can be accessed from an .aspx page via registration and instantiation. This is a server-side include with several bells and whistles and is a great step forward for ASP/ASP.NET developers, particularly as the languages they are now writing in are fully OO compliant. Here's my definition, borrowing elements from others and adding my own slant:

    An ASP.NET user control is a group of one or more server controls or static HTML elements, possibly with additional code, which encapsulate a set of functionality. A user control could simply be an extension of the functionality of an existing server control(s) (such as an image control that can be rotated or a calendar control that stores the date in a text box). Alternatively, it could consist of several elements that work and interact together to deliver a prescribed set of functionality. A key feature is that by exposing properties of the control through the code-behind (or in the HTML), other elements can easily interact with the user control programmatically.

    Remember that the four types of controls discussed so far are all JIT compiled as part of the featureset offered by ASP.NET for the Web form pages with the extensions .aspx and .ascx. These are all derived from the page class hierarchy with its provided properties, methods, and events. Our controls don't have to be derived from the page class however; they can be distinct from the ASP.NET page framework as pre-compiled components. This, however, means we lose the support of this framework, and we have to get our hands a little dirtier.

    Microsoft makes a distinction between Web user controls and Web custom controls, which seems a little misleading to me because user controls are customisable to some extent as well. Anyway, as already stated two of the main distinctions between a user control and a custom control is that the latter is pre-compiled and more difficult to create than the former. The other main difference is that custom controls are considered more 're-usable', as they can be registered with the global assembly cache (GAC), whereas a copy of each user control is required per application (in the IIS sense). There are also differences with regard to IDE and design time support.

    In contrast to a user control, a custom control is compiled into a class. Further, the interface (HTML, JavaScript, etc.) is written out programmatically instead of being part of the user interface portion of the standard page class. This permits the programmer the flexibility to blend the richness of the .NET programming model with as complex an interface as is required. As a custom control is contained in a class, you have access to all the functionality of the .NET Framework; properties can be defined, and functions can be implemented. In fact, the server controls that ship with ASP.NET and Visual Studio .NET are in essence (complex) custom controls. They are compiled classes that when placed on a page, interact with each other, interact with the page (take advantage of events like OnLoad), emit HTML and script, and provide the power behind the ASP.NET technology.

    There are several ways to create custom controls, depending on your requirements:

    • You can compile a control that combines the functionality of two or more existing controls. For example, if you need a control that encapsulates a button and a text box, you can create it by compiling the existing controls together. Such a control is termed a Composite Control.

    • If an existing server control almost meets your requirements but lacks some required features, you can customize the control by deriving from it and overriding its properties, methods, and events.

    • If none of the existing Web server controls (or their combinations) meets your requirements, you can create a custom control by deriving from one of the base control classes. These classes provide all the basic functionality of Web server controls, so you can focus on programming the features you need.

    As you may have already realised, we shall be focussing on the first option: developing a simple composite control that delivers the required functionality. Note that for a problem of this complexity one would normally, given the pros and cons (discussed above), implement the required functionality as a user control, but we're also going to use this as an excuse to look at a few issues surrounding developing composite controls. The code presented is also meant as a starting point for your own explorations. If you're interested in the user control version of the application, either derive it yourself or see my column at aspalliance.com.

    Development of the Composite Control

    We will require a text box in which the user is going to type text, a corresponding submit button, and a label to provide feedback to the user. Our control is going to check whether this submitted text contains 'naughty' words by checking for the existence of word roots identified from a companion XML file of structure similar to:

    
    <?xml version="1.0"?>
    <words>
    	<word>word root 1</word>
    	<word>word root 2</word>
    </words>
    
    
    Remember you'll need to alter this file before the examples will behave as you might anticipate! The version we shall implement in this article will simply report whether the submitted text is valid or not. You may extend this functionality as you see fit.

    The following describes a composite control (Composite) that combines three ASP.NET server controls: a Textbox control, a Label control, and a Button control. When its child Button control is clicked, Composite checks whether the text submitted contains any dubious words as specified in the XML file (the filename of which, initially set as bad_words.xml, is defined as a custom property) and raises a custom event. It also exposes the Text property of its child Label control as a top-level property.

    Note that the child controls of a composite control are encapsulated. By default, they are not visible outside the parent. A page developer could try to access the child controls using the parent's Controls collection, but because of intervening literal controls - used to output basic HTML elements that do not require server side processing - it might be difficult to obtain the index of a particular child control.

    A composite control can choose whether to expose a child control as a property and also which properties and events of its child controls to expose as top-level properties and events. When a composite control synthesizes properties from those of its child controls, it merely delegates to the child controls, as shown in the following example.

    
    // Delegate to label, which is an instance of
    // System.Web.UI.WebControls.Label.
    
        Public Property Text() As String
             Get
                EnsureChildControls()
                Return label.Text
             End Get
             Set
                EnsureChildControls()
                label.Text = value
             End Set
          End Property
    
    
    Let's begin by looking at the code with the Web form from which the composite control is instantiated:

    Listing 1: composite.aspx

    
    <%@ Page Language="vb" debug="true" trace="true" %>
    <%@ Register TagPrefix="Custom" Namespace="CustomControls" Assembly = 
    "CustomControls" %>
    
    <html>
    <script language="VB" runat=server>
       Private Sub CheckText(sender As Object, e As CheckEventArgs)
          If e.Match = false Then
             Composite.Text = "<h2>Clean your dirty mind out!</h2>"
          Else
             Composite.Text = "Text validated OK."
          End If
       End Sub 
    </script>
    <body>
    
    <h1>Anti-Swear Composite Control Example</h1><br>
    
    <form runat=server>
    <Custom:Composite id = "Composite" OnCheck = "CheckText" filename = "bad_words.xml" runat = server/>
    </form>
    </body>
    </html>
    
    
    The above registers our composite control indicating the namespace and assembly names. We'll compile the control code to a .dll in the bin directory of our application, which will be the first place searched by ASP.NET. Note, as introduced earlier, for greater re-usability the dll could be placed in the GAC - perhaps the topic of a subsequent article.

    Within the user interface of the Web form, we instantiate the custom control, specifying:

    • a local sub to be executed when the OnCheck event is raised by the control. We shall expose the text value of the label of the composite control via a public property that shall be altered dependent on the value of another public property set by the OnCheck event.

    • the filename of the XML file containing the root words for checking by the control.

    • Finally we have the CheckText sub that may be called by the control, as already discussed.
    Moving onto the component itself. It has two classes that I've implemented as two separate VB source files: composite.vb and checkevent.vb.

    Listing 2: composite.vb

    
    Imports System
    Imports System.Web
    Imports System.Web.UI
    Imports System.Web.UI.WebControls
    Imports System.Xml
    Imports System.Collections
    
    
    Namespace CustomControls
       Public Class Composite
          Inherits Control
          Implements INamingContainer
          Private _filename As String = "bad_words.xml"
          Private label As Label
          Public box1 As TextBox
          
          Public Property filename() As String
             Get
                Return _filename
             End Get
             Set
                _filename = value
             End Set
          End Property
          
          'takes as input the submitted text and returns the sanitisied version if 
    'naughty words found,
          'or a copy of the original string if not
          
          Public Function CheckString(InputString as String) as string
    		Dim alWordList As new ArrayList
    		dim xmlDocPath as string = mappathsecure("bad_words.xml")
    		dim xmlReader as XmlTextreader = new xmlTextReader(xmlDocPath)
    		dim element as string
    		dim output as string
    		dim asterisks as string = "*************************"
    		
    			'load the naughty word roots into an arraylist
    			while (xmlReader.Read())
    				if xmlReader.NodeType=xmlNodeType.Text then
    					alWordList.Add(xmlReader.Value)
    				end if
    			end while
    			xmlReader.Close()
    			
    			'check the string, replacing naughty roots with the 
    'appropriate number of asterisks.
    			For Each element in alWordList
    
    	InputString=InputString.Replace(element,asterisks.substring(1, (element.length)))
    			Next   
            
    	        Return InputString		
                        
          End Function
          
          Public Property Text() As String
             Get
    			'This method first checks the current value of the 
    'ChildControlsCreated property. 
    		'If this value is false, the CreateChildControls method is called.
                EnsureChildControls()
                Return label.Text
             End Get
             Set
                EnsureChildControls()
                label.Text = value
             End Set
          End Property
          
          Public Event Check As CheckEventHandler
          
          Protected Overridable Sub OnCheck(ce As CheckEventArgs)
             RaiseEvent Check(Me, ce)
          End Sub
          
          'create the child controls of the composite control
          Protected Overrides Sub CreateChildControls()
                   
             Controls.Add(New LiteralControl("<h3>Enter some text: "))
             
             'the text box 
    		Dim box1 As New Textbox()
             box1.Text = ""
             Controls.Add(box1)
             
             Controls.Add(New LiteralControl("</h3>"))
                     
             'the button
             Dim button1 As New Button()
             button1.Text = "Submit"
             Controls.Add(New LiteralControl("<br>"))
             Controls.Add(button1)
             
             'dynamically add an event handler to the newly created button object
             AddHandler button1.Click, AddressOf Me.ButtonClicked
             
             Controls.Add(New LiteralControl("<br><br>"))
             label = New Label()
             label.Height = Unit.Pixel(50)
             label.Width = Unit.Pixel(500)
             label.Text = ""
             Controls.Add(label)
          End Sub
          
          Protected Overrides Sub OnPreRender(e As EventArgs)
             CType(Controls(1), TextBox).Text = ""
          End Sub
          
          Private Sub ButtonClicked(sender As [Object], e As EventArgs)
             OnCheck(New CheckEventArgs(CType(Controls(1), 
    TextBox).Text,CheckString(CType(Controls(1), TextBox).Text)))
          End Sub
       End Class
    End Namespace
    
    
    Note, in (largely) code order:

    • We import the necessary namespaces for the classes we'll be using and define the namespace in which this class resides.

    • We proceed to define the composite class, which we set to inherit from the base control class and specify that the classes implements the INamingContainer interface, which allows it to route a postback event to its child Button control.

    • Composite creates its child controls in the CreateChildControls method and not in OnInit or in its constructor. CreateChildControls() creates the child controls of the composite controls; the sub-is called elsewhere in the code wherever an attempt is made to use the child controls (via ChildControlsCreated).

    • Composite does not expose the Click event of its Button child control. It instead handles the Click event and raises the custom event Check. If a composite control handles events raised by its child controls, it must wire the event handlers in CreateChildControls.

    • Composite exposes the following public properties:

      • Text: the base value of which is the Text property of the child Label control.
      • Filename: allows getting or setting of the XML filename from which naughty words are loaded for text checking

    • The main public function is CheckString which takes as input a text string, checks this string for 'naughty' root words as loaded from the specified XML file into an array list data structure. Any 'naughty' root words are replaced by the appropriate number of asterisks.

    • Sub OnPreRender clears the text of the textbox child control

    • Sub ButtonClicked fires when the child button control is pressed and calls the onCheck sub with appropriate arguments (a new CheckEventArgs object is passed checked and unchecked text as constructor parameters). OnCheck in turn raises an event which will be handled by code in the parent .aspx page. The event is 'bubbled' up from the child control up to the container and exposed as top-level events on the container object for use.

    Listing 3: checkevent.vb

    
    ' CheckEvent.vb
    ' Contains the code for the custom event data class CheckEventArgs.
    ' Also defines the event handler for the Check event.
    Imports System
    Namespace CustomControls
       Public Class CheckEventArgs
          Inherits EventArgs
          Private _match As Boolean = False
          
          Public Sub New(string1 As String, string2 as String)
             If string1=string2 Then
                _match = True
             End If
          End Sub
          
          Public ReadOnly Property Match() As Boolean
             Get
                Return _match
             End Get
          End Property
       End Class
       
       Public Delegate Sub CheckEventHandler(sender As Object, ce As CheckEventArgs)
    End Namespace
    
    
    The preliminaries are as per composite.vb. The constructor of CheckEventArgs takes as parameters two strings and sets the value of the Boolean value 'match' appropriately. The event handler CheckEventHandler is also defined.

    Finally, in case you are proceeding without the help of an IDE, like myself, the code can be compiled as follows, from the root of your Web application and with a bin sub-directory there created:

    vbc /t:library /out:./bin/CustomControls.dll /r:System.dll /r:System.web.dll
    /r:System.drawing.dll /r:System.Data.dll /r:System.xml.dll *.vb

    I hope this has proven to be a useful introduction to some of the issues surrounding composite controls in the context of a useful mini-application, which you may to like to extend for your own use. Feedback is welcome, as are suggestions for future articles or enquiries regarding possible projects either myself or my company may be interested in becoming involved.

    References

    .NET Framework SDK documentation
    ASP.NET: Tips, Tutorials and Code Sams
    Professional ASP.NET Wrox
    Various online resources

    About the Author

    Chris Sully is a UK-based Microsoft Web developer currently focusing on development with .NET and ASP.NET in particular. He's originally from Wales, hence the name of the Web design and development company with which he is currently the technical director - Cymru-Web.net (http://www.cymru-web.net). Cymru-Web.net focuses on bespoke Web application development using .NET and related Microsoft technologies, though we also offer a range of basic 'off the shelf' products which can be customised.

    Other services Cymru-Web offer include hosting, design, training, etc. See the site for full details. Please contact me at chris.sully@cymru-web.net directly or use the enquiry form on the site if you are interested in any of our services.

    Cymru-Web does not currently take up 100% of Chris' time so he also writes technical articles and undertakes freelance work. Chris has a B.Sc. in Computing Science, an M.Sc. in Cognitive Science, and a Ph.D. in Computer Science (Neural Networks). He spent four years working for a global telco in Cardiff, initially as a Web author/designer and then gradually changing skillsets to that of a Web developer focusing on Microsoft technologies. He then spent two years for a global consultancy firm in London working on intranet applications before being invited to join Cymru-Web.net. His primary skillset is fairly standard -- more ASP than VB with significant SQLServer/ IIS/ XML/ XSLT etc. in the mix, as well as skills relating to full lifecycle design and development in an enterprise environment.

  • Rate This Article
    Not HelpfulMost Helpful
    1 2 3 4 5
    Other Articles
    Apr 21, 2004 - Creating a Web Custom Control
    Conrad Jalali shows how to build Web custom controls by creating one that displays checkboxes in a categorized, hierarchical view.
    [Read This Article]  [Top]
    Mar 15, 2004 - Creating a Popup Date Picker
    Conrad Jalali shows how to extend the functionality of the ASP.NET Calendar control to remove some of the annoying postback delays that occur when populating a text box with a date from a popup calendar.
    [Read This Article]  [Top]
    Oct 23, 2003 - Creating a Custom .NET Web Control With Events
    This article covers some of the essentials of building reusable Web controls. Learn how to create a Web control and its custom events and event arguments, as well as how to use the control properly within a page.
    [Read This Article]  [Top]
    Aug 12, 2003 - Creating a Generic Pager Control
    ASP.NET provides only one control that supports paging, the DataGrid. Tomasz Kaszuba shows how to build and implement a custom pager for different controls that change depending on the data source or presentation.
    [Read This Article]  [Top]
    Jun 10, 2003 - Hosting .NET Windows Forms Controls in IE
    Windows Forms within Web pages work in a manner similar to Java applets. Thiru Thangarathinam shows how to host Windows Forms controls in Internet Explorer and how to utilize .NET Code Access Security to configure what the control can do when running within the browser.
    [Read This Article]  [Top]
    May 6, 2003 - Building a Simple Mask Control
    James Culshaw shares his experiences building his first working custom control, a basic mask control that allows input of time values, and offers advice and tips to those just starting out.
    [Read This Article]  [Top]
    Mar 3, 2003 - Creating a Server Control for JavaScript Testing
    Learn how to create an ASP.NET server control that detects if a browser supports JavaScript AND if JavaScript is enabled.
    [Read This Article]  [Top]
    Nov 26, 2002 - Introduction to the .NET Speech SDK
    Rob Chartier offers a tour of the .NET Speech SDK Beta 2 and its use of the industry specification SALT. The article shows you how to create a basic speech-enabled Web user control.
    [Read This Article]  [Top]
    Aug 27, 2002 - Creating "Self Populating" Controls
    In this article, Luther Stanton shows how to combine inheritance and server controls to create a self-populating drop-down-list control.
    [Read This Article]  [Top]
    Apr 30, 2002 - Building ASP.NET User and Server Controls, Part 2
    Solomon Shaffer explains custom controls, describes the complexities and issues surrounding building such controls, and walks through a useful example.
    [Read This Article]  [Top]
    Mailing List
    Want to receive email when the next article is published? Just Click Here to sign up.

    Support the Active Server Industry


    The Network for Technology Professionals

    Search:

    About Internet.com

    Legal Notices, Licensing, Permissions, Privacy Policy.
    Advertise | Newsletters | E-mail Offers