The power of AJAX is the capability of calling the web server and updating only a portion of the page using JavaScript.
Besides calling code in the page itself, as it occurs when using the UpdatePanel, we can also call a web service with ASP.NET AJAX.
In this post, we’ll build a small page that calls a web service using JavaScript.
Let’s say we are a restaurant chain and we want our customers to be able to find a location close to them.
Open Visual Studio or Visual Web Developer Express and create a new web application. I’ll use C# for this sample. I named my project LocationsSample.
First, let’s create a class to represent a location. Add a new class to the project. Name it Location.cs.
Add the following properties to the class.
public class Location { public String Name { get; set; } public String StreetAddress { get; set; } public String City { get; set; } public String State { get; set; } public String Zip { get; set; } public String Phone { get; set; } public String Distance { get; set; } }
Next, let’s add a web service to the project. Name it LocationService.asmx.
The new web service will have a web method named HelloWorld by default. We’ll replace it with our own web method later. But first, take a look at the web service definition.
[WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.ComponentModel.ToolboxItem(false)] // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. // [System.Web.Script.Services.ScriptService] public class LocationService : System.Web.Services.WebService
In the comments, you can see that if we want to make our web service available through AJAX, we just need to uncomment one line. Let’s go ahead and uncomment it:
[System.Web.Script.Services.ScriptService] public class LocationService : System.Web.Services.WebService
The ScriptService attribute tells ASP.NET that we want to be able to call the web service from client scripts, in this case, from JavaScript.
Now, let’s replace HelloWorld with our web method. We’ll name it FindLocations. It will take one parameter for the zip code and will return an array of locations. In a real scenario, we would probably define other web methods that take different parameters, such as city and state.
[System.Web.Script.Services.ScriptService] public class LocationService : System.Web.Services.WebService { [WebMethod] public Location[] FindLocations(String zipCode) { List<Location> locations = new List<Location>(); if (zipCode == "92805") { Location loc = new Location(); loc.Name = "Store #1"; loc.StreetAddress = "275 S Harbor Blvd"; loc.City = "Anaheim"; loc.State = "CA"; loc.Zip = "92805"; loc.Phone = "(714) 555-5555"; loc.Distance = "0.2 miles"; locations.Add(loc); loc = new Location(); loc.Name = "Store #2"; loc.StreetAddress = "1189 S State College Blvd"; loc.City = "Anaheim"; loc.State = "CA"; loc.Zip = "92806"; loc.Phone = "(714) 555-1234"; loc.Distance = "1.6 miles"; locations.Add(loc); } return locations.ToArray(); } }
To keep the sample short, I hard coded only two locations close to one zip code. In a real application, we would probably query the database to find the locations.
Finally, let’s build the web page that will call the web service. Open the Default.aspx page and change it as shown below.
<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="LocationsSample._Default" %> <asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent"> </asp:Content> <asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent"> <asp:ScriptManager ID="ScriptManager1" runat="server"> <Services> <asp:ServiceReference Path="~/LocationService.asmx" /> </Services> </asp:ScriptManager> <script type="text/javascript"> function Find() { var zip = $get("<%= txtZipCode.ClientID %>").value; LocationsSample.LocationService.FindLocations(zip, onSuccess, onFailed); } function onSuccess(results) { if (results.length > 0) { var table = "<table border=\"1\" cellspacing=\"0\" cellpadding=\"10\">"; for (var i in results) { table += "<tr>"; table += "<td>"; table += "<b>" + results[i].Name + "</b><br/>"; table += results[i].StreetAddress + "<br/>"; table += results[i].City + ", " + results[i].State + " " + results[i].Zip + "<br/>"; table += results[i].Phone; table += "</td>"; table += "<td>" + results[i].Distance + "</td>"; table += "</tr>"; } table += "</table>"; $get("locationList").innerHTML = table; } else { $get("locationList").innerHTML = "<b>No locations found.</b>"; } } function onFailed(error) { $get("locationList").innerHTML = "<b>There was a problem communicating with the server.</b>"; } </script> <h2> Welcome to Oscar's Restaurants Family </h2> <p> Find a location near you. </p> <div> <span>Enter Zip Code: </span> <asp:TextBox ID="txtZipCode" runat="server"></asp:TextBox> <asp:Button ID="Button1" runat="server" Text="Find" OnClientClick="Find(); return false;" /> </div> <div id="locationList" style="margin-top: 10px; float: left;"></div> </asp:Content>
First, we added a ScriptManager control to enable AJAX on our page. Inside the script manager, we also define a Services section, where we reference our web service. This will take care of creating all the JavaScript functions needed to invoke the web service.
Then, we define our functions that will call the web service and update a portion of the page.
The Find function will get the zip code from a text box named txtZipCode using the $get function. We pass the zip code to the web method.
To call the web service we use a JavaScript function that has the same name as the web method, FindLocations. This function is created automatically thanks to the ScriptManager.
Our web method only takes one parameter, but we pass two extra parameters when calling it from JavaScript. The first parameter corresponds to the parameters defined in the web method. The second parameter is the name of the function that would be called after the web method is called successfully, while the third parameter is the name of the function that would be called if an error occurs when calling the web service.
The onSuccess function takes the results from the web method, in this case, an array of locations. We use this array to build a table inside a div named locationList. If the array is empty, we show a message inside the div.
The onFailed function only lets the user know that there was a problem. The error parameter contains info about the problem, in case we need to debug the code.
After the JavaScript code, we define the TextBox control for the zip code and a Button control that will invoke the Find function when pressed. After calling the function, we return false to prevent a postback.
At the end, we define an empty div named locationList, which will hold the table we build dynamically.
Go ahead and run the application. Enter zip code 92805 and press Find.
You’ll notice how the table will appear without refreshing the whole page.
Please leave a comment if you have any question or suggestion.