Lookup Area Codes by Zip Codes with an ASP.NET Custom Control in VB.NET

Introduction:

This article describes the construction of a simple custom control used to lookup an area code and a city/state location based upon a selected zip code; the lookup is performed through the use of an available public web service. The article includes the source code for this custom control and well as a demonstration site used to test the control.

The custom control contains a zip code property. Once set, the control will pass the zip code as an argument to a web method which will, if the zip code is valid, return the city, state, and area code associated with the zip code. The control will display the zip code, area code, and location whenever the zip code property is set or changed.

The demonstration web site included with this example provides an interface to change the zip code property for the control and to update the content displayed in the control. The web service is provided through www.webservicex.com and is available for use at no cost.

AreaCodeLookup1-in-vb.net.gif

Figure 1: Area Code Custom Control in Use

Getting Started:

The files included with this project include a web control library project and a demonstration web site. In order to get started, open the included zip file and install the two projects onto your file system. Open IIS and create a virtual directory for the web application. Open the solution into Visual 2005 and make any changes necessary to bring both projects into the solution. Once properly configured, your solution explorer should show these projects, references, and files:

AreaCodeLookup2-in-vb.net.gif

Figure 2: Solution Explorer with Web App and Control Library

In examining the solution, note that the "AreaCodeLookup" control library contains only a single control and that control is called "AreaCodeLookup". This project also includes a web reference that points to the http://www.webservicex.net site; this public site supports the web service used to capture the area code and location information associated with the user supplied zip code.

The web application contains only a single web page (default.aspx) and includes a reference to the "AreaCodeLookup" DLL.

The web application serves as a container used to test the custom control; the default.aspx page contains an instance of the custom control as well as an interface for submitting zip codes to the control.

The Code: AreaCodeLookup

The "AreaCodeLookup" custom control is constructed to retrieve the information from the web service upon initialization and to use that information to populate a collection of properties; each of the properties is set to contain one of the values collected from the web service.

The web service returns the requested data in the form of an XML node; this node is imported into an XML document which is parsed to obtain the individual values used to populate the member variables. These member variables are in turn used to display the area code and location information when the page is rendered.

In examining the code, note that, aside from the default imports, only the System.XML class has been added. The class itself inherits from the WebControl class.

Imports System

Imports System.Collections.Generic

Imports System.ComponentModel

Imports System.Text

Imports System.Web

Imports System.Web.UI

Imports System.Web.UI.WebControls

Imports System.Xml

 

<DefaultProperty("ZipCode"), ToolboxData("<{0}:AreaCodeLookup runat=server></{0}:AreaCodeLookup>")> _

Public Class AreaCodeLookup

Inherits WebControl

 

Following the class declaration, a region entitled "Declarations" is created and within that region are the declarations for any of the private member variables used within the control. In this case, there is only a single member variable as I opted to store all of the property values directly into view state.

#Region "Declarations"

 

Private mGetAreaCode As net.webservicex.www.USZip

 

#End Region

 

After the variable declarations, there is another region defined (Methods) and within that region is the code used to capture the data from the web service, and to read the XML returned by that service and use the values to populate the properties. The initialization handler calls a subroutine called "GetAreaCode" each time the control is initialized. GetAreaCode accepts a single argument in the form of a string bearing the zip code.

Inside the GetAreaCode subroutine, a new XML node is created. This node is populated with the return value derived from calling the web services "GetInfoByZip" web method. This node is checked to determine whether or not it is empty; if it is empty, the properties are set to contain an indication that the supplied zip code was invalid and the GetAreaCode subroutine is exited. If the node is not empty, an XML document is created and the node is imported into that document. This XML document is then parsed and its values are captured into the object's properties. When the control is rendered the properties are displayed to the user.

The code contained in the Methods region is as follows:

#Region "Methods"

 

Private Sub AreaCodeLookup_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init

 

AreaCode = ""

 

'get the area code for the current zip

GetAreaCode(ZipCode)

 

End Sub

 

