User Tools

Site Tools


map_suite_web_for_webapi_quick_start_guide

Map Suite Quick Start Guide For WebAPI

The Map Suite WebAPI illustrated Quickstart Guide will guide you through the process of creating a sample application and will help you become familiar with Map Suite. This edition of the Quickstart Guide supports Map Suite Web for WebAPI 10.0.0 and higher and will show you how to create a ASP.NET WebAPI application using this product.

If you want to build a Web Forms application using the standard Map Suite Web product, please see the Web Edition Quickstart Guide instead.

Welcome to Map Suite™ WebAPI from ThinkGeo, a full-featured mapping control that makes it easy for any Microsoft .NET developer to add mapping functionality to a Microsoft .NET application quickly and efficiently. Using the intuitive object model, even developers inexperienced in geographic information systems (GIS) can create fully functional maps in minutes.

This guide will help you quickly get started building your own spatially aware applications. Like any new software, there will be some learning along the way.

How do we begin taking advantage of the power of Map Suite? The best way to learn is to make a sample application with it.

Download the Sample

Setting up the Environment

Let's start by creating a new WebAPI application in Visual Studio.NET 2015 IDE named “QuickstartSample” (see Figure 1). Set the Templates to “.NET Framework 4.5” for the project. In next wizard page, select the “Empty” template; this means that your sample project won't have any built-in pages or functionalities.


Figure 1. Creating a new project in Visual Studio.NET 2015 IDE.

Installing ThinkGeo WebApi NuGet packages

To installing Asp.NET WebAPI, please right click “references” > “Manage NuGet packages…”.

Figure 2. Reference NuGet packages.

To build this sample, we need to reference several packages from NuGet manager. There are two options for you.

1. For the beginner of MapSuite 10.0 products, we recommend to use “MapSuiteWebForWebApi-Standard” package. This package is the full featured package for developing GIS application with web forms. Please refer http://wiki.thinkgeo.com/wiki/map_suite_web_for_webapi#standard for detail.

2. For the advanced user of MapSuite 10.0 products and want to include the least set of reference, we recommend to use “MapSuiteWebForWebApi-BareBone” package. It only depends on required packages that a basic web forms application needs. Please refer http://wiki.thinkgeo.com/wiki/map_suite_web_for_webapi#barebone for detail.

In this sample, we choose an advanced way. To build this sample, we are going to reference the “MapSuiteWebForWebApi-Standard” package. \\Now that we open NuGet dialog and install the three Nuget packages (See Figure 3).



Figure 3. Install NuGet package.

Now the package is installing into the project. Click “OK” if the message box like the following pops up.

The “NetTopologySuite” is the third part assembly, so the license acceptance is required. You can click “I Accept” to agree the license.


Map Suite WebAPI Quickstart Sample

In this section, we'll use Map Suite Web for WebApi to display a map that uses your own data.

To begin, in the Default.htm file, let's enter a few lines of code that will display a simple map. Next, we'll have a look at the data and the important objects we'll use.

Display a Simple map

The first step in creating our “QuickstartSample” application is to add a html file named Default.html and include code that similar to the example below.


Figure 4. Adding Default.html.

<!DOCTYPE html>
<html>
<head>
    <title>Quickstart</title>
    <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
</head>
<body>
    <div id="map" style="height: 800px; width: 1200px"></div>
    <!-- <div>
         <input id="chKAddStates" name="group1" type="radio" value="Show US States" onclick="updateLayer('usstates')" />
         Show US States
     <br />
         <input id="chKAddCites" name="group1" type="radio" value="Show US Counties" onclick="updateLayer('uscities')" />
         Show US Cities
     <br />
     </div>-->
</body>
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<script>
    var map = L.map('map', { zoomAnimation: false }).setView([39.6948, -96.8150], 4);
 
    // add thinkgeo map
    L.tileLayer.wms('http://{s}.thinkgeo.com/CachedWMSServer/WmsServer.axd', {
        subdomains: ['worldmapkit1', 'worldmapkit2', 'worldmapkit3', 'worldmapkit4', 'worldmapkit5', 'worldmapkit6'],
        layers: 'OSMWorldMapKitLayer',
        format: 'image/png',
        styles: 'WorldMapKitDefaultStyle',
        version: '1.1.1',
        attribution: '<a href="http://thinkgeo.com/map-suite-developer-gis/world-map-kit-sdk/">ThinkGeo</a> | &copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors '
    }).addTo(map);
 
    var worldLayer = L.tileLayer('/Quickstart/Tile//{z}/{x}/{y}').addTo(map);
 
    //function updateLayer(layerId) {
    //    worldLayer.setUrl('/Quickstart/Tile/' + layerId + '/{z}/{x}/{y}');
    //    worldLayer.redraw();
    //}
