The products listed above, and their associated names, icons and logos, are the intellectual property of Microsoft Corporation.
Rate this Article!
Average Rating: 
Whole StarWhole StarWhole StarWhole StarWhole Star
Total number of ratings: 66
Leave your own rating
Shopping for local auto auctions using advanced search capabilities




Background


The goal of http://FindYourAuto.net site was to enhance the shopping experience on eBay motors. I have bought multiple vehicles on the site, and so have my friends and there were some issues I wanted to address, the prominent ones being the ability to see the vehicles on auctions in the context of location as well as time. Location because I wanted the users to be able to shop locally and have the option of driving the car before they bought it and time because the true value of the vehicle is reflected in the final hours and minutes of the auction.

The search interface was further enhanced with sliders so that users could quickly narrow down the search results, giving the application a very visual and interactive feel. In most cases a user would be able to narrow down to their desired vehicle in a couple of minutes.


In this article I will go over the main functionality of the site, and show the data as it flows through the system, using a similar sample application.



Technology


My job was made much easier by the presence of the Javascript debugger in VS 2008 and certain features in .net 3.5. If you write code once in a while like I do, being able to step through client-side code was great productivity booster. And I chose VE as the mapping platform because I was looking forward to the VE Silverlight control for future iterations of the site (it wasn’t out then), as well as other enhancements from the team such as the VE server control. Of course, the interactive SDK with the code sample was an added bonus.

I would also like to acknowledge Marco Anastasi, who had some excellent posts around VE and JSON on his blog here.


Onto Code


The are 3 main steps to this application


  • Accessing data

  • De-serializing, Manipulating and Serializing data

  • Displaying data on the map



Step 1: Accessing Data


eBay makes its data available in various formats, I chose to go with JSON over XML since it more lightweight, and this can make a difference when you are getting back hundreds of results in your result set. It can also be easily manipulated both on the server as well as the client browser.


eBay’s API expects requests in this format:
http://open.api.ebay.com/shopping?callname=FindItemsAdvanced&responseencoding=JSON&appid={your_app_id}&siteid={site_id}&version={api_version}&CategoryID={category_id}&MaxEntries={num_max_entries}&IncludeSelector={include_selector_type}



After all the variables have been filled in, the request looks something like this:

http://open.api.ebay.com/shopping?callname=FindItemsAdvanced&responseencoding=JSON&appid={your_app_id}&siteid=100&version=615&CategoryID=6131&MaxEntries=10&IncludeSelector=Details



The returned result looks something like this (shown in xml for better readability)


I have downloaded a part of this file and put it on the server, so we don’t have to worry about authentication issues for the sake of this example.

Here is the sample JSON formatted response from the eBay API


Step 2: De-serializing, Manipulating and Serializing data


Since the client-side JavaScript cannot access the remote eBay service directly we set up a proxy service on our server and leverage the ASP.NET AJAX infrastructure to directly call this service from the browser. This service makes a call on behalf of the client and additionally geocodes the data as it is received from
the eBay servers.


We add the [System.Web.Script.Services.ScriptService] attribute to the webservice, this creates a javascript helper class that can be directly called from the client



[System.Web.Script.Services.ScriptService]
public class eBayMotorsDemoSvc : System.Web.Services.WebService {
[WebMethod]
public string GeteBayMotorsData()
{
return eBayMotors.GetMotors();
}
}




Looking at the format of the returned JSON, we now create classes to hold the deserialised values.
These classes will mirror the properties we are interested in, for the returned JSON.


public class FindItemsAdvancedResponse
{
public string Ack { get; set; }
public searchResult[] SearchResult { get; set; }
}

public class searchResult
{
public itemArray ItemArray { get; set; }
}

public class itemArray
{
public List Item { get; set; }
}

public class item
{
public long ItemID { get; set; }
public string ViewItemURLForNaturalSearch { get; set; }
public string GalleryURL { get; set; }
public string PostalCode { get; set; }
public int BidCount { get; set; }
public string Title { get; set; }
public float lat { get; set; }
public float lng { get; set; }
public USDPrice ConvertedCurrentPrice { get; set; }
}

public class USDPrice
{
public float Value { get; set; }
}


Except for the lat and lng fields in items, which will be filled in by our custom geocoder, the rest of the values will be automatically filled in by the deserialization process. Now all that is left is to make the call and deserialize the data. The calls below set up the JavaScriptSerializer. This will be used to both serialize and deserialize the data.



JavaScriptSerializer eBaySerializer = new JavaScriptSerializer();
Uri jsonCallURI = new Uri("http://demoebaymotors.findyourauto.net/shopping.aspx");
HttpWebRequest webRequest = (HttpWebRequest)System.Net.WebRequest.Create(jsonCallURI);
HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();


After we get the response we parse it into a StreamReader



string jsoneBayResponse = string.Empty;
using (StreamReader sr = new StreamReader(webResponse.GetResponseStream()))
{
jsoneBayResponse = sr.ReadToEnd();
}


Now the magic of deserialization of the stream into C# objects happens


FindItemsAdvancedResponse ebayResponse = eBaySerializer.Deserialize(jsoneBayResponse);


If the call was successful, we take each of the objects representing the auction information about a particular vehicle and send it to be geocoded. For the sake of this example, since we are using static data I just setup a dummy geocoder.


if (ebayResponse.Ack == "Success")
{
eBayItems = ebayResponse.SearchResult[0].ItemArray.Item;
foreach (item eBayItem in eBayItems)
{
geocode(eBayItem);
}
return(eBaySerializer.Serialize(eBayItems));
}


After the geocoding is complete, we serialize the data for transfer to the client browser


return(eBaySerializer.Serialize(eBayItems));


Step 3: Displaying data on the map


Now we add a web-form to the application, and add a reference to the VE API as well as our proxy web service


<asp:ScriptManager ID="ScriptManager1" runat="server">
<Scripts>
<asp:ScriptReference Path="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2" />
</Scripts>
<Services>
<asp:ServiceReference Path="~/eBayMotorsDemoSvc.asmx" />
</Services>
</asp:ScriptManager>

We also setup a default instance of a VE map on the page, along with a button that initiates the call to the eBay web-service.


<input id="getData" type="button" value="Display eBay data" onclick="calleBayWS();" />
<div id="myMap" style="position: relative; width: 600px; height: 400px; top: 0px; overflow: hidden" />


On page load we initialize this instance of the map. Note we are using pageLoad() function provided by ASP.NET AJAX to encapsulate our initialization logic.


function pageLoad() {
if (map == null) {
map = new VEMap('myMap');
map.LoadMap(new VELatLong(40, -100), 4);
}
}


We then tie up the click event for the button to a call to the web-service


function calleBayWS() {
eBayMotorsDemoSvc.GeteBayMotorsData(calleBaySuccess, onFailed);
}


This service call takes two parameters, the first one is a pointer to the function that will be executed if the web service call was successful, and the 2nd parameter points to a function that is executed on call failure


function calleBaySuccess(e) {
var eBayData = Sys.Serialization.JavaScriptSerializer.deserialize(e);
if (eBayData.length > 0) {
Array.forEach(eBayData, DisplayOnMap);
}
}



In case the call completes successfully, the call return value is accessible through the parameter e. This parameter is now deserialized using the JavaScriptSerializer in ASP.NET AJAX. This process populates an Array of auction items into eBayData. We now iterate over this array using the Array.forEach provided by the AJAX client library.

As we iterate over each item we create the appropriate title and description for the pushpin and display them on the map. Here we again use the String.format function provided by the AJAX client library to create an appropriately formatted tooltip for our pushpin.


function DisplayOnMap(eBayDataItem) {
var htmlDescription = "<img src='{0}' width='150'/><br/><b>Bids:</b> {1}<br/><b>Current Price (USD)</b>: {2} <br/><A href='{3}' target='_blank'>Details</a>"

var title = eBayDataItem.Title;
var description = String.format(htmlDescription, eBayDataItem.GalleryURL, eBayDataItem.BidCount, eBayDataItem.ConvertedCurrentPrice.Value, eBayDataItem.ViewItemURLForNaturalSearch);
var lat = eBayDataItem.lat;
var lng = eBayDataItem.lng;

var point = new VELatLong(lat, lng);
var shp = new VEShape(VEShapeType.Pushpin, point);
shp.SetTitle(title);
shp.SetDescription(description);
map.AddShape(shp);
}

The final application looks like this


Link to the application: http://demoebaymotors.findyourauto.net/

Download Code




Copyright 2009. Sponsored by nsquared.   |  Terms Of Use  |  Privacy Statement
Content on this site is generated from the developer community and shared freely for your enjoyment and benefit. This site is run independently of Microsoft and does not express Microsoft's views in any way.