Public Sub GetAreaCode(ByVal zip As String)

 

Try

 

mGetAreaCode = New net.webservicex.www.USZip

Dim xn As XmlNode = mGetAreaCode.GetInfoByZIP(zip)

 

If xn.HasChildNodes = False Then

AreaCode = "XXX"

ZipCode = "INVALID"

City = "XXX"

State = "XX"

Exit Sub

End If

 

Dim xdoc As New XmlDocument

xdoc.AppendChild(xdoc.ImportNode(xn, True))

 

 

Dim wsNodes As XmlNodeList

Dim wsNode As XmlNode

 

' get area code

wsNodes = xdoc.GetElementsByTagName("AREA_CODE")

 

For Each wsNode In wsNodes

AreaCode = wsNode.ChildNodes(0).Value

Next

 

' get city name

wsNodes = xdoc.GetElementsByTagName("CITY")

 

For Each wsNode In wsNodes

City = wsNode.ChildNodes(0).Value

Next

 

' get state name

wsNodes = xdoc.GetElementsByTagName("STATE")

 

For Each wsNode In wsNodes

State = wsNode.ChildNodes(0).Value

Next

 

Catch

 

AreaCode = "XXX"

ZipCode = "INVALID"

City = "XXX"

State = "XX"

 

End Try

 

End Sub

 

#End Region

 

The next region defined in the code is called "Properties". Properties contains a collection of one public property and three private properties. The public property is used to contain the zip code; the other private properties contain the area code, city, and state. All property values are maintained in view state, these properties are:

#Region "Properties"

 

<Category("Zip Code")> _

<Browsable(True)> _

<Description("Enter the five number zip code.")> _

Public Property ZipCode() As String

Get

Dim s As String = CStr(ViewState("ZipCode"))

If s Is Nothing Then

Return String.Empty

Else

Return s

End If

End Get

 

Set(ByVal Value As String)

ViewState("ZipCode") = Value

End Set

End Property

 

Private Property AreaCode() As String

Get

Dim s As String = CStr(ViewState("AreaCode"))

If s Is Nothing Then

Return String.Empty

Else

Return s

End If

End Get

 

Set(ByVal Value As String)

ViewState("AreaCode") = Value

End Set

End Property

 

Private Property City() As String

Get

Dim s As String = CStr(ViewState("City"))

If s Is Nothing Then

Return String.Empty

Else

Return s

End If

End Get

 

Set(ByVal Value As String)

ViewState("City") = Value

End Set

End Property

 

Private Property State() As String

Get

Dim s As String = CStr(ViewState("State"))

If s Is Nothing Then

Return String.Empty

Else

Return s

End If

End Get

 

Set(ByVal Value As String)

ViewState("State") = Value

End Set

End Property

 

#End Region

 

The attributes of category, browsable, and description are used to provide design time support for the custom control. The category and description text will be displayed in the IDE's property editor whenever this control is selected by the developer using the control.

Having captured the values from the XML string returned from the web service, and having populated the properties using the values contained in the XML, the only remaining step is to render the control. A region entitled, "Rendering" follows and it contains the code necessary to render the control on the page.

The code used to render the control is pretty simple; the HtmlTextWriter is used to define a table and set up its characteristics (cell padding in this example), each row of the table contains two cells, a label and its associated value are placed into each of those two cells. The City and State properties are combined into a Location string and displayed adjacent to the label reading "Location". Once all of the data has been written into the table, the ending tag is rendered and the control is complete.

Naturally, you can change the configuration of the table or remove some of the data returned from the web service by making changes in the definition of the HTML as defined through the HtmlTextWriter. If accessibility is an issue, you may wish to render the control based upon the user of a "div" in lieu of the table. The rendering operation is wrapped up in a try-catch block; if the rendering operation fails, the catch block will display some placeholder text. The RenderContents subroutine is overridden and the HTML is formatted within this subroutine through the use of the HtmlTextWriter.

#Region "Rendering"

 

