Skip Navigation LinksFront Page > Archive > Dynamically populating city and state from zip codes using AJAX and aspnet web services
posted on:7/27/2005 11:11:38 PM
Ajax PhotoSick of hearing about web services yet ? How about AJAX ? What if i told you that you could use AJAX (javascript and DHTML) to request the XML output of an asp.net web service and display the data without reloading the page. Interested yet? As you can imagine, this solution has many applications. It allows you to speed up your web application by not forcing the user to reload a page every time they request information, while at the same time only loading data when it is requested. As well as adding speed and function to your current tasks, you may find yourself inventing new ways to make your web applications more user friendly, that were just not feasible using server side technologies.

In the example below will investigate building a form that auto completes the city and state information after the user types in their zip code. There are two essential parts to this project. First being the creation of a web service that will return a city and state given its zip code. And the second, a HTML page that uses javascript to request the XML from the web service.

View Demo | Download Source

Step 1: Creating the web service.

If your not familiar with web services you may be overwhelmed by all the hype that surrounds them. In actuality people spend allot more time talking about web services than actually coding them. This is because asp.net makes it very easy to build web services quickly without introducing an entirely new methodology to do so. If you need to catch up on your web services, I suggest reading An Extensive Examination of Web Services: Part 1 By Scott Mitchell.

The first step to building this web service was finding the zip code data. I have included in the zip package a csv file that contains 98% of the zip codes in the United States based on 2003 census data. Once you successfully download and extract this csv file, you will simply need to import the data into your sequel server and you will be ready to go.

Next you will need to build your asmx file. In this case our web service needs to accept an integer using "get", make a simple SQL query to the database and return the city and state. To accomplish this we use the following code.

<%@ WebService Language="VB" Class="ZipService" %>
Imports System.Web.Services
Imports System.Data
Imports System.Data.SqlClient
Imports System.Configuration

<WebService(Namespace:="http://www.aprogrammersjournal.com")> Public Class ZipService : Inherits WebService
 
  Private Function GetDataSet(strSQL as String) as DataSet

    Dim myConnection as New SqlConnection("Persist Security Info=False;Data Source=Server;Initial Catalog=db;User ID=XX ;Password=XX ;")
    Dim myCommand as New SqlCommand(strSQL, myConnection)
    myConnection.Open()

    Dim myDataAdapter as New SqlDataAdapter()
    myDataAdapter.SelectCommand = myCommand

    Dim myDataSet as New DataSet()
    myDataAdapter.Fill(myDataSet)
    myConnection.Close()
  
       Return myDataSet 
    End Function
  
     <WebMethod()> Public Function GetZip(Z As System.Single) as DataSet
    Return GetDataSet("Select city,state from zipcode where zip = "  Z)
  End Function

End Class

To see a demonstration of this code in action take a look at the web service running on my web server.

View Web Service

Step 2: Creating the AJAX file.

Now that you have your web service built we need to put it to use. In this case the challenge was to auto complete form fields based on zip code data. After the user types in zip code we need to trigger an event to invoke a client side XMLHttpRequest, aggregate that data and fill in the other form fields. We will start by looking at the java script functions below.

<script language="Javascript">
 
  <!--
 
  var req;
  var response;
  var city;
  var state;
 
  function loadXMLDoc(url) {
      // branch for native XMLHttpRequest object
      if (window.XMLHttpRequest) {
          req = new XMLHttpRequest();
          req.onreadystatechange = processReqChange;
          req.open("GET", url, true);
          req.send(null);
      // branch for IE/Windows ActiveX version
      } else if (window.ActiveXObject) {
          isIE = true;
          req = new ActiveXObject("Microsoft.XMLHTTP");
          if (req) {
              req.onreadystatechange = processReqChange;
              req.open("GET", url, true);
              req.send();
          }
      }
  }
 
  function processReqChange() {
      if (req.readyState == 4) {
          if (req.status == 200) {
  document.forms[0].output.value  = req.responseText
  response  = req.responseXML.documentElement;
  city = response.getElementsByTagName('city')[0].firstChild.data;
  state = response.getElementsByTagName('state')[0].firstChild.data;
  document.forms[0].city.value = city
  document.forms[0].state.value = state
          } else {
              alert("Please enter a valid zip code:\n" +
                  req.statusText);
          }
      }
  }
 
  function loadxml(form) {
  loadXMLDoc('http://www.aprogrammersjournal.com/zipcodes.asmx/GetZip?z=' + document.forms[0].zipcode.value);
  }
   
  //-->
 
  </script>
 

