Thinking in GIS

a blog about GIS from a urban geogeek living at the countryside

Feed, Categories, Archives


Implementing the C# mapscript code (c# mapscript tutorial, part 5)

Posted: July 26, 2006
Categories: GIS, .NET, PostGIS, devs, MapServer, Tutorials
Feedback: View Comments

Add reference to mapscript

Add the reference to mapscript_csharp.dll (browse to the mapscrip installation folder, for example C:ms4wApachecgi-binmapscriptcsharp):

{{:MapServer:tutorial:add_reference.jpg|:mapserver:tutorial:add_reference.jpg}}

Remember that if you didn't set PATH environment variable to the MapServer dlls you will need to manually copy them under the bin folder of this ASP .NET application.

The c# code for Default.aspx page

This is the complete code to add for the Default.aspx page:

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Data.OleDb; //for dbf connection
using System.IO; //for copying the point shapefile

namespace TutorialMapServer
{
    /// 
    /// User Interface for c# MapServer Tutorial
    /// 
    public class _Default : System.Web.UI.Page
    {
        protected System.Web.UI.WebControls.Literal litIdentifyResult;
        protected System.Web.UI.WebControls.DropDownList ddlLayers;
        protected System.Web.UI.WebControls.Button butFullExtent;
        protected System.Web.UI.WebControls.RadioButtonList rblGisTools;
        protected System.Web.UI.WebControls.ImageButton ibMap;
        protected System.Web.UI.WebControls.Button butRefresh;
        protected System.Web.UI.WebControls.CheckBoxList cblLayers;
        protected System.Web.UI.WebControls.Label lblInfo;
        protected System.Web.UI.WebControls.TextBox txtUser;
        protected System.Web.UI.WebControls.Button butClear;
        //private variable for this class
        mapObj map;

/// 
        /// Page Load of Tutorial User Interface
        /// 
        /// 
        /// 
        private void Page_Load(object sender, System.EventArgs e)
        {
            if(!Page.IsPostBack) //First access to the map
            {
                //send image stream from MapServer to ibMap
                ibMap.ImageUrl = "MapStream.aspx?ACTION=INITMAP";
                //initialize controls
                mapObj map = new mapObj(System.Configuration.ConfigurationSettings.AppSettings["mapFilePath"].ToString());
                //iterate the map layer to populate ddlLayer and cblLayer
                for(int i=0;i
        /// Click Event on the Map button control
        /// 
        /// 
        /// 
        private void ibMap_Click(object sender, System.Web.UI.ImageClickEventArgs e)
        {
            lblInfo.Text = "";
            String Action = "";
            String activeLayer=ddlLayers.SelectedItem.Text;
            //we have to check what GIS tool is needed
            switch(rblGisTools.SelectedItem.Text.ToUpper())
            {
                case "ZOOM IN":
                    Action = "ZOOMIN";
                    break;
                case "ZOOM OUT":
                    Action = "ZOOMOUT";
                    break;
                case "IDENTIFY":
                    Action = "IDENTIFY";
                    break;
                case "ADD POINT":
                    Action = "ADDPOINT";
                    break;
            }
            //For Identify let's call DoIdentify
            if(Action.Equals("IDENTIFY"))
            {
                DoIdentify(e.X,e.Y,activeLayer);
            }
            //For Add Point let's call AddPoint
            if(Action.Equals("ADDPOINT"))
            {
                String[,] fieldValues = new String[2,2];
                fieldValues[0,0]="POI_USER";
                fieldValues[0,1]=   txtUser.Text;
                fieldValues[1,0]="POI_TIME";
                fieldValues[1,1]= DateTime.Now.ToShortDateString() + ", " + System.DateTime.Now.ToLongTimeString();
                AddPoint(e.X,e.Y,activeLayer,fieldValues);
            }
            //Stream map image to ibMap according to the needed GIS Action
            ibMap.ImageUrl = "MapStream.aspx?ACTION=" + Action + "&X;=" + e.X + "&Y;=" + e.Y + "&ACTIVELAYER;=" + activeLayer;
        }

/// 
        /// Create a full Extent Map
        /// 
        /// 
        /// 
        private void butFullExtent_Click(object sender, System.EventArgs e)
        {
            ibMap.ImageUrl = "MapStream.aspx?ACTION=FULLEXTENT";
        }

/// 
        /// Add a point feature to point shapefile with an array of values for dbf
        /// 
        /// 
        /// 
        /// 
        /// 
        private void AddPoint(Double x, Double y, String activeLayer, String[,] fieldValues)
        {
            //check: this action is valid only for point shapefiles
            pointObj point = pixel2point(new pointObj(x,y,0,0)); //conver the image point in map point
            String shapeFullPath = map.shapepath + "\\" + activeLayer + ".shp";
            shapefileObj shapefile = new shapefileObj(shapeFullPath,-2);
            if(shapefile.type!=(int)mapscript.MS_SHAPEFILE_POINT)
            {
                //notify action
                lblInfo.Text = "This action can be performed only on point shapefiles.";
            }
            else
            {
                /*Alternative way to insert a point in the shapefile using shapeObj:
                //create line to store the point
                lineObj line = new lineObj();
                line.add(point);
                //create shape
                shapeObj shape = new shapeObj((int)MS_SHAPE_TYPE.MS_SHAPE_POINT);
                shape.add(line);
                //add shape to shapefile
                shapefile.add(shape);
                */
                shapefile.addPoint(point);
                //add record for dbf table
                OleDbConnection cn = new OleDbConnection(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + map.shapepath + ";Extended Properties=dBASE IV;User ID=Admin;Password=");
                cn.Open();
                OleDbCommand com = cn.CreateCommand();
                //get field list and value list to use in the query on dbf
                String fieldList = "";
                String valueList = "";
                for(int i=0; i<(fieldValues.Length/2); i++)
                {
                    fieldList = fieldList + fieldValues[i,0];
                    valueList = valueList + "'" + fieldValues[i,1] + "'";
                    if(i<((fieldValues.Length/2)-1))
                    {
                        fieldList = fieldList + ", ";
                        valueList = valueList + ", ";
                    }
                }
                com.CommandText = "INSERT INTO " + activeLayer + " (" + fieldList + ") VALUES(" + valueList + ")";
                com.CommandType = CommandType.Text;
                com.ExecuteNonQuery();
                cn.Close();
                //notify action
                lblInfo.Text = "Point added (" + (shapefile.numshapes + 1) + " features in shapefile).";
            }
            shapefile.Dispose();
        }

/// 
        /// Let's do identify
        /// 
        /// x image coordinate for the point to identify
        /// y image coordinate for the point to identify
        /// layer to identify
        private void DoIdentify(Double x, Double y, String activeLayer)
        {
            litIdentifyResult.Text = "";
            //identify
            layerObj layer = map.getLayerByName(activeLayer);
            if(layer!=null)
            {
                layer.template = "dummy"; //for historical reasons
                pointObj point = pixel2point(new pointObj(x,y,0,0)); //conver the image point in map point
                double tolerance = map.width/100; //we use this tolerance
                if(layer.queryByPoint(map, point, mapscript.MS_SINGLE, tolerance)==(int)MS_RETURN_VALUE.MS_SUCCESS)
                {
                    //there is a feature to identify
                    resultCacheObj result = layer.getResults();
                    if(result.numresults>0)
                    {
                        int shapeInd = result.getResult(0).shapeindex;
                        //int tileInd = result.getResult(0).tileindex;
                        layer.open();
                        shapeObj shape=layer.getFeature(shapeInd, -1);
                        //iterate fields and getting values
                        for(int i=0; i
" + layer.getItem(i) + "=" + shape.getValue(i); } layer.close(); } } else { //there is nothing to identify System.Diagnostics.Debug.WriteLine("Nothing to identify."); } } } /// /// Conver pixel point coordinates to map point coordinates /// /// pixel point (from map Image) /// private pointObj pixel2point(pointObj pointPixel) { rectObj extent = map.extent; double mapWidth = extent.maxx - extent.minx; double mapHeight = extent.maxy - extent.miny; double xperc; double yperc; xperc = pointPixel.x / map.width; yperc = (map.height-pointPixel.y) / map.height; double x=extent.minx + xperc*mapWidth; double y=extent.miny + yperc*mapHeight; pointObj pointMap = new pointObj(x,y,0,0); return pointMap; } /// /// Refresh the map /// /// /// private void butRefresh_Click(object sender, System.EventArgs e) { //iterate layers and check visibility for(int i=0; i /// Restore the original point shapefile (cleared) /// /// /// private void butClear_Click(object sender, System.EventArgs e) { String shapeFullPath = map.shapepath + "\\" + ddlLayers.SelectedItem.Text + ".shp"; layerObj layer = map.getLayerByName(ddlLayers.SelectedItem.Text); if(layer.type!=MS_LAYER_TYPE.MS_LAYER_POINT || layer.connectiontype!=MS_CONNECTION_TYPE.MS_SHAPEFILE) { //notify action lblInfo.Text = "This action can be performed only on point shapefiles."; } else { //Clear the point shapefile by copying its copy //Create a DirectoryInfo object representing the specified directory. DirectoryInfo dir = new DirectoryInfo(map.shapepath); //Get the FileInfo objects for every file that belongs to shapefile in the directory. FileInfo[] files = dir.GetFiles(ddlLayers.SelectedItem.Text + "Copy.*"); for(int i=0; i /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.butRefresh.Click += new System.EventHandler(this.butRefresh_Click); this.ibMap.Click += new System.Web.UI.ImageClickEventHandler(this.ibMap_Click); this.butFullExtent.Click += new System.EventHandler(this.butFullExtent_Click); this.butClear.Click += new System.EventHandler(this.butClear_Click); this.Load += new System.EventHandler(this.Page_Load); } #endregion } }

The c# code for MapStream.aspx page

This is the complete code to add for the MapStream.aspx page:

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.IO;

namespace TutorialMapServer
{
    /// 
    /// MapStream produce an imagestream for the ibMap control at the Default.aspx page
    /// 
    public class MapStream : System.Web.UI.Page
    {
        //private variable for this class
        mapObj map;
        rectObj originalExtent;

/// 
        /// Zoom Mode Enumerator
        /// 
        private enum ZOOMMODE
        {
            ZoomIn = 0,
            ZoomOut = 1
        }

/// 
        /// Do a Map Action and send an image stream
        /// 
        /// 
        /// 
        private void Page_Load(object sender, System.EventArgs e)
        {
            //read map if existing, otherwhise create a new one from map file
            map = (mapObj)Session["MAP"];
            if(map==null)
            {
                map = new mapObj(System.Configuration.ConfigurationSettings.AppSettings["mapFilePath"].ToString());
                originalExtent = new rectObj(map.extent.minx, map.extent.miny, map.extent.maxx, map.extent.maxy, 0);
                Session["ORIGINALEXTENT"]=originalExtent;
            }
            originalExtent = (rectObj)Session["ORIGINALEXTENT"];
            //read x,y
            Double x=0;
            Double y=0;
            if(Request.QueryString["X"]!=null && Request.QueryString["Y"]!=null)
            {
                x = Double.Parse(Request.QueryString["X"].ToString());
                y = Double.Parse(Request.QueryString["Y"].ToString());
            }
            //let's see which action is necessary
            String Action = Request.QueryString["ACTION"].ToString().ToUpper();
            switch(Action)
            {
                case "ZOOMIN":
                    DoZoom(ZOOMMODE.ZoomIn,x,y);
                    break;
                case "ZOOMOUT":
                    DoZoom(ZOOMMODE.ZoomOut,x,y);
                    break;
                case "FULLEXTENT":
                    DoZoomFullExtent();
                    break;
            }
            //refresh
            RefreshMap();
            //store in session
            Session["MAP"]=map;
        }

/// 
        /// Refresh MapServer map and send the image stream to output
        /// 
        private void RefreshMap()
        {
            using(imageObj image = map.draw())
            {
                byte[] img = image.getBytes();
                using (MemoryStream ms = new MemoryStream(img))
                {
                    System.Drawing.Image mapimage = System.Drawing.Image.FromStream(ms);    
                    Bitmap bitmap = (Bitmap)mapimage;
                    bitmap.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
                }               
            }
        }

/// 
        /// Do a zoom in or zoom out
        /// 
        /// zoomin or zoomout
        /// x image coordinate
        /// y image coordinate
        private void DoZoom(ZOOMMODE zoomMode, Double x, Double y)
        {
            //Do Zoom In
            if(zoomMode==ZOOMMODE.ZoomIn)
            {
                map.zoomPoint(2, new pointObj(x,y,0,0), map.width, map.height, map.extent, null);
            }
            //Do Zoom Out
            if(zoomMode==ZOOMMODE.ZoomOut)
            {
                map.zoomPoint(-2, new pointObj(x,y,0,0), map.width, map.height, map.extent, null);
            }
        }

/// 
        /// Do a Full Extent (return to Origina Extent)
        /// 
        private void DoZoomFullExtent()
        {
            map.extent = originalExtent;
        }

#region Web Form Designer generated code
        override protected void OnInit(EventArgs e)
        {
            //
            // CODEGEN: This call is required by the ASP.NET Web Form Designer.
            //
            InitializeComponent();
            base.OnInit(e);
        }

/// 
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// 
        private void InitializeComponent()
        {    
            this.Load += new System.EventHandler(this.Page_Load);

}
        #endregion
    }
}

Code flow

The code is extensively commented, so you should have not difficulties to follow it.

  • the client from the browser request a map. If it is the first map the INITMAP action is performed and the first map from MapServer is generated
  • the MapServer map is generated from the mapObj from the mapscript library, by accessing to the data (shapefiles) by the Map File
  • the map is streamed to the image button control in the default.aspx page from the MapStream.aspx page
  • the mapObj is stored in session for following access from the client
  • all the GIS actions (Zoom In, Zoom Out...) from the default.aspx page are performed still by the MapStream.aspx page
schema flow of tutorial code
blog comments powered by Disqus