[ Home | Syllabus | Course Notes | Assignments | Search]
consists of three files
CityView.aspx: Web Form Gui
CityView.ashx: http HANDLER (web service client)
TerraService.dll: proxy
<html> <body> <h1>CityView</h1> <hr> <form runat="server"> <table cellpadding="8"> <tr> <td> City </td> <td> <asp:TextBox ID="City" Width="100%" RunAt="server" /> </td> <td> <asp:RequiredFieldValidator ControlToValidate="City" ErrorMessage="*" Display="static" Color="red" RunAt="server" /> </td> </tr> <tr> <td> State </td> <td> <asp:DropDownList ID="State" Width="100%" RunAt="server"> <asp:ListItem Text="AL" RunAt="server" /> //... </asp:DropDownList> </td> <td> </td> </tr> <tr> <td> </td> <td> <fieldset> <legend>Scale</legend> <asp:RadioButtonList ID="Scale" RunAt="server" RepeatColumns="2" RepeatDirection="Horizontal"> <asp:ListItem Text="1 meter" RunAt="server" /> <asp:ListItem Text="2 meters" RunAt="server" /> <asp:ListItem Text="4 meters" RunAt="server" /> <asp:ListItem Text="8 meters" Selected="true" RunAt="server" /> <asp:ListItem Text="16 meters" RunAt="server" /> <asp:ListItem Text="32 meters" RunAt="server" /> </asp:RadioButtonList> </fieldset> </td> <td> </td> </tr> <tr> <td> </td> <td> <asp:Button Text="Show Image" OnClick="OnShowImage" Width="100%" RunAt="server" /> </td> <td> </td> </tr> </table> </form> <hr> <asp:Image ID="MyImage" RunAt="server" /> </body> </html> <script language="C#" runat="server"> void OnShowImage (Object sender, EventArgs e) { StringBuilder builder = new StringBuilder (); builder.Append ("CityView.ashx?city="); builder.Append (City.Text); builder.Append ("&state="); builder.Append (State.SelectedItem.Text); builder.Append ("&scale="); switch (Scale.SelectedIndex) { case 0: builder.Append ("1"); //... } MyImage.ImageUrl = builder.ToString (); } </script>
<%@ WebHandler Language="C#" Class="CityViewImageGen" %> public class CityViewImageGen : IHttpHandler { public void ProcessRequest (HttpContext context) { // Extract user input from the query string string city = context.Request["City"]; string state = context.Request["State"]; string scale = context.Request["Scale"]; if (city != null && state != null) { // Determine the scale TS.Scale res = TS.Scale.Scale8m; // . . . // Generate the requested image string type = "image/jpeg"; ImageFormat format = ImageFormat.Jpeg; Bitmap bitmap = GetTiledImage (city, state, res, 600, 400); // . . . // Write the image to the HTTP response bitmap.Save (context.Response.OutputStream, format); } } Bitmap GetTiledImage (string City, string State, TS.Scale Scale, int cx, int cy) { Bitmap bitmap = null; Graphics g = null; try { // Instantiate the TerraService proxy TS.TerraService ts = new TS.TerraService (); // Get the latitude and longitude of the requested city TS.Place place = new TS.Place (); place.City = City; place.State = State; place.Country = "USA"; TS.LonLatPt point = ts.ConvertPlaceToLonLatPt (place); // Compute the parameters for a bounding box // . . . Image tile = Image.FromStream (new MemoryStream (ts.GetTile (tid))); g.DrawImage (tile, // . . . } // Return the image return bitmap; } // . . . }
GetTiledImage uses three TerraService Web methods:
ConvertPlaceToLonLatPt, which converts a “place” (city, state, country) into a latitude and longitude
GetAreaFromPt, which takes a latitude and longitude and an image size (in pixels) and returns an AreaBoundingBox representing the image boundaries
GetTile, which takes a tile ID (obtained from the AreaBoundingBox) and returns the corresponding tile
A “tile” is a 200-pixel-square image of a particular geographic location. To build larger images, a TerraService client must fetch multiple tiles and stitch them together to form a composite. That’s how GetTiledImage generates the 600 x 400 images that it returns. It starts by creating a Bitmap object to represent the image. Then it uses Graphics.DrawImage to draw each tile onto the image. The logic is wholly independent of the image size, so if you’d like to modify CityView to show larger (or smaller) images, find the statement
Bitmap bitmap = GetTiledImage (city, state, res, 600, 400);
in CityView.ashx and change the 600 and 400 to the desired width and height.
TerraService.dll was compiled from TerraService.cs, which I generated with the following command:
wsdl /namespace:TS http://terraservice.net/terraservice.asmx
The namespace was necessary to prevent certain data types defined in TerraService’s WSDL contract from conflicting with data types defined in the .NET Framework Class Library. Once TerraService.cs was created, the command
csc /t:library terraservice.cs
compiled it into a DLL.
F1: more efficient than using String objects which as immutable (cannot be changed without deletion and reallocation of memory)
F2: http handler which is a web service client
F3: uses query string to pass arguments
F4: uses a URL to get the image - image
returned by "CityView.ashx"
example URL
CityView.ashx?city=Redmond&state=WA&scale=8
F5: identifies this class as an HTPP-handler
F6: called each time a request is processed
F7: namespace (used in wsdl command to
generate proxy class) , e.g.
wsdl /namespace:TS http://terraservice.net/terraservice.asmx
F8: saves the bitmap to the outputsteam of the HTTP response
F9: proxy class
F10: function call supported by the terraservice
F11: this web service call actually gets the image
F12: puts the tile image into a drawing canvas