As you can see we are passing the url of our web service loadXMLDoc function and defining the nodes to display the data. Now all that is left to do is invoke the script, in this case we will use the OnBlur event like so:

<input type = "text" name = "zipcode" onblur = "loadxml(this.form);" />

Why HTML ?
Some of you may be familiar with the great client side scripting capabilities of asp.net and wonder why I would choose standard javascript over asp.net. The bottom line is that even though my web service is written is asp.net my client can be deployed on any server no matter what technology it is using. Also using this method takes a good amount of load off of your web server because you are basically pushing all of the work on the client. The client computer invokes the web service parses the XML and returns the result to the user. The server only had to serve up a small html file which takes almost no resources to complete.

View Demo | Download Source



Comments For This Article:

This article is featured on code project. please take a minute to vote if you have an account. http://www.codeproject.com/aspnet/AjaxWebServices.asp thanks, Jason

posted on: 8/5/2005 12:19:28 PM by jason


Great article! This really was a great intro to AJAX. I have read some of it and just not given much thought to it, but the way in which you presented this was a very easy understanding of what AJAX is and the new benefits developers are afforded. Cheers, Jeremy

posted on: 8/8/2005 1:59:35 AM by Jeremy


I tried your sample and it is returning an error of Internal Server Error... I made sure to create the directory as an application and even gave it Script access but same error. Any ideas would be appreciated, it sure is a great implementation of both services though. Very excited about getting it to work.

posted on: 8/10/2005 6:46:01 PM by Kevin M


Just so everyone knows... when you install this app you have to enable the post and get properties within the web.config file on the web server for the application with which you are running it. http://www.ryantechinc.com Thanks Jason for the wonderful example...

posted on: 8/10/2005 9:28:15 PM by Kevin M


yes you will need to add the following code to your web config file.




this will make your web service available to the "public." By default web services are only accessable to localhost or 127.0.0.1 Thanks for the great comments Kevin and Jeremy. I checked out ryantech. cool site. I guess I should make a box where people can type thier website when they post a comment. -jason

posted on: 8/10/2005 10:56:58 PM by Jason


Does anyone know if this is at all possible with CF 5??? I am able to actually get results but the city & state fields do not populate... see below for sample code. SELECT city,state FROM T_Zips WHERE zipcode = #z# #Get_Location.City##Get_Location.State#

posted on: 11/10/2005 8:54:50 AM by Tony


Try again
(cfsetting enablecfoutputonly="Yes")
(cfheader name="content-type" value="text/xml") (cfsetting showdebugoutput="No") (cfparam name='z' default='96762') (cfquery name="Get_Location" datasource="harborsales") SELECT city,state FROM T_Zips WHERE zipcode = #z#(/cfquery) (?xml version="1.0" encoding="utf-8"?)

posted on: 11/10/2005 8:58:33 AM by Tony


resultant pronouncing thrown booster sorting Truk disposes sneaker

posted on: 2/20/2007 8:02:27 AM by


very usefull example

posted on: 6/12/2007 10:13:26 AM by asmvax


Thanks for the article. Using asp on the front end and asp.net on the backend, this article was amazingly on target with my needs. Thanks for taking the time to write it.

posted on: 8/4/2007 8:47:25 AM by Josh


very nice.if u show that xml document structure it will more usfull for understanding.

posted on: 1/9/2008 11:26:38 PM by venkat


What do I set the datatypes to for each column?

posted on: 2/27/2008 7:44:28 PM by Chris


I figured out my above question. The script works on an html form. Now how do I get it to work on a ASP form? There is no NAME on form fields, just ID.

posted on: 2/27/2008 9:39:06 PM by Chris


You can use the javascript function: findElementById 

document.forms[0].findElementById('city').value = city
document.forms[0].findElementById('state').value = state

or depending on where your script is placed:


document.findElementById('city').value = city
document.findElementById('state').value = state



hope this helps!

 

-jason

posted on: 2/27/2008 11:53:05 PM by Jason


Correction: Use the javascript function: getElementById to access the value property.

 

hope this helps !

 

-jason

 //use getElementById for id based objects.
document.getElementById('city').value = city
document.getElementById('state').value = state
//use getElementById for id based objects.
loadXMLDoc('zipcodes.asmx/GetZip?z=' + document.getElementById('zipcode').value);

posted on: 2/28/2008 1:58:13 PM by Jason


Post A Comment:

  Your Name:


  Your Comment:

  Please Enter The Captcha Image: