Since the advent of the .NET framework and Web Services I've heard of many interesting and wonderful applications of the two technologies. However, you never really get an appreciation for something until you actually try it yourself. Well, I tried out these technologies with an idea of mine and I must say that it has turned out quite well and was not that difficult to implement. I now introduce to everyone my first ASP.NET application, The Amazon Explorer.
In a few words, the Amazon Explorer is an ASP.NET application that allows the user to search Amazon for any item in their catalogs by utilizing the Amazon Web Service (version 3.0).
How to setup/install
I used a Web Setup project to create the installer for Amazon Explorer in Visual Studio .NET 2002. Simple run the AmazonPortalSetup.msi and follow the instructions. You will need to have IIS running. The Setup creates a virtual directory in IIS and copies the files (source, DLL, etc ..) to your hard drive. Alternatively you can create an ASP.NET application from the Visual Studio templates then copy the source files from the zip file provided.
The adventure - lessons learnt
During the construction of this application I learned about the various capabilities and functionality offered by the .NET framework that take the pain out of web development and allow for easy usage of Web Services. I'll go through each of the useful features of ASP.NET and the .NET framework along with the functionality of the application in this section.
The user interface (UI)
The Amazon Explorer interface is a basic one that seeks to capture all necessary input from the user in an elegant and simple form. Below you can see screenshots of when the application is initially launched and one of the application displaying results from a previous search:
Figure 01: Initial application interface
Figure 02: Results page
For the lifetime of the application, these two screens are what you will come to see. The only exception being if an error occurs during the search, at which time you will see an appropriate error message displayed. The interface is a simple one and contains just a few ASP.NET Web Form controls. When I first started this application, I had used normal HTML versions of the Web Form controls you see, namely, Drop-Down lists, text boxes, and a submit button.
The problem here was that I was not able to keep the values of the controls across submissions of the form used in the application my default! Sigh ... but not for long, Web Forms came running to my rescue :). I discovered that Web Form controls were capable of retaining their values, by default, across submissions. My first thought ... beautiful! From this point, I replaced all the normal HTML controls with their respective Web Form control versions. Below you can see a shot of the UI as it is in the Visual Studio .NET IDE:
Figure 03: Visual Studio .NET IDE -- Design mode
In Figure 03 above, you will note the numbers 1 -3. Each of these areas contain different controls or components that comprise the entire Amazon Explorer application.
Area 1: DataGrid component
The DataGrid component is used to display the results of a search by the end-user. This component is quite ideal for the job as it can be bound to various data sources. The data source used is really dependent on your needs, but for this scenario I used a DataSet. The data source for the search is populated via the Amazon Web Service.
Area 2: Drop-Down lists, text boxes, and submit button
Drop Down lists were used to accommodate the easy selection by users of search parameters that aided in the search for the item in the Amazon catalog. One drop-down list was used to allow the user to select the category they think their item will be found in. The other list allows the user to specify the maximum number of results they want the search to produce on the results page.
Text boxes were used to gather loose (i.e. typed) input from the users. Specifically, I wanted to get the name of the item that the user wanted to search for. The other text boxes, I use to collect price range values so that the user can search for an item in a price range. Unfortunately the Amazon Web Service does not support price ranges via SOAP but do support it via normal HTTP requests. In the future when SOAP support exists, these text boxes will be used in the back-end but for now I leave them to display the validation features of ASP.NET Web Form controls.
Area 3: Validator controls
To perform input validation here, I used the .NET
CompareValidator Web Form control which quite nicely allows you to specify the items to be compared by just choosing them in the properties of the control. How sweet is that! Along with this nice feature, to specify an error message, you simply type it into a property field and voila you have yourself very nice and simple input validation on your Web Form.
CompareValidator property sheet
That pretty much took care of my user interface. The only extra is that I changed the format of the DataGrid using its property sheet to give me a nice looking color scheme for the DataGrid display. Everybody should remember this color scheme from Microsoft Word's Table AutoFormat option.
The Back-End (Code behind)
So now that we have a UI we need some code that processes the input from our UI to give us some meaningful output by means of displaying some results to the end-user. My implementation language of choice in this project is C#. Why one may ask? Well the .NET framework gives me the flexibility to implement this application in any of 30+ plus languages that it supports but for historical reasons, I like my curly braces and semi-colons :)
Initially when I started this project I thought I would have a lot of code to write. Boy was I wrong. The action starts in Amazon Explorer when the user clicks the "Search Amazon" button. The Web Form is sent back to the server where the input is gathered and run thru the Amazon Web Service which then returns some results to the Web Form for display to the user. That's it in a nice tight nutshell. All code for gathering the input from the text Boxes to processing the click of the Search button are in the back-end. Along with that however, we have several neat features offered by .NET.
Gathering & caching data
Amazon Explorer's main purpose is displaying results from a end-user search. As one can imagine there are times when there will be LOTS of results. A nice way to solve this issue is to have a mechanism to page the results displaying "x" results at a time. The DataGrid offers this functionality with the simple selection of a few property fields of the control. The fields involved in this are namely,
PageSize. Note also that you can implement your own custom paging solution for the DataGrid, however, I just wanted simple paging so I went with the property selections. Along with these property selections, one also has to create an event-handler for the
PageIndexChanged event which is fired by the DataGrid when a user selects a different page than the current page.
1: private void gridAmazonResults_PageIndexChanged
(object source, DataGridPageChangedEventArgs e)
3: gridAmazonResults.CurrentPageIndex = e.NewPageIndex;
4: dsetAmazonReponse = (DataSet)Cache[AMAZON_CACHE_NAME];
5: gridAmazonResults.DataSource = dsetAmazonReponse;
It is important to note here that all that is being done is to change the current page index in the DataGrid (line 3) and then bind the DataGrid (line 6) to a cached DataSet (line 4-5).
Caching in ASP.NET is quite simple and shows remarkable speed increases in terms of usability and processing of data. Initially when I was performing paging without caching, each page change required a hit to the Amazon Web Service for the page to be updated even though I already had all the information in the DataSet used in the application. Of course you can imagine the performance issues with this. The reason I use caching in the application, apart from the performance improvement, is that when a user does a search, it is better to allow him to view all the results returned at the time of his search. We only hit the Amazon Web Service again when the user clicks the "Search Amazon" button which indicates that he wants to perform a "brand new" search instead of looking at all his results.
1: private void btnSubmit_Click(object sender, System.EventArgs e)
4: dsetAmazonReponse = (DataSet)Cache[AMAZON_CACHE_NAME];
6: if( dsetAmazonReponse == null )
8: dsetAmazonReponse = new DataSet();
12: dsetAmazonReponse.Tables["AmazonResults"].Columns.Add("Our Price");
13: dsetAmazonReponse.Tables["AmazonResults"].Columns.Add("List Price");
17: Cache[AMAZON_CACHE_NAME] = dsetAmazonReponse;
19: dsetAmazonReponse = (DataSet)Cache[AMAZON_CACHE_NAME];
20: gridAmazonResults.DataSource = dsetAmazonReponse;
In the above code extract we see what's going on when a user requests a "brand new" search. We first remove the current DataSet that is in the cache (line 3-4) then we acquire a new DataSet and create the table we use to setup the data we get from the Amazon Web Service (line 6-18). After the request has been performed by the Amazon Web Service we rebind our DataGrid to the DataSet that now has the data we want to display in the grid to the user in a nice formatted manner (line19-21).
Like most applications, Amazon Explorer has certain characteristics that can be configured to affect how the application runs. One such example is the configuration that allows the application to be run behind a proxy. I wanted a mechanism that would allow me to change a flag or something to that effect to allow Amazon Explorer to work behind a proxy without me having to recompile code and all that fun stuff. Again, the .NET framework came through for me.
Microsoft has a mechanism which now allows developers to put their application specific settings in what they called .config files. Really and truly, these files are quite similar to .ini files with the only difference being that they are in XML format. Well with this nice feature, I was able to specify a few settings that would change as the application was distributed to various domains, machines, and developers.
<add key="SetProxy" value="off" />
<add key="ProxyIP" value="184.108.40.206" />
<add key="ProxyPort" value="8080" />
Above I am able to specify in the Web.config file some properties that I consider dynamic in the application. The proxy information allows me to change the proxy information for my location just by editing the .config file. When the user click the "Search Amazon" button again, the proxy will be used depending on the value of the
SetProxy field in the .config file.
1: private void Page_Load(object sender, System.EventArgs e)
3: if( ConfigurationSettings.AppSettings[CONFIG_PROXY_NAME] == "on" )
In line 3 of the above code, you can see how we access the settings specified in the .config file from the Web Form code. The
AppSettings collection of the
Configuration object contains all the key-value fields we specified in the
<appSettings> element of the XML based .config file. Gaining access to the values of the settings is a simple matter of indexing into the
AppSettings array and voila, you have your dynamic settings now loaded into your application.
The Amazon web service
The real work horse of the application is the Amazon Web Service. Without it, we would have no results to display. The Amazon Web Service API is quite simple and only requires a few lines of code to allow the developer to request a query and receive a collection of items. A sample piece of code to perform a general keyword search on Amazon's catalogs is as below:
1: AmazonSearchService amazonSrch = new AmazonSearchService();
2: KeywordRequest kwdReq = new KeywordRequest();
4: kwdReq.devtag = "1010101010";
5: kwdReq.keyword = "Beenie Man";
6: kwdReq.type = "heavy";
7: kwdReq.mode = "music";
9: ProductInfo prodMfg = amazonSrch.KeywordSearchRequest(kwdReq);
The three key objects are
ProductInfo. The name of the objects alone give you an idea of their purpose in the whole scheme of things. The
AmazonSearchService is what we use to connect to the Web Service offered by Amazon. Through this object we can perform various types of searches/requests as provided by the API. One such type search/request is the
KeywordRequest which allows us to do a search of the Amazon catalog by simple providing a keyword, quite similar to how one searches a regular web search engine like Google. Each of the various requests offered by the API returns some form of product information regarding the item(s) it found in the catalog. This information is encapsulated in the
ProductInfo object. The
ProductInfo object itself contains a collection of
Details objects. Each
Details object in the collection - an array - contains the specifics on an item found in the catalog. I will leave it to you to discover these specifics on your own because it is quite a lot!
Each time that we get some product information, we want to make that information available to our DataGrid so that it can be displayed to the end-user during their viewing of the results. We do this by adding the information to our DataSet which will later be bounded to the DataGrid.
1: private void AddToDataSet(ProductInfo newProducts)
3: DataRow newRow;
5: for( int i = 0; i < newProducts.Details.Length; i++ )
7: newRow = dsetAmazonReponse.Tables["AmazonResults"].NewRow();
9: newRow["Our Price"] = newProducts.Details[i].OurPrice;
10: newRow["List Price"] = newProducts.Details[i].ListPrice;
11: newRow["Catalog"] = newProducts.Details[i].Catalog;
As you can see above, every new item is placed in a new row of our DataSet (line 13) and the columns of the row are populated with the actual data from the
Details object (line 9-11). At the end of this method we would have collected all the product information we need to display to the user. When you look at the actual code you will see ways that you can modify and format the data as you wish. The above code is just a simple example.
From idea to reality, this application was done in about a week and a half on and off and with no prior knowledge of ASP.NET. That to me, is quite impressive and tells me that Microsoft has taken a step forward in their mission to help developers get things done quickly, but efficiently. I personally now have a lot of interest in the ASP.NET and Web Services and look forward to doing more work with both technologies. As you can see, the Amazon Web Service API is quite simple and not hard to use and ASP.NET itself is not difficult to use either as it provides powerful functionality in a simple interface via elegant controls and components.
Here is a list of resources I found very useful while developing and researching this application.
- Original article submitted