</script>
</html>

Now press F5 to build and run your application. It should look like figure 5:


Figure 5. The basic map display.

Map Suite WebAPI "Quickstart"

Now let's look at the code needed to bring this concept to fruition.

Our next step is to add our ShapeFile layers to the map. For this example, we'll use a ShapeFile containing worldwide country borders. We have one such ShapeFile available to us:

  • Worldwide country borders (cntry02.shp)

(NOTE: The data used in this sample can be found in the attached sample above in the “\App_Data” folder.)

Let's add a controller named “HomeController”, like this:

Figure 6. Adding the "HomeController".

Figure 6. Adding the “HomeController”.

Then add the following code to HomeController:

using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web;
using System.Web.Http;
using ThinkGeo.MapSuite;
using ThinkGeo.MapSuite.Drawing;
using ThinkGeo.MapSuite.Layers;
using ThinkGeo.MapSuite.Shapes;
using ThinkGeo.MapSuite.Styles;
using ThinkGeo.MapSuite.WebApi;
 
namespace QuickstartSample.Controllers
{
    [RoutePrefix("Quickstart")]
    public class HomeController : ApiController
    {
        [Route("tile/{z}/{x}/{y}")]
        [HttpGet]
        public HttpResponseMessage GetTile(int z, int x, int y)
        {
            // We create a new Layer and pass the path to a Shapefile into its constructor.
            ShapeFileFeatureLayer worldLayer = new ShapeFileFeatureLayer(HttpContext.Current.Server.MapPath(@"~/App_Data/cntry02.shp"));
            Proj4Projection proj4 = new Proj4Projection();
            proj4.InternalProjectionParametersString = Proj4Projection.GetWgs84ParametersString();
            proj4.ExternalProjectionParametersString = Proj4Projection.GetSphericalMercatorParametersString();
            proj4.Open();
 
            worldLayer.FeatureSource.Projection = proj4;
            AreaStyle areaStyle = new AreaStyle();
            areaStyle.FillSolidBrush = new GeoSolidBrush(GeoColor.FromArgb(255, 233, 232, 214));
            areaStyle.OutlinePen = new GeoPen(GeoColor.FromArgb(255, 118, 138, 69), 1);
            areaStyle.OutlinePen.DashStyle = LineDashStyle.Solid;
 
            // Set the worldLayer to use a preset Style. Since AreaStyles.Country1 has YellowGreen background and Black border, our worldLayer will have the same render style. 
            worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = areaStyle;
 
            // This setting will apply from ZoomLevel01 to ZoomLevel20, which means we can see the world the same style all the time no matter how far we zoom in or out.
            worldLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
 
 
            // Change the number below (to 0, for example) and you will be able to see what we mean.
 
            LayerOverlay layerOverlay = new LayerOverlay();
            layerOverlay.Layers.Add(worldLayer);
 
 
            using (Bitmap bitmap = new Bitmap(256, 256))
            {
                PlatformGeoCanvas geoCanvas = new PlatformGeoCanvas();
                RectangleShape boundingBox = WebApiExtentHelper.GetBoundingBoxForXyz(x, y, z, GeographyUnit.Meter);
                geoCanvas.BeginDrawing(bitmap, boundingBox, GeographyUnit.Meter);
                layerOverlay.Draw(geoCanvas);
                geoCanvas.EndDrawing();
 
                MemoryStream ms = new MemoryStream();
                bitmap.Save(ms, ImageFormat.Png);
 
                HttpResponseMessage msg = new HttpResponseMessage(HttpStatusCode.OK);
                msg.Content = new ByteArrayContent(ms.ToArray());
                msg.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
 
                return msg;
            }
        }
    }
}

So what has occurred here? We've created a layer and added it to the map and the map has rendered it according to its default style parameters. We've also used ZoomLevel to display the map the way that we want.

NOTE: It is important that the “MapUnit” property of a map object be set using the “GeographyUnit” enumeration. This is because the coordinates stored in a ShapeFile can be in DecimalDegrees (a format of latitude and longitude), feet, meters, or another unit system. Our map has no way to know what the ShapeFile's unit of measurement is until we set it. This information is normally found somewhere in the ShapeFile's documentation (also referred to as its metadata), or within the supplemental data file as discussed in the section on ShapeFiles. It may also come as a separate .txt, .xml, or .html file that begins with the same file name as the main ShapeFile.

The attributes [RoutePrefix(“Quickstart”)] and [Route(“tile/{z}/{x}/{y}”)] are for custom route, we can easily access it by '/Quickstart/tile/{z}/{x}/{y}'. To make it work, we need to modify the WebApiConfig.cs, like this:

public static void Register(HttpConfiguration config)
{
     // Web API routes
     config.MapHttpAttributeRoutes();
 
     config.Routes.MapHttpRoute(
       name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
       defaults: new { id = RouteParameter.Optional }
     );
 
     config.EnsureInitialized();
}

Now that the server side is ready, let's support it adding the following code to the client side:

L.tileLayer('/Quickstart/Tile/{z}/{x}/{y}').addTo(map);

After adding, it will look like as following:

<script>
    var map = L.map('map', { zoomAnimation: false }).setView([39.6948, -96.8150], 4);
 
    // add thinkgeo map
    L.tileLayer.wms('http://{s}.thinkgeo.com/CachedWMSServer/WmsServer.axd', {
        subdomains: ['worldmapkit1', 'worldmapkit2', 'worldmapkit3', 'worldmapkit4', 'worldmapkit5', 'worldmapkit6'],
        layers: 'OSMWorldMapKitLayer',
        format: 'image/png',
        styles: 'WorldMapKitDefaultStyle',
        version: '1.1.1',
        attribution: '<a href="http://thinkgeo.com/map-suite-developer-gis/world-map-kit-sdk/">ThinkGeo</a> | &copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors '
    }).addTo(map);
 
    L.tileLayer('/Quickstart/Tile/{z}/{x}/{y}').addTo(map);
</script>

If you compile and run what you have now, your map should look like the screenshot below. (See Figure 7).


Figure 7. A sample map of the world.

With the above code, you can both display a map and navigate it. You can pan by dragging the map, zoom in by double-clicking,​ track zoom in by drawing a rectangle with your left mouse button mouse while holding the shift key, or zoom in and out by using the mouse wheel. Very powerful for just couple lines of code, isn't it?

That was an easy start! Now let's add a second ShapeFile to the sample, so we'll have a total of two layers:

  1. World country borders (“cntry02.shp”)
  2. World capitals (“capital.shp”)

Change the code in server side to correspond with the following example. You don't need to make any changes to client side.

[Route("tile/{z}/{x}/{y}")]
[HttpGet]
public HttpResponseMessage GetTile(int z, int x, int y)
{
    // We create a new Layer and pass the path to a ShapeFile into its constructor.
    ShapeFileFeatureLayer worldLayer = new ShapeFileFeatureLayer(HttpContext.Current.Server.MapPath(@"~/App_Data/cntry02.shp"));
    Proj4Projection proj4 = new Proj4Projection();
    proj4.InternalProjectionParametersString = Proj4Projection.GetWgs84ParametersString();
    proj4.ExternalProjectionParametersString = Proj4Projection.GetSphericalMercatorParametersString();
    proj4.Open();
 
    worldLayer.FeatureSource.Projection = proj4;
 
    // Set the worldLayer to use a preset style. Since AreaStyles.Country1 has a YellowGreen background and Black border, our worldLayer will have the   
    //same render style. 
    AreaStyle areaStyle = new AreaStyle();
    areaStyle.FillSolidBrush = new GeoSolidBrush(GeoColor.FromArgb(255, 233, 232, 214));
    areaStyle.OutlinePen = new GeoPen(GeoColor.FromArgb(255, 118, 138, 69), 1);
    areaStyle.OutlinePen.DashStyle = LineDashStyle.Solid;
    worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = areaStyle;
 
    // This setting will apply to all zoom levels from ZoomLevel01 through ZoomLevel20, so the same style will be rendered no matter how far we zoom in or out.
    worldLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
 
    // Capital layer
    ShapeFileFeatureLayer capitalLayer = new ShapeFileFeatureLayer(HttpContext.Current.Server.MapPath("~/App_Data/capital.shp"));
    capitalLayer.FeatureSource.Projection = proj4;
    PointStyle pointStyle = new PointStyle();
    pointStyle.SymbolType = PointSymbolType.Square;
    pointStyle.SymbolSolidBrush = new GeoSolidBrush(GeoColor.StandardColors.White);
    pointStyle.SymbolPen = new GeoPen(GeoColor.StandardColors.Black, 1);
    pointStyle.SymbolSize = 6;
 
    PointStyle stackStyle = new PointStyle();
    stackStyle.SymbolType = PointSymbolType.Square;
    stackStyle.SymbolSolidBrush = new GeoSolidBrush(GeoColor.StandardColors.Maroon);
    stackStyle.SymbolPen = new GeoPen(GeoColor.StandardColors.Transparent, 0);
    stackStyle.SymbolSize = 2;
 
    pointStyle.CustomPointStyles.Add(stackStyle);
    capitalLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = pointStyle;
    capitalLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
 
    LayerOverlay layerOverlay = new LayerOverlay();
    layerOverlay.Layers.Add(worldLayer);
    layerOverlay.Layers.Add(capitalLayer);
 
    using (Bitmap bitmap = new Bitmap(256, 256))
    {
        PlatformGeoCanvas geoCanvas = new PlatformGeoCanvas();
        RectangleShape boundingBox = WebApiExtentHelper.GetBoundingBoxForXyz(x, y, z, GeographyUnit.Meter);
        geoCanvas.BeginDrawing(bitmap, boundingBox, GeographyUnit.Meter);
        layerOverlay.Draw(geoCanvas);
        geoCanvas.EndDrawing();
 
        MemoryStream ms = new MemoryStream();
        bitmap.Save(ms, ImageFormat.Png);
 
        HttpResponseMessage msg = new HttpResponseMessage(HttpStatusCode.OK);
        msg.Content = new ByteArrayContent(ms.ToArray());
        msg.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
 
        return msg;
    }
}

The result is as follows (Figure 8):


Figure 8. A basic map of the Americas with the additional borders and capitals layers displayed.

How to Use TextStyle

A TextStyle ​is used to label items on map. As every ShapeFile ​has a relative .dbf file that includes descriptions for every record, the most common way to use TextStyles is for labeling. For example, Capital ShapeFile'​s corresponding .dbf file contains the field “​CITY_NAME”​. We can use this field to label the cities on our map.


Figure 9. Attribute data from the .dbf file.

Map Suite includes several built-in TextStyles to help us quickly apply attractive city labels. We can simply pick the TextStyle we like and use it.

[Route("tile/{z}/{x}/{y}")]
[HttpGet]
public HttpResponseMessage GetTile(int z, int x, int y)
{
    // We create a new Layer and pass the path to a Shapefile into its constructor.
    ShapeFileFeatureLayer worldLayer = new ShapeFileFeatureLayer(HttpContext.Current.Server.MapPath(@"~/App_Data/cntry02.shp"));
    Proj4Projection proj4 = new Proj4Projection();
    proj4.InternalProjectionParametersString = Proj4Projection.GetWgs84ParametersString();
    proj4.ExternalProjectionParametersString = Proj4Projection.GetSphericalMercatorParametersString();
    proj4.Open();
 
    worldLayer.FeatureSource.Projection = proj4;
    AreaStyle areaStyle = new AreaStyle();
    areaStyle.FillSolidBrush = new GeoSolidBrush(GeoColor.FromArgb(255, 233, 232, 214));
    areaStyle.OutlinePen = new GeoPen(GeoColor.FromArgb(255, 118, 138, 69), 1);
    areaStyle.OutlinePen.DashStyle = LineDashStyle.Solid;
 
 
    // Set the worldLayer to use a preset Style. Since AreaStyles.Country1 has YellowGreen background and Black border, our worldLayer will have the same render style. 
    worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = areaStyle;
 
    // This setting will apply from ZoomLevel01 to ZoomLevel20, which means we can see the world the same style all the time no matter how far we zoom in or out.
    worldLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
 
    // Capital layer
    ShapeFileFeatureLayer capitalLayer = new ShapeFileFeatureLayer(HttpContext.Current.Server.MapPath("~/App_Data/capital.shp"));
    capitalLayer.FeatureSource.Projection = proj4;
    // We can customize our own Style. Here we pass in a color and a size.
    capitalLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimpleCircleStyle(GeoColor.StandardColors.White, 7, GeoColor.StandardColors.Brown);
    // The Style we set here is applied from ZoomLevel01 to ZoomLevel05. That means if we zoom in a bit more, this particular style will not be visible anymore.
    capitalLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level05;
 
    PointStyle pointStyle = new PointStyle();
    pointStyle.SymbolType = PointSymbolType.Square;
    pointStyle.SymbolSolidBrush = new GeoSolidBrush(GeoColor.StandardColors.White);
    pointStyle.SymbolPen = new GeoPen(GeoColor.StandardColors.Black, 1);
    pointStyle.SymbolSize = 6;
 
    PointStyle stackStyle = new PointStyle();
    stackStyle.SymbolType = PointSymbolType.Square;
    stackStyle.SymbolSolidBrush = new GeoSolidBrush(GeoColor.StandardColors.Maroon);
    stackStyle.SymbolPen = new GeoPen(GeoColor.StandardColors.Transparent, 0);
    stackStyle.SymbolSize = 2;
 
    pointStyle.CustomPointStyles.Add(stackStyle);
 
    capitalLayer.ZoomLevelSet.ZoomLevel06.DefaultPointStyle = pointStyle;
    // The Style we set here is applied from ZoomLevel06 to ZoomLevel20. That means if we zoom out a bit more, this particular style will not be visible anymore.
    capitalLayer.ZoomLevelSet.ZoomLevel06.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
 
    // Label layer
    ShapeFileFeatureLayer capitalLabelLayer = new ShapeFileFeatureLayer(HttpContext.Current.Server.MapPath("~/App_Data/capital.shp"));
    capitalLabelLayer.FeatureSource.Projection = proj4;
    // We can customize our own TextStyle. Here we pass in the font, the size, the style and the color.
    capitalLabelLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.CreateSimpleTextStyle("CITY_NAME", "Arial", 8, DrawingFontStyles.Italic, GeoColor.StandardColors.Black, 3, 3);
    // The TextStyle we set here is applied from ZoomLevel01 to ZoomLevel05. 
    capitalLabelLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level05;
    GeoFont font = new GeoFont("Arial", 9, DrawingFontStyles.Bold);
    GeoSolidBrush txtBrush = new GeoSolidBrush(GeoColor.StandardColors.Maroon);
    TextStyle textStyle = new TextStyle("CITY_NAME", font, txtBrush);
    textStyle.XOffsetInPixel = 0;
    textStyle.YOffsetInPixel = -6;
 
    capitalLabelLayer.ZoomLevelSet.ZoomLevel06.DefaultTextStyle = textStyle;
    // The TextStyle we set here is applied from ZoomLevel06 to ZoomLevel20.
    capitalLabelLayer.ZoomLevelSet.ZoomLevel06.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
    // Change the number below (to 0, for example) and you will be able to see what we mean.
 
    LayerOverlay layerOverlay = new LayerOverlay();
    layerOverlay.Layers.Add(worldLayer);
    layerOverlay.Layers.Add(capitalLayer);
    layerOverlay.Layers.Add(capitalLabelLayer);
 
    using (Bitmap bitmap = new Bitmap(256, 256))
    {
        PlatformGeoCanvas geoCanvas = new PlatformGeoCanvas();
        RectangleShape boundingBox = WebApiExtentHelper.GetBoundingBoxForXyz(x, y, z, GeographyUnit.Meter);
        geoCanvas.BeginDrawing(bitmap, boundingBox, GeographyUnit.Meter);
        layerOverlay.Draw(geoCanvas);
        geoCanvas.EndDrawing();
 
        MemoryStream ms = new MemoryStream();
        bitmap.Save(ms, ImageFormat.Png);
 
        HttpResponseMessage msg = new HttpResponseMessage(HttpStatusCode.OK);
        msg.Content = new ByteArrayContent(ms.ToArray());
        msg.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
 
        return msg;
    }
}

The result is as follows (Figure 10):


Figure 10. Map of the Americas with a TextStyle applied.

Now that we know how to render text and symbols, let's create customized Styles and TextStyles. We'll also specify different ranges of ZoomLevels, and apply varying customized Styles and TextStyles to the same layer at different ZoomLevel ranges.

[Route("tile/{z}/{x}/{y}")]
[HttpGet]
public HttpResponseMessage GetTile(int z, int x, int y)
{
    // Create a new Layer and pass the path to a Shapefile into its constructor.
    ShapeFileFeatureLayer worldLayer = new ShapeFileFeatureLayer(HttpContext.Current.Server.MapPath(@"~/App_Data/cntry02.shp"));
    Proj4Projection proj4 = new Proj4Projection();
    proj4.InternalProjectionParametersString = Proj4Projection.GetWgs84ParametersString();
    proj4.ExternalProjectionParametersString = Proj4Projection.GetSphericalMercatorParametersString();
    proj4.Open();
 
    worldLayer.FeatureSource.Projection = proj4;
 
    // Set the worldLayer to use a preset Style. Since AreaStyles.Country1 has a YellowGreen background and Black border, our worldLayer will have the same render style. 
    AreaStyle areaStyle = new AreaStyle();
    areaStyle.FillSolidBrush = new GeoSolidBrush(GeoColor.FromArgb(255, 233, 232, 214));
    areaStyle.OutlinePen = new GeoPen(GeoColor.FromArgb(255, 118, 138, 69), 1);
    areaStyle.OutlinePen.DashStyle = LineDashStyle.Solid;
    worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = areaStyle;
 
    // This setting will apply from ZoomLevel01 to ZoomLevel20, which means the map will be rendered in the same style, no matter how far we zoom in or out. 
    worldLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
 
    // Capital layer
    ShapeFileFeatureLayer capitalLayer = new ShapeFileFeatureLayer(HttpContext.Current.Server.MapPath("~/App_Data/capital.shp"));
    capitalLayer.FeatureSource.Projection = proj4;
    // We can customize our own Style. Here we pass in a color and a size.
    capitalLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimpleCircleStyle(GeoColor.StandardColors.White, 7, GeoColor.StandardColors.Brown);
    // The Style we set here is applied from ZoomLevel01 to ZoomLevel05. That means if we zoom in a bit more, this particular style will no longer be visible.
    capitalLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level05;
    PointStyle pointStyle = new PointStyle();
    pointStyle.SymbolType = PointSymbolType.Square;
    pointStyle.SymbolSolidBrush = new GeoSolidBrush(GeoColor.StandardColors.White);
    pointStyle.SymbolPen = new GeoPen(GeoColor.StandardColors.Black, 1);
    pointStyle.SymbolSize = 6;
 
    PointStyle stackStyle = new PointStyle();
    stackStyle.SymbolType = PointSymbolType.Square;
    stackStyle.SymbolSolidBrush = new GeoSolidBrush(GeoColor.StandardColors.Maroon);
    stackStyle.SymbolPen = new GeoPen(GeoColor.StandardColors.Transparent, 0);
    stackStyle.SymbolSize = 2;
 
    pointStyle.CustomPointStyles.Add(stackStyle);
 
 
    capitalLayer.ZoomLevelSet.ZoomLevel06.DefaultPointStyle = pointStyle;
    // The Style we set here is applied from ZoomLevel06 to ZoomLevel20. That means if we zoom out a bit more, this particular style will no longer be visible.
    capitalLayer.ZoomLevelSet.ZoomLevel06.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
 
    // Label layer
    ShapeFileFeatureLayer capitalLabelLayer = new ShapeFileFeatureLayer(HttpContext.Current.Server.MapPath("~/App_Data/capital.shp"));
    capitalLabelLayer.FeatureSource.Projection = proj4;
    // We can customize our own TextStyle. Here we pass in the font, the size, the style and the color.
    capitalLabelLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.CreateSimpleTextStyle("CITY_NAME", "Arial", 8, DrawingFontStyles.Italic, GeoColor.StandardColors.Black, 3, 3);
    // The TextStyle we set here is applied from ZoomLevel01 to ZoomLevel05. 
    capitalLabelLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level05;
 
    GeoFont font = new GeoFont("Arial", 9, DrawingFontStyles.Bold);
    GeoSolidBrush txtBrush = new GeoSolidBrush(GeoColor.StandardColors.Maroon);
    TextStyle textStyle = new TextStyle("CITY_NAME", font, txtBrush);
    textStyle.XOffsetInPixel = 0;
    textStyle.YOffsetInPixel = -6;
    capitalLabelLayer.ZoomLevelSet.ZoomLevel06.DefaultTextStyle = textStyle;
    // The TextStyle we set here is applied from ZoomLevel06 to ZoomLevel20.
    capitalLabelLayer.ZoomLevelSet.ZoomLevel06.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
    // Change the number below (to 0, for example) to better understand how this works.
 
    LayerOverlay layerOverlay = new LayerOverlay();
    layerOverlay.Layers.Add(worldLayer);
    layerOverlay.Layers.Add(capitalLayer);
    layerOverlay.Layers.Add(capitalLabelLayer);
 
    using (Bitmap bitmap = new Bitmap(256, 256))
    {
        PlatformGeoCanvas geoCanvas = new PlatformGeoCanvas();
        RectangleShape boundingBox = WebApiExtentHelper.GetBoundingBoxForXyz(x, y, z, GeographyUnit.Meter);
        geoCanvas.BeginDrawing(bitmap, boundingBox, GeographyUnit.Meter);
        layerOverlay.Draw(geoCanvas);
        geoCanvas.EndDrawing();
 
        MemoryStream ms = new MemoryStream();
        bitmap.Save(ms, ImageFormat.Png);
 
        HttpResponseMessage msg = new HttpResponseMessage(HttpStatusCode.OK);
        msg.Content = new ByteArrayContent(ms.ToArray());
        msg.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
 
        return msg;
    }
}

Can you imagine what the map will look like now? Figure 11 below is the result. At first it looks the same as it did in Figure 10. Now zoom in, and watch the map change to resemble Figure 12.


Figure 11. A map of European cities with two ZoomLevels, before zooming in.


Figure 12. The same map with two ZoomLevels, after zooming in.

Perform an AJAX HTTP request to the Action of the Controller

Map Suite WebAPI Edition provides a large number of client APIs that allow us to easily operate the map on client side, just as we've done on the server side in the above sample code.

Here we'll show you how to perform an AJAX request to update the layers of the map according to the different parameters passed in from the client.

We will need to access the parameters passed from here in the action.

The code in your client side should look like this:

<!DOCTYPE html>
<html>
<head>
    <title>Quickstart</title>
    <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
</head>
<body>
    <div id="map" style="height: 800px; width: 1200px"></div>
     <div>
         <input id="chKAddStates" name="group1" type="radio" value="Show US States" onclick="updateLayer('usstates')" />
         Show US States
     <br />
         <input id="chKAddCites" name="group1" type="radio" value="Show US Counties" onclick="updateLayer('uscities')" />
         Show US Cities
     <br />
     </div>
</body>
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<script>
    var map = L.map('map', { zoomAnimation: false }).setView([39.6948, -96.8150], 4);
 
    // add thinkgeo map
    L.tileLayer.wms('http://{s}.thinkgeo.com/CachedWMSServer/WmsServer.axd', {
        subdomains: ['worldmapkit1', 'worldmapkit2', 'worldmapkit3', 'worldmapkit4', 'worldmapkit5', 'worldmapkit6'],
        layers: 'OSMWorldMapKitLayer',
        format: 'image/png',
        styles: 'WorldMapKitDefaultStyle',
        version: '1.1.1',
        attribution: '<a href="http://thinkgeo.com/map-suite-developer-gis/world-map-kit-sdk/">ThinkGeo</a> | &copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors '
    }).addTo(map);
 
    var worldLayer = L.tileLayer('/Quickstart/Tile//{z}/{x}/{y}').addTo(map);
 
    function updateLayer(layerId) {
        worldLayer.setUrl('/Quickstart/Tile/' + layerId + '/{z}/{x}/{y}');
        worldLayer.redraw();
    }
</script>
</html>

Now copy and paste the code below about the accessed action into your “HomeController” page:

[Route("tile/{layerId}/{z}/{x}/{y}")]
[HttpGet]
public HttpResponseMessage GetTile(string layerId, int z, int x, int y)
{
    Proj4Projection proj4 = new Proj4Projection();
    proj4.InternalProjectionParametersString = Proj4Projection.GetWgs84ParametersString();
    proj4.ExternalProjectionParametersString = Proj4Projection.GetSphericalMercatorParametersString();
    proj4.Open();
 
    LayerOverlay layerOverlay = new LayerOverlay();
 
    if (layerId.ToLowerInvariant() == "usstates")
    {
        // States layer
        ShapeFileFeatureLayer statesLayer = new ShapeFileFeatureLayer(HttpContext.Current.Server.MapPath("~/App_Data/USStates.shp"));
        statesLayer.FeatureSource.Projection = proj4;
        AreaStyle areaStyle = new AreaStyle();
        areaStyle.FillSolidBrush = new GeoSolidBrush(GeoColor.FromArgb(255, 233, 232, 214));
        areaStyle.OutlinePen = new GeoPen(GeoColor.FromArgb(255, 118, 138, 69), 1);
        areaStyle.OutlinePen.DashStyle = LineDashStyle.Solid;
 
        statesLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = areaStyle;
        statesLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
 
        layerOverlay.Layers.Add(statesLayer);
    }
    else if (layerId.ToLowerInvariant() == "uscities")
    {
        // Cities layer
        ShapeFileFeatureLayer countyLayer = new ShapeFileFeatureLayer(HttpContext.Current.Server.MapPath("~/App_Data/cities_a.shp"));
        countyLayer.FeatureSource.Projection = proj4;
        PointStyle pointStyle = new PointStyle();
        pointStyle.SymbolType = PointSymbolType.Square;
        pointStyle.SymbolSolidBrush = new GeoSolidBrush(GeoColor.StandardColors.White);
        pointStyle.SymbolPen = new GeoPen(GeoColor.StandardColors.Black, 1);
        pointStyle.SymbolSize = 6;
 
        PointStyle stackStyle = new PointStyle();
        stackStyle.SymbolType = PointSymbolType.Square;
        stackStyle.SymbolSolidBrush = new GeoSolidBrush(GeoColor.StandardColors.Maroon);
        stackStyle.SymbolPen = new GeoPen(GeoColor.StandardColors.Transparent, 0);
        stackStyle.SymbolSize = 2;
 
        pointStyle.CustomPointStyles.Add(stackStyle);
        countyLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = pointStyle;
        GeoFont font = new GeoFont("Arial", 9, DrawingFontStyles.Bold);
        GeoSolidBrush txtBrush = new GeoSolidBrush(GeoColor.StandardColors.Maroon);
        TextStyle textStyle = new TextStyle("AREANAME", font, txtBrush);
        textStyle.XOffsetInPixel = 0;
        textStyle.YOffsetInPixel = -6;
        countyLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = textStyle;
        countyLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
        layerOverlay.Layers.Add(countyLayer);
    }
 
    using (Bitmap bitmap = new Bitmap(256, 256))
    {
        PlatformGeoCanvas geoCanvas = new PlatformGeoCanvas();
        RectangleShape boundingBox = WebApiExtentHelper.GetBoundingBoxForXyz(x, y, z, GeographyUnit.Meter);
        geoCanvas.BeginDrawing(bitmap, boundingBox, GeographyUnit.Meter);
        layerOverlay.Draw(geoCanvas);
        geoCanvas.EndDrawing();
 
        MemoryStream ms = new MemoryStream();
        bitmap.Save(ms, ImageFormat.Png);
 
        HttpResponseMessage msg = new HttpResponseMessage(HttpStatusCode.OK);
        msg.Content = new ByteArrayContent(ms.ToArray());
        msg.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
 
        return msg;
    }
}

If we compile and run the application now, it should look like the screenshot below:


Figure 13. Note the client side layer display control that now appears below the map.

You can click the check boxes for “Show US States” or “Show US Cities” to load different layers to the map. For example, if you check the “Show US States” box, the map should look like this:


Figure 14. Map with states layer shown.

if you check the “Show US Cities” box, the map should look like this:


Figure 15. Map with cities layer shown.

This completes ​this scenario. The next thing you might want to do is to make it run on another machine ​that does not have a developer license. ​A runtime ​license is the one we are looking for. Here is the guide to generate a runtime license: http://wiki.thinkgeo.com/wiki/map_suite_deployment_license_guide_for_web.

Summary


You now know the basics of using Map Suite WebAPI and can start adding this functionality to your own applications. Let's recap what we've learned about the object relationships and how the pieces of Map Suite work together:

  1. It is of the utmost importance that the units (feet, meters, decimal degrees, etc.) be set properly for the Map control, based on the requirements of your data.
  2. Shapefiles provide the data used by a Map control to render a map.
  3. A Layer can have one-to-many ZoomLevels. ZoomLevels help to define ranges (upper and lower scales) of when a Layer should be shown or hidden.
map_suite_web_for_webapi_quick_start_guide.txt · Last modified: 2017/03/15 07:15 by tgwikiupdate