Protected Overrides Sub RenderContents(ByVal output As HtmlTextWriter)

 

Try

 

output.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "3")

output.RenderBeginTag(HtmlTextWriterTag.Table)

 

output.RenderBeginTag(HtmlTextWriterTag.Tr)

 

output.AddAttribute(HtmlTextWriterAttribute.Align, "left")

output.RenderBeginTag(HtmlTextWriterTag.Td)

output.Write("<b>Zip Code: </b>")

output.RenderEndTag()

output.RenderBeginTag(HtmlTextWriterTag.Td)

output.Write(ZipCode)

output.RenderEndTag()

 

output.RenderEndTag()

output.RenderBeginTag(HtmlTextWriterTag.Tr)

 

output.RenderBeginTag(HtmlTextWriterTag.Tr)

 

output.AddAttribute(HtmlTextWriterAttribute.Align, "left")

output.RenderBeginTag(HtmlTextWriterTag.Td)

output.Write("<b>Area Code: </b>")

output.RenderEndTag()

output.RenderBeginTag(HtmlTextWriterTag.Td)

output.Write(AreaCode)

output.RenderEndTag()

 

output.RenderEndTag()

output.RenderBeginTag(HtmlTextWriterTag.Tr)

 

output.AddAttribute(HtmlTextWriterAttribute.Align, "left")

output.RenderBeginTag(HtmlTextWriterTag.Td)

output.Write("<b>Location: </b>")

output.RenderEndTag()

output.RenderBeginTag(HtmlTextWriterTag.Td)

output.Write(City & ", " & State)

output.RenderEndTag()

 

output.RenderEndTag()

output.RenderBeginTag(HtmlTextWriterTag.Tr)

 

output.RenderBeginTag(HtmlTextWriterTag.Tr)

 

output.RenderEndTag()

 

output.RenderEndTag()

 

Catch ex As Exception

 

output.Write("Area Code From Zip")

 

End Try

 

End Sub

#End Region

 

The Code: The Demo Site's Default Page

The default.aspx page contained within the demo site serves only a test container for the control. The page contains a label control used to title the page, a textbox used to capture zip codes, and a button to submit requests. The property editor may be used in the IDE to set the zip code property or, as is indicated in the submit button event handler, the zip code property may be edited while the web application is in use.

AreaCodeLookup3-in-vb.net.gif

Figure 3: Setting the Zip Code Property at Design Time

The button click event handler's code is as follows:

Protected Sub btnLookup_Click(ByVal sender As Object, ByVal e As

System.EventArgs) Handles btnLookup.Click

 

If Not String.IsNullOrEmpty(txtZip.Text.ToString()) Then

Try

 

Dim chr() As Char = txtZip.Text.ToCharArray()

Dim iLoop As Integer

For iLoop = 0 To chr.Length - 1

If Char.IsLetter(chr(iLoop)) Then

txtZip.Text = "INVALID"

Exit Sub

End If

Next

 

AreaCodeLookup1.ZipCode = txtZip.Text

AreaCodeLookup1.GetAreaCode(txtZip.Text)

 

Catch ex As Exception

 

End Try

End If

 

End Sub

AreaCodeLookup4-in-vb.net.gif

Figure 3: After Entering an Invalid Zip Code

The handler is pretty straight forward, the contents of the text box used to capture the zip code is first checked to make sure it is not empty. If isn't empty, the contents are checked to make sure that the value does not contain characters. If characters are encountered the text box text is set to display INVALID and the event handler subroutine is exited. If the text box contains a valid entry, the custom control's zip code property is set and then the control's GetAreaCode subroutine is called with text box text value passed in as the zip code argument.

From there, the custom control will, through the web service, update the area code, city, and state values which will in turn be displayed on the page through the control.

Summary

This project was intended to describe a useful, easy to build custom control. While this demonstration was limited to describing the AreaCodeLookup custom control, the same approach applied herein would work with a variety of other custom controls. The project itself describes some of the procedures that may be used to communicate with a web service through a custom control.v


Similar Articles