/// <summary> /// Generates a WMS 1.3.0 compliant response based on a <see cref="SharpMap.Map"/> and the current HttpRequest. /// </summary> /// <remarks> /// <para> /// The Web Map Server implementation in SharpMap requires v1.3.0 compatible clients, /// and support the basic operations "GetCapabilities" and "GetMap" /// as required by the WMS v1.3.0 specification. SharpMap does not support the optional /// GetFeatureInfo operation for querying. /// </para> /// <example> /// Creating a WMS server in ASP.NET is very simple using the classes in the SharpMap.Web.Wms namespace. /// <code lang="C#"> /// void page_load(object o, EventArgs e) /// { /// //Get the path of this page /// string url = (Request.Url.Query.Length>0?Request.Url.AbsoluteUri.Replace(Request.Url.Query,""):Request.Url.AbsoluteUri); /// SharpMap.Web.Wms.Capabilities.WmsServiceDescription description = /// new SharpMap.Web.Wms.Capabilities.WmsServiceDescription("Acme Corp. Map Server", url); /// /// // The following service descriptions below are not strictly required by the WMS specification. /// /// // Narrative description and keywords providing additional information /// description.Abstract = "Map Server maintained by Acme Corporation. Contact: [email protected]. High-quality maps showing roadrunner nests and possible ambush locations."; /// description.Keywords.Add("bird"); /// description.Keywords.Add("roadrunner"); /// description.Keywords.Add("ambush"); /// /// //Contact information /// description.ContactInformation.PersonPrimary.Person = "John Doe"; /// description.ContactInformation.PersonPrimary.Organisation = "Acme Inc"; /// description.ContactInformation.Address.AddressType = "postal"; /// description.ContactInformation.Address.Country = "Neverland"; /// description.ContactInformation.VoiceTelephone = "1-800-WE DO MAPS"; /// //Impose WMS constraints /// description.MaxWidth = 1000; //Set image request size width /// description.MaxHeight = 500; //Set image request size height /// /// //Call method that sets up the map /// //We just add a dummy-size, since the wms requests will set the image-size /// SharpMap.Map myMap = MapHelper.InitializeMap(new System.Drawing.Size(1,1)); /// /// //Parse the request and create a response /// SharpMap.Web.Wms.WmsServer.ParseQueryString(myMap,description); /// } /// </code> /// </example> /// </remarks> /// <param name="map">Map to serve on WMS</param> /// <param name="description">Description of map service</param> public static void ParseQueryString(SharpMap.Map map, Capabilities.WmsServiceDescription description) { if (map == null) throw (new ArgumentException("Map for WMS is null")); if (map.Layers.Count == 0) throw (new ArgumentException("Map doesn't contain any layers for WMS service")); if (System.Web.HttpContext.Current == null) throw (new ApplicationException("An attempt was made to access the WMS server outside a valid HttpContext")); System.Web.HttpContext context = System.Web.HttpContext.Current; //IgnoreCase value should be set according to the VERSION parameter //v1.3.0 is case sensitive, but since it causes a lot of problems with several WMS clients, we ignore casing anyway. bool ignorecase = true; //Check for required parameters //Request parameter is mandatory if (context.Request.Params["REQUEST"] == null) { WmsException.ThrowWmsException("Required parameter REQUEST not specified"); return; } //Check if version is supported if (context.Request.Params["VERSION"] != null) { if (String.Compare(context.Request.Params["VERSION"], "1.3.0", ignorecase) != 0) { WmsException.ThrowWmsException("Only version 1.3.0 supported"); return; } } else //Version is mandatory if REQUEST!=GetCapabilities. Check if this is a capabilities request, since VERSION is null { if (String.Compare(context.Request.Params["REQUEST"], "GetCapabilities", ignorecase) != 0) { WmsException.ThrowWmsException("VERSION parameter not supplied"); return; } } //If Capabilities was requested if (String.Compare(context.Request.Params["REQUEST"], "GetCapabilities", ignorecase) == 0) { GetCapabilities(map, ref description, context); } else if (String.Compare(context.Request.Params["REQUEST"], "GetMap", ignorecase) == 0) //Map requested { GetMap(map, ref description, context, ignorecase); } else if (String.Compare(context.Request.Params["REQUEST"], "getfeatureinfo", ignorecase) == 0) //Map requested { GetFeatureInfo(map, context); } else WmsException.ThrowWmsException(WmsException.WmsExceptionCode.OperationNotSupported, "Invalid request"); }
/// <summary> /// Generates a capabilities file from a map object for use in WMS services /// </summary> /// <remarks>The capabilities document uses the v1.3.0 OpenGIS WMS specification</remarks> /// <param name="map">The map to create capabilities for</param> /// <param name="serviceDescription">Additional description of WMS</param> /// <returns>Returns XmlDocument describing capabilities</returns> public static XmlDocument GetCapabilities(Map map, Capabilities.WmsServiceDescription serviceDescription) { XmlDocument capabilities = new XmlDocument(); //Set XMLSchema //capabilities.Schemas.Add(GetCapabilitiesSchema()); //Instantiate an XmlNamespaceManager object. //System.Xml.XmlNamespaceManager xmlnsManager = new System.Xml.XmlNamespaceManager(capabilities.NameTable); //xmlnsManager.AddNamespace(xlinkNamespaceURI, "urn:Books"); //Insert XML tag capabilities.InsertBefore(capabilities.CreateXmlDeclaration("1.0", "UTF-8", string.Empty), capabilities.DocumentElement); capabilities.AppendChild( capabilities.CreateComment("Capabilities generated by SharpMap v. " + Assembly.GetExecutingAssembly().GetName().Version)); //Create root node XmlNode RootNode = capabilities.CreateNode(XmlNodeType.Element, "WMS_Capabilities", wmsNamespaceURI); RootNode.Attributes.Append(CreateAttribute("version", "1.3.0", capabilities)); XmlAttribute attr = capabilities.CreateAttribute("xmlns", "xsi", "http://www.w3.org/2000/xmlns/"); attr.InnerText = "http://www.w3.org/2001/XMLSchema-instance"; RootNode.Attributes.Append(attr); RootNode.Attributes.Append(CreateAttribute("xmlns:xlink", xlinkNamespaceURI, capabilities)); XmlAttribute attr2 = capabilities.CreateAttribute("xsi", "schemaLocation", "http://www.w3.org/2001/XMLSchema-instance"); attr2.InnerText = "http://schemas.opengis.net/wms/1.3.0/capabilities_1_3_0.xsd"; RootNode.Attributes.Append(attr2); //Build Service node RootNode.AppendChild(GenerateServiceNode(ref serviceDescription, capabilities)); //Build Capability node RootNode.AppendChild(GenerateCapabilityNode(map, capabilities, serviceDescription.PublicAccessURL)); capabilities.AppendChild(RootNode); //TODO: Validate output against schema return capabilities; }
/// <summary> /// Generates a WMS 1.3.0 compliant response based on a <see cref="SharpMap.Map"/> and the current HttpRequest. /// </summary> /// <remarks> /// <para> /// The Web Map Server implementation in SharpMap requires v1.3.0 compatible clients, /// and support the basic operations "GetCapabilities" and "GetMap" /// as required by the WMS v1.3.0 specification. SharpMap does not support the optional /// GetFeatureInfo operation for querying. /// </para> /// <example> /// Creating a WMS server in ASP.NET is very simple using the classes in the SharpMap.Web.Wms namespace. /// <code lang="C#"> /// void page_load(object o, EventArgs e) /// { /// //Get the path of this page /// string url = (Request.Url.Query.Length>0?Request.Url.AbsoluteUri.Replace(Request.Url.Query,""):Request.Url.AbsoluteUri); /// SharpMap.Web.Wms.Capabilities.WmsServiceDescription description = /// new SharpMap.Web.Wms.Capabilities.WmsServiceDescription("Acme Corp. Map Server", url); /// /// // The following service descriptions below are not strictly required by the WMS specification. /// /// // Narrative description and keywords providing additional information /// description.Abstract = "Map Server maintained by Acme Corporation. Contact: [email protected]. High-quality maps showing roadrunner nests and possible ambush locations."; /// description.Keywords.Add("bird"); /// description.Keywords.Add("roadrunner"); /// description.Keywords.Add("ambush"); /// /// //Contact information /// description.ContactInformation.PersonPrimary.Person = "John Doe"; /// description.ContactInformation.PersonPrimary.Organisation = "Acme Inc"; /// description.ContactInformation.Address.AddressType = "postal"; /// description.ContactInformation.Address.Country = "Neverland"; /// description.ContactInformation.VoiceTelephone = "1-800-WE DO MAPS"; /// //Impose WMS constraints /// description.MaxWidth = 1000; //Set image request size width /// description.MaxHeight = 500; //Set image request size height /// /// //Call method that sets up the map /// //We just add a dummy-size, since the wms requests will set the image-size /// SharpMap.Map myMap = MapHelper.InitializeMap(new System.Drawing.Size(1,1)); /// /// //Parse the request and create a response /// SharpMap.Web.Wms.WmsServer.ParseQueryString(myMap,description); /// } /// </code> /// </example> /// </remarks> /// <param name="map">Map to serve on WMS</param> /// <param name="description">Description of map service</param> /// <param name="intersectDelegate">Delegate for Getfeatureinfo intersecting, when null, the WMS will default to ICanQueryLayer implementation</param> public static void ParseQueryString(Map map, Capabilities.WmsServiceDescription description, int pixelSensitivity, InterSectDelegate intersectDelegate) { _intersectDelegate = intersectDelegate; if (pixelSensitivity > 0) _pixelSensitivity = pixelSensitivity; ParseQueryString(map, description); }
/// <summary> /// Generates a WMS 1.3.0 compliant response based on a <see cref="SharpMap.Map"/> and the current HttpRequest. /// </summary> /// <remarks> /// <para> /// The Web Map Server implementation in SharpMap requires v1.3.0 compatible clients, /// and support the basic operations "GetCapabilities" and "GetMap" /// as required by the WMS v1.3.0 specification. SharpMap does not support the optional /// GetFeatureInfo operation for querying. /// </para> /// <example> /// Creating a WMS server in ASP.NET is very simple using the classes in the SharpMap.Web.Wms namespace. /// <code lang="C#"> /// void page_load(object o, EventArgs e) /// { /// //Get the path of this page /// string url = (Request.Url.Query.Length>0?Request.Url.AbsoluteUri.Replace(Request.Url.Query,""):Request.Url.AbsoluteUri); /// SharpMap.Web.Wms.Capabilities.WmsServiceDescription description = /// new SharpMap.Web.Wms.Capabilities.WmsServiceDescription("Acme Corp. Map Server", url); /// /// // The following service descriptions below are not strictly required by the WMS specification. /// /// // Narrative description and keywords providing additional information /// description.Abstract = "Map Server maintained by Acme Corporation. Contact: [email protected]. High-quality maps showing roadrunner nests and possible ambush locations."; /// description.Keywords.Add("bird"); /// description.Keywords.Add("roadrunner"); /// description.Keywords.Add("ambush"); /// /// //Contact information /// description.ContactInformation.PersonPrimary.Person = "John Doe"; /// description.ContactInformation.PersonPrimary.Organisation = "Acme Inc"; /// description.ContactInformation.Address.AddressType = "postal"; /// description.ContactInformation.Address.Country = "Neverland"; /// description.ContactInformation.VoiceTelephone = "1-800-WE DO MAPS"; /// //Impose WMS constraints /// description.MaxWidth = 1000; //Set image request size width /// description.MaxHeight = 500; //Set image request size height /// /// //Call method that sets up the map /// //We just add a dummy-size, since the wms requests will set the image-size /// SharpMap.Map myMap = MapHelper.InitializeMap(new System.Drawing.Size(1,1)); /// /// //Parse the request and create a response /// SharpMap.Web.Wms.WmsServer.ParseQueryString(myMap,description); /// } /// </code> /// </example> /// </remarks> /// <param name="map">Map to serve on WMS</param> /// <param name="description">Description of map service</param> public static void ParseQueryString(Map map, Capabilities.WmsServiceDescription description) { if (_pixelSensitivity ==-1) _pixelSensitivity = 1; if (map == null) throw (new ArgumentException("Map for WMS is null")); if (map.Layers.Count == 0) throw (new ArgumentException("Map doesn't contain any layers for WMS service")); if (HttpContext.Current == null) throw (new ApplicationException( "An attempt was made to access the WMS server outside a valid HttpContext")); HttpContext context = HttpContext.Current; //IgnoreCase value should be set according to the VERSION parameter //v1.3.0 is case sensitive, but since it causes a lot of problems with several WMS clients, we ignore casing anyway. bool ignorecase = true; //Check for required parameters //Request parameter is mandatory if (context.Request.Params["REQUEST"] == null) { WmsException.ThrowWmsException("Required parameter REQUEST not specified"); return; } //Check if version is supported if (context.Request.Params["VERSION"] != null) { if (String.Compare(context.Request.Params["VERSION"], "1.3.0", ignorecase) != 0) { WmsException.ThrowWmsException("Only version 1.3.0 supported"); return; } } else //Version is mandatory if REQUEST!=GetCapabilities. Check if this is a capabilities request, since VERSION is null { if (String.Compare(context.Request.Params["REQUEST"], "GetCapabilities", ignorecase) != 0) { WmsException.ThrowWmsException("VERSION parameter not supplied"); return; } } //If Capabilities was requested if (String.Compare(context.Request.Params["REQUEST"], "GetCapabilities", ignorecase) == 0) { //Service parameter is mandatory for GetCapabilities request if (context.Request.Params["SERVICE"] == null) { WmsException.ThrowWmsException("Required parameter SERVICE not specified"); return; } if (String.Compare(context.Request.Params["SERVICE"], "WMS") != 0) WmsException.ThrowWmsException( "Invalid service for GetCapabilities Request. Service parameter must be 'WMS'"); XmlDocument capabilities = Capabilities.GetCapabilities(map, description); context.Response.Clear(); context.Response.ContentType = "text/xml"; XmlWriter writer = XmlWriter.Create(context.Response.OutputStream); capabilities.WriteTo(writer); writer.Close(); context.Response.End(); } else if (String.Compare(context.Request.Params["REQUEST"], "GetFeatureInfo", ignorecase) == 0) //FeatureInfo Requested { if (context.Request.Params["LAYERS"] == null) { WmsException.ThrowWmsException("Required parameter LAYERS not specified"); return; } if (context.Request.Params["STYLES"] == null) { WmsException.ThrowWmsException("Required parameter STYLES not specified"); return; } if (context.Request.Params["CRS"] == null) { WmsException.ThrowWmsException("Required parameter CRS not specified"); return; } else if (context.Request.Params["CRS"] != "EPSG:" + map.Layers[0].TargetSRID) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidCRS, "CRS not supported"); return; } if (context.Request.Params["BBOX"] == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Required parameter BBOX not specified"); return; } if (context.Request.Params["WIDTH"] == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Required parameter WIDTH not specified"); return; } if (context.Request.Params["HEIGHT"] == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Required parameter HEIGHT not specified"); return; } if (context.Request.Params["FORMAT"] == null) { WmsException.ThrowWmsException("Required parameter FORMAT not specified"); return; } if (context.Request.Params["QUERY_LAYERS"] == null) { WmsException.ThrowWmsException("Required parameter QUERY_LAYERS not specified"); return; } if (context.Request.Params["INFO_FORMAT"] == null) { WmsException.ThrowWmsException("Required parameter INFO_FORMAT not specified"); return; } //parameters X&Y are not part of the 1.3.0 specification, but are included for backwards compatability with 1.1.1 (OpenLayers likes it when used together with wms1.1.1 services) if (context.Request.Params["X"] == null && context.Request.Params["I"] == null) { WmsException.ThrowWmsException("Required parameter I not specified"); return; } if (context.Request.Params["Y"] == null && context.Request.Params["J"] == null) { WmsException.ThrowWmsException("Required parameter J not specified"); return; } //sets the map size to the size of the client in order to calculate the coordinates of the projection of the client try { map.Size = new System.Drawing.Size(System.Convert.ToInt16(context.Request.Params["WIDTH"]), System.Convert.ToInt16(context.Request.Params["HEIGHT"])); } catch { WmsException.ThrowWmsException("Invalid parameters for HEIGHT or WITDH"); return; } //sets the boundingbox to the boundingbox of the client in order to calculate the coordinates of the projection of the client BoundingBox bbox = ParseBBOX(context.Request.Params["bbox"]); if (bbox == null) { WmsException.ThrowWmsException("Invalid parameter BBOX"); return; } map.ZoomToBox(bbox); //sets the point clicked by the client SharpMap.Geometries.Point p = new SharpMap.Geometries.Point(); Single x = 0; Single y = 0; //tries to set the x to the Param I, if the client send an X, it will try the X, if both fail, exception is thrown if (context.Request.Params["X"] != null) try { x = System.Convert.ToSingle(context.Request.Params["X"]); } catch { WmsException.ThrowWmsException("Invalid parameters for I"); } if (context.Request.Params["I"] != null) try { x = System.Convert.ToSingle(context.Request.Params["I"]); } catch { WmsException.ThrowWmsException("Invalid parameters for I"); } //same procedure for J (Y) if (context.Request.Params["Y"] != null) try { y = System.Convert.ToSingle(context.Request.Params["Y"]); } catch { WmsException.ThrowWmsException("Invalid parameters for I"); } if (context.Request.Params["J"] != null) try { y = System.Convert.ToSingle(context.Request.Params["J"]); } catch { WmsException.ThrowWmsException("Invalid parameters for I"); } p = map.ImageToWorld(new System.Drawing.PointF(x, y)); int fc; try { fc = System.Convert.ToInt16(context.Request.Params["FEATURE_COUNT"]); if (fc < 1) fc = 1; } catch { fc = 1; } //default to text if an invalid format is requested string infoFormat = context.Request.Params["INFO_FORMAT"]; string cqlFilter = null; if (context.Request.Params["CQL_FILTER"] != null) { cqlFilter = context.Request.Params["CQL_FILTER"]; } string vstr = ""; string[] requestLayers = context.Request.Params["QUERY_LAYERS"].Split(new[] { ',' }); if (String.Compare(context.Request.Params["INFO_FORMAT"], "text/json", ignorecase) == 0) { vstr = CreateFeatureInfoGeoJSON(map, requestLayers, x, y, fc, cqlFilter); context.Response.ContentType = "text/json"; } else { vstr = CreateFeatureInfoPlain(map, requestLayers, x, y, fc, cqlFilter); context.Response.ContentType = "text/plain"; } context.Response.Clear(); context.Response.Charset = "windows-1252"; context.Response.Write(vstr); context.Response.Flush(); context.Response.End(); } else if (String.Compare(context.Request.Params["REQUEST"], "GetMap", ignorecase) == 0) //Map requested { //Check for required parameters if (context.Request.Params["LAYERS"] == null) { WmsException.ThrowWmsException("Required parameter LAYERS not specified"); return; } if (context.Request.Params["STYLES"] == null) { WmsException.ThrowWmsException("Required parameter STYLES not specified"); return; } if (context.Request.Params["CRS"] == null) { WmsException.ThrowWmsException("Required parameter CRS not specified"); return; } else if (context.Request.Params["CRS"] != "EPSG:" + map.Layers[0].TargetSRID) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidCRS, "CRS not supported"); return; } if (context.Request.Params["BBOX"] == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Required parameter BBOX not specified"); return; } if (context.Request.Params["WIDTH"] == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Required parameter WIDTH not specified"); return; } if (context.Request.Params["HEIGHT"] == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Required parameter HEIGHT not specified"); return; } if (context.Request.Params["FORMAT"] == null) { WmsException.ThrowWmsException("Required parameter FORMAT not specified"); return; } //Set background color of map if (String.Compare(context.Request.Params["TRANSPARENT"], "TRUE", ignorecase) == 0) map.BackColor = Color.Transparent; else if (context.Request.Params["BGCOLOR"] != null) { try { map.BackColor = ColorTranslator.FromHtml(context.Request.Params["BGCOLOR"]); } catch { WmsException.ThrowWmsException("Invalid parameter BGCOLOR"); return; } ; } else map.BackColor = Color.White; //Get the image format requested ImageCodecInfo imageEncoder = GetEncoderInfo(context.Request.Params["FORMAT"]); if (imageEncoder == null) { WmsException.ThrowWmsException("Invalid MimeType specified in FORMAT parameter"); return; } //Parse map size int width = 0; int height = 0; if (!int.TryParse(context.Request.Params["WIDTH"], out width)) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Invalid parameter WIDTH"); return; } else if (description.MaxWidth > 0 && width > description.MaxWidth) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.OperationNotSupported, "Parameter WIDTH too large"); return; } if (!int.TryParse(context.Request.Params["HEIGHT"], out height)) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Invalid parameter HEIGHT"); return; } else if (description.MaxHeight > 0 && height > description.MaxHeight) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.OperationNotSupported, "Parameter HEIGHT too large"); return; } map.Size = new Size(width, height); BoundingBox bbox = ParseBBOX(context.Request.Params["bbox"]); if (bbox == null) { WmsException.ThrowWmsException("Invalid parameter BBOX"); return; } map.PixelAspectRatio = (width / (double)height) / (bbox.Width / bbox.Height); map.Center = bbox.GetCentroid(); map.Zoom = bbox.Width; //set Styles for layers //first, if the request == STYLES=, set all the vectorlayers with Themes not null the Theme to the first theme from Themes if (String.IsNullOrEmpty(context.Request.Params["STYLES"])) { foreach (ILayer layer in map.Layers) { if (layer.GetType() == typeof(VectorLayer)) { if ((layer as VectorLayer).Themes != null) { if ((layer as VectorLayer).Themes.Count > 0) { foreach (KeyValuePair<string, SharpMap.Rendering.Thematics.ITheme> kvp in (layer as VectorLayer).Themes) { (layer as VectorLayer).Theme = kvp.Value; break; } } } } } } else { if (!String.IsNullOrEmpty(context.Request.Params["LAYERS"])) { string[] layerz = context.Request.Params["LAYERS"].Split(new[] { ',' }); string[] styles = context.Request.Params["STYLES"].Split(new[] { ',' }); //test whether the lengt of the layers and the styles is the same. WMS spec is unclear on what to do if there is no one-to-one correspondence if (layerz.Length == styles.Length) { foreach (ILayer layer in map.Layers) { if (layer.GetType() == typeof(VectorLayer)) { if ((layer as VectorLayer).Themes != null) { if ((layer as VectorLayer).Themes.Count > 0) { for (int i = 0; i < layerz.Length; i++) { if (String.Equals(layer.LayerName, layerz[i], StringComparison.InvariantCultureIgnoreCase)) { //take default style if style is empty if (styles[i] =="") { foreach (KeyValuePair<string, SharpMap.Rendering.Thematics.ITheme> kvp in (layer as VectorLayer).Themes) { (layer as VectorLayer).Theme = kvp.Value; break; } } else { if ((layer as VectorLayer).Themes.ContainsKey(styles[i])) { (layer as VectorLayer).Theme = (layer as VectorLayer).Themes[styles[i]]; } else { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.StyleNotDefined, "Style not advertised for this layer"); } } } } } } } } } } } if (context.Request.Params["CQL_FILTER"] != null) { foreach (ILayer layer in map.Layers) { if (layer.GetType() == typeof(VectorLayer)) { if (typeof(SharpMap.Data.Providers.FilterProvider).IsAssignableFrom((layer as VectorLayer).DataSource.GetType())) { SharpMap.Data.Providers.FilterProvider shape = (SharpMap.Data.Providers.FilterProvider)(layer as VectorLayer).DataSource; shape.FilterDelegate = new Data.Providers.FilterProvider.FilterMethod(delegate(SharpMap.Data.FeatureDataRow row) { return CQLFilter(row, context.Request.Params["CQL_FILTER"]); }); } } else if(layer.GetType() == typeof(LabelLayer)) { if (typeof(SharpMap.Data.Providers.FilterProvider).IsAssignableFrom((layer as VectorLayer).DataSource.GetType())) { SharpMap.Data.Providers.FilterProvider shape = (SharpMap.Data.Providers.FilterProvider)(layer as VectorLayer).DataSource; shape.FilterDelegate = new Data.Providers.FilterProvider.FilterMethod(delegate(SharpMap.Data.FeatureDataRow row) { return CQLFilter(row, context.Request.Params["CQL_FILTER"]); }); } } } } //Set layers on/off if (!String.IsNullOrEmpty(context.Request.Params["LAYERS"])) //If LAYERS is empty, use default layer on/off settings { string[] layers = context.Request.Params["LAYERS"].Split(new[] { ',' }); if (description.LayerLimit > 0) { if (layers.Length == 0 && map.Layers.Count > description.LayerLimit || layers.Length > description.LayerLimit) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.OperationNotSupported, "Too many layers requested"); return; } } foreach (ILayer layer in map.Layers) layer.Enabled = false; foreach (string layer in layers) { //SharpMap.Layers.ILayer lay = map.Layers.Find(delegate(SharpMap.Layers.ILayer findlay) { return findlay.LayerName == layer; }); ILayer lay = null; for (int i = 0; i < map.Layers.Count; i++) if (String.Equals(map.Layers[i].LayerName, layer, StringComparison.InvariantCultureIgnoreCase)) lay = map.Layers[i]; if (lay == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.LayerNotDefined, "Unknown layer '" + layer + "'"); return; } else lay.Enabled = true; } } //Render map Image img = map.GetMap(); //Png can't stream directy. Going through a memorystream instead MemoryStream MS = new MemoryStream(); img.Save(MS, imageEncoder, null); img.Dispose(); byte[] buffer = MS.ToArray(); context.Response.Clear(); context.Response.ContentType = imageEncoder.MimeType; context.Response.OutputStream.Write(buffer, 0, buffer.Length); //context.Response.End(); } else WmsException.ThrowWmsException(WmsException.WmsExceptionCode.OperationNotSupported, "Invalid request"); }
/// <summary> /// /// </summary> /// <param name="map"></param> /// <param name="description"></param> /// <param name="context"></param> /// <param name="ignorecase"></param> private static void GetMap(SharpMap.Map map, ref Capabilities.WmsServiceDescription description, System.Web.HttpContext context, bool ignorecase) { string QueryString = context.Request.QueryString.ToString(); System.Diagnostics.Debug.WriteLine(context.Request.QueryString); if (RequestIsCached(QueryString)) { SendCachedData(context); } else { bool MapIsStatic = true; //Check for required parameters if (context.Request.Params["LAYERS"] == null) { WmsException.ThrowWmsException("Required parameter LAYERS not specified"); return; } if (context.Request.Params["STYLES"] == null) { WmsException.ThrowWmsException("Required parameter STYLES not specified"); return; } if (context.Request.Params["CRS"] == null) { WmsException.ThrowWmsException("Required parameter CRS not specified"); return; } else if (context.Request.Params["CRS"] != "EPSG:" + map.Layers[0].SRID.ToString()) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidCRS, "CRS not supported"); return; } if (context.Request.Params["BBOX"] == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Required parameter BBOX not specified"); return; } if (context.Request.Params["WIDTH"] == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Required parameter WIDTH not specified"); return; } if (context.Request.Params["HEIGHT"] == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Required parameter HEIGHT not specified"); return; } if (context.Request.Params["FORMAT"] == null) { WmsException.ThrowWmsException("Required parameter FORMAT not specified"); return; } //Set background color of map if (String.Compare(context.Request.Params["TRANSPARENT"], "TRUE", ignorecase) == 0) map.BackColor = System.Drawing.Color.Transparent; else if (context.Request.Params["BGCOLOR"] != null) { try { map.BackColor = System.Drawing.ColorTranslator.FromHtml(context.Request.Params["BGCOLOR"]); } catch { WmsException.ThrowWmsException("Invalid parameter BGCOLOR"); return; }; } else map.BackColor = System.Drawing.Color.White; //Get the image format requested System.Drawing.Imaging.ImageCodecInfo imageEncoder = GetEncoderInfo(context.Request.Params["FORMAT"]); if (imageEncoder == null) { WmsException.ThrowWmsException("Invalid MimeType specified in FORMAT parameter"); return; } //Parse map size int width = 0; int height = 0; if (!int.TryParse(context.Request.Params["WIDTH"], out width)) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Invalid parameter WIDTH"); return; } else if (description.MaxWidth > 0 && width > description.MaxWidth) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.OperationNotSupported, "Parameter WIDTH too large"); return; } if (!int.TryParse(context.Request.Params["HEIGHT"], out height)) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Invalid parameter HEIGHT"); return; } else if (description.MaxHeight > 0 && height > description.MaxHeight) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.OperationNotSupported, "Parameter HEIGHT too large"); return; } map.Size = new System.Drawing.Size(width, height); SharpMap.Geometries.BoundingBox bbox = ParseBBOX(context.Request.Params["bbox"]); if (bbox == null) { WmsException.ThrowWmsException("Invalid parameter BBOX"); return; } map.PixelAspectRatio = ((double)width / (double)height) / (bbox.Width / bbox.Height); map.Center = bbox.GetCentroid(); map.Zoom = bbox.Width; //Set layers on/off if (context.Request.Params["LAYERS"] != "") //If LAYERS is empty, use default layer on/off settings { string[] layers = context.Request.Params["LAYERS"].Split(new char[] { ',' }); if (description.LayerLimit > 0) { if (layers.Length == 0 && map.Layers.Count > description.LayerLimit || layers.Length > description.LayerLimit) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.OperationNotSupported, "Too many layers requested"); return; } } foreach (SharpMap.Layers.ILayer layer in map.Layers) layer.Enabled = false; foreach (string layer in layers) { SharpMap.Layers.ILayer lay = map.Layers.Find(delegate(SharpMap.Layers.ILayer findlay) { return findlay.LayerName == layer; }); if (lay == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.LayerNotDefined, "Unknown layer '" + layer + "'"); return; } else { lay.Enabled = true; if (lay is SharpMap.Layers.VectorLayer) { if (!((lay as SharpMap.Layers.VectorLayer).DataSource is SharpMap.Data.Providers.ShapeFile)) { MapIsStatic = false; } } } } } //Render map System.Drawing.Image img = map.GetMap(); //Png can't stream directy. Going through a memorystream instead System.IO.MemoryStream MS = new System.IO.MemoryStream(); img.Save(MS, imageEncoder, null); img.Dispose(); byte[] buffer = MS.ToArray(); context.Response.Clear(); context.Response.ContentType = imageEncoder.MimeType; context.Response.OutputStream.Write(buffer, 0, buffer.Length); if (MapIsStatic) SaveCachedData(QueryString, imageEncoder.MimeType, buffer); context.Response.End(); } }
/// <summary> /// /// </summary> /// <param name="map"></param> /// <param name="description"></param> /// <param name="context"></param> private static void GetCapabilities(SharpMap.Map map, ref Capabilities.WmsServiceDescription description, System.Web.HttpContext context) { //Service parameter is mandatory for GetCapabilities request if (context.Request.Params["SERVICE"] == null) { WmsException.ThrowWmsException("Required parameter SERVICE not specified"); return; } if (String.Compare(context.Request.Params["SERVICE"], "WMS") != 0) WmsException.ThrowWmsException("Invalid service for GetCapabilities Request. Service parameter must be 'WMS'"); System.Xml.XmlDocument capabilities = Wms.Capabilities.GetCapabilities(map, description); context.Response.Clear(); context.Response.ContentType = "text/xml"; System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(context.Response.OutputStream); capabilities.WriteTo(writer); writer.Close(); context.Response.End(); }
/// <summary> /// Generates a WMS 1.3.0 compliant response based on a <see cref="SharpMap.Map"/> and the current HttpRequest. /// </summary> /// <remarks> /// <para> /// The Web Map Server implementation in SharpMap requires v1.3.0 compatible clients, /// and support the basic operations "GetCapabilities" and "GetMap" /// as required by the WMS v1.3.0 specification. SharpMap does not support the optional /// GetFeatureInfo operation for querying. /// </para> /// <example> /// Creating a WMS server in ASP.NET is very simple using the classes in the SharpMap.Web.Wms namespace. /// <code lang="C#"> /// void page_load(object o, EventArgs e) /// { /// //Get the path of this page /// string url = (Request.Url.Query.Length>0?Request.Url.AbsoluteUri.Replace(Request.Url.Query,""):Request.Url.AbsoluteUri); /// SharpMap.Web.Wms.Capabilities.WmsServiceDescription description = /// new SharpMap.Web.Wms.Capabilities.WmsServiceDescription("Acme Corp. Map Server", url); /// /// // The following service descriptions below are not strictly required by the WMS specification. /// /// // Narrative description and keywords providing additional information /// description.Abstract = "Map Server maintained by Acme Corporation. Contact: [email protected]. High-quality maps showing roadrunner nests and possible ambush locations."; /// description.Keywords.Add("bird"); /// description.Keywords.Add("roadrunner"); /// description.Keywords.Add("ambush"); /// /// //Contact information /// description.ContactInformation.PersonPrimary.Person = "John Doe"; /// description.ContactInformation.PersonPrimary.Organisation = "Acme Inc"; /// description.ContactInformation.Address.AddressType = "postal"; /// description.ContactInformation.Address.Country = "Neverland"; /// description.ContactInformation.VoiceTelephone = "1-800-WE DO MAPS"; /// //Impose WMS constraints /// description.MaxWidth = 1000; //Set image request size width /// description.MaxHeight = 500; //Set image request size height /// /// //Call method that sets up the map /// //We just add a dummy-size, since the wms requests will set the image-size /// SharpMap.Map myMap = MapHelper.InitializeMap(new System.Drawing.Size(1,1)); /// /// //Parse the request and create a response /// SharpMap.Web.Wms.WmsServer.ParseQueryString(myMap,description); /// } /// </code> /// </example> /// </remarks> /// <param name="map">Map to serve on WMS</param> /// <param name="description">Description of map service</param> ///<param name="pixelSensitivity"> </param> ///<param name="intersectDelegate">Delegate for Getfeatureinfo intersecting, when null, the WMS will default to ICanQueryLayer implementation</param> public static void ParseQueryString(Map map, Capabilities.WmsServiceDescription description, int pixelSensitivity, InterSectDelegate intersectDelegate) { IntersectDelegate = intersectDelegate; if (pixelSensitivity > 0) PixelSensitivity = pixelSensitivity; ParseQueryString(map, description, new Context(HttpContext.Current)); }
/// <summary> /// Generates a WMS 1.3.0 compliant response based on a <see cref="SharpMap.Map"/> and the current HttpRequest. /// </summary> /// <remarks> /// <para> /// The Web Map Server implementation in SharpMap requires v1.3.0 compatible clients, /// and support the basic operations "GetCapabilities" and "GetMap" /// as required by the WMS v1.3.0 specification. SharpMap does not support the optional /// GetFeatureInfo operation for querying. /// </para> /// <example> /// Creating a WMS server in ASP.NET is very simple using the classes in the SharpMap.Web.Wms namespace. /// <code lang="C#"> /// void page_load(object o, EventArgs e) /// { /// //Get the path of this page /// string url = (Request.Url.Query.Length>0?Request.Url.AbsoluteUri.Replace(Request.Url.Query,""):Request.Url.AbsoluteUri); /// SharpMap.Web.Wms.Capabilities.WmsServiceDescription description = /// new SharpMap.Web.Wms.Capabilities.WmsServiceDescription("Acme Corp. Map Server", url); /// /// // The following service descriptions below are not strictly required by the WMS specification. /// /// // Narrative description and keywords providing additional information /// description.Abstract = "Map Server maintained by Acme Corporation. Contact: [email protected]. High-quality maps showing roadrunner nests and possible ambush locations."; /// description.Keywords.Add("bird"); /// description.Keywords.Add("roadrunner"); /// description.Keywords.Add("ambush"); /// /// //Contact information /// description.ContactInformation.PersonPrimary.Person = "John Doe"; /// description.ContactInformation.PersonPrimary.Organisation = "Acme Inc"; /// description.ContactInformation.Address.AddressType = "postal"; /// description.ContactInformation.Address.Country = "Neverland"; /// description.ContactInformation.VoiceTelephone = "1-800-WE DO MAPS"; /// //Impose WMS constraints /// description.MaxWidth = 1000; //Set image request size width /// description.MaxHeight = 500; //Set image request size height /// /// //Call method that sets up the map /// //We just add a dummy-size, since the wms requests will set the image-size /// SharpMap.Map myMap = MapHelper.InitializeMap(new System.Drawing.Size(1,1)); /// /// //Parse the request and create a response /// SharpMap.Web.Wms.WmsServer.ParseQueryString(myMap,description); /// } /// </code> /// </example> /// </remarks> /// <param name="map">Map to serve on WMS</param> /// <param name="description">Description of map service</param> /// <param name="context">The context the <see cref="WmsServer"/> is running in.</param> public static void ParseQueryString(Map map, Capabilities.WmsServiceDescription description, IContext context) { const StringComparison @case = StringComparison.InvariantCultureIgnoreCase; IContextRequest request = context.Request; IContextResponse response = context.Response; try { if (PixelSensitivity < 0) PixelSensitivity = 1; if (map == null) throw new WmsArgumentException("Map for WMS is null"); if (map.Layers.Count == 0) throw new WmsArgumentException("Map doesn't contain any layers for WMS service"); string req = request.GetParam("REQUEST"); if (req == null) throw new WmsParameterNotSpecifiedException("REQUEST"); IHandler handler; if (String.Equals(req, "GetCapabilities", @case)) handler = new GetCapabilities(description); else if (String.Equals(req, "GetFeatureInfo", @case)) { // use text/plain as default handler // let the default handler validate params string format = request.GetParam("INFO_FORMAT") ?? String.Empty; GetFeatureInfoParams @params = new GetFeatureInfoParams(PixelSensitivity, IntersectDelegate, FeatureInfoResponseEncoding); if (String.Equals(format, "text/json", @case)) handler = new GetFeatureInfoJson(description, @params); else if (String.Equals(format, "text/html", @case)) handler = new GetFeatureInfoHtml(description, @params); else handler = new GetFeatureInfoPlain(description, @params); } else if (String.Equals(req, "GetMap", @case)) handler = new GetMap(description); else { string s = String.Format("Invalid request: {0}", req); throw new WmsOperationNotSupportedException(s); } IHandlerResponse result = handler.Handle(map, request); result.WriteToContextAndFlush(response); } catch (WmsExceptionBase ex) { ex.WriteToContextAndFlush(response); } }
/// <summary> /// Generates a WMS 1.3.0 compliant response based on a <see cref="SharpMap.Map"/> and the current HttpRequest. /// </summary> /// <remarks> /// <para> /// The Web Map Server implementation in SharpMap requires v1.3.0 compatible clients, /// and support the basic operations "GetCapabilities" and "GetMap" /// as required by the WMS v1.3.0 specification. SharpMap does not support the optional /// GetFeatureInfo operation for querying. /// </para> /// <example> /// Creating a WMS server in ASP.NET is very simple using the classes in the SharpMap.Web.Wms namespace. /// <code lang="C#"> /// void page_load(object o, EventArgs e) /// { /// //Get the path of this page /// string url = (Request.Url.Query.Length>0?Request.Url.AbsoluteUri.Replace(Request.Url.Query,""):Request.Url.AbsoluteUri); /// SharpMap.Web.Wms.Capabilities.WmsServiceDescription description = /// new SharpMap.Web.Wms.Capabilities.WmsServiceDescription("Acme Corp. Map Server", url); /// /// // The following service descriptions below are not strictly required by the WMS specification. /// /// // Narrative description and keywords providing additional information /// description.Abstract = "Map Server maintained by Acme Corporation. Contact: [email protected]. High-quality maps showing roadrunner nests and possible ambush locations."; /// description.Keywords.Add("bird"); /// description.Keywords.Add("roadrunner"); /// description.Keywords.Add("ambush"); /// /// //Contact information /// description.ContactInformation.PersonPrimary.Person = "John Doe"; /// description.ContactInformation.PersonPrimary.Organisation = "Acme Inc"; /// description.ContactInformation.Address.AddressType = "postal"; /// description.ContactInformation.Address.Country = "Neverland"; /// description.ContactInformation.VoiceTelephone = "1-800-WE DO MAPS"; /// //Impose WMS constraints /// description.MaxWidth = 1000; //Set image request size width /// description.MaxHeight = 500; //Set image request size height /// /// //Call method that sets up the map /// //We just add a dummy-size, since the wms requests will set the image-size /// SharpMap.Map myMap = MapHelper.InitializeMap(new System.Drawing.Size(1,1)); /// /// //Parse the request and create a response /// SharpMap.Web.Wms.WmsServer.ParseQueryString(myMap,description); /// } /// </code> /// </example> /// </remarks> /// <param name="map">Map to serve on WMS</param> /// <param name="description">Description of map service</param> public static void ParseQueryString(SharpMap.Map map, Capabilities.WmsServiceDescription description) { if (map == null) throw (new ArgumentException("Map for WMS is null")); if (map.Layers.Count == 0) throw (new ArgumentException("Map doesn't contain any layers for WMS service")); if (System.Web.HttpContext.Current == null) throw (new ApplicationException("An attempt was made to access the WMS server outside a valid HttpContext")); System.Web.HttpContext context = System.Web.HttpContext.Current; //IgnoreCase value should be set according to the VERSION parameter //v1.3.0 is case sensitive, but since it causes a lot of problems with several WMS clients, we ignore casing anyway. bool ignorecase = true; //Check for required parameters //Request parameter is mandatory if (context.Request.Params["REQUEST"] == null) { WmsException.ThrowWmsException("Required parameter REQUEST not specified"); return; } //Check if version is supported if (context.Request.Params["VERSION"] != null) { if (String.Compare(context.Request.Params["VERSION"], "1.3.0", ignorecase) != 0) { WmsException.ThrowWmsException("Only version 1.3.0 supported"); return; } } else //Version is mandatory if REQUEST!=GetCapabilities. Check if this is a capabilities request, since VERSION is null { if (String.Compare(context.Request.Params["REQUEST"], "GetCapabilities", ignorecase) != 0) { WmsException.ThrowWmsException("VERSION parameter not supplied"); return; } } //If Capabilities was requested if (String.Compare(context.Request.Params["REQUEST"], "GetCapabilities", ignorecase) == 0) { //Service parameter is mandatory for GetCapabilities request if (context.Request.Params["SERVICE"] == null) { WmsException.ThrowWmsException("Required parameter SERVICE not specified"); return; } if (String.Compare(context.Request.Params["SERVICE"], "WMS") != 0) WmsException.ThrowWmsException("Invalid service for GetCapabilities Request. Service parameter must be 'WMS'"); System.Xml.XmlDocument capabilities = Wms.Capabilities.GetCapabilities(map, description); context.Response.Clear(); context.Response.ContentType = "text/xml"; System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(context.Response.OutputStream); capabilities.WriteTo(writer); writer.Close(); context.Response.End(); } else if (String.Compare(context.Request.Params["REQUEST"], "GetMap", ignorecase) == 0) //Map requested { //Check for required parameters if (context.Request.Params["LAYERS"] == null) { WmsException.ThrowWmsException("Required parameter LAYERS not specified"); return; } if (context.Request.Params["STYLES"] == null) { WmsException.ThrowWmsException("Required parameter STYLES not specified"); return; } if (context.Request.Params["CRS"] == null) { WmsException.ThrowWmsException("Required parameter CRS not specified"); return; } else if (context.Request.Params["CRS"] != "EPSG:" + map.Layers[0].SRID.ToString()) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidCRS, "CRS not supported"); return; } if (context.Request.Params["BBOX"] == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Required parameter BBOX not specified"); return; } if (context.Request.Params["WIDTH"] == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Required parameter WIDTH not specified"); return; } if (context.Request.Params["HEIGHT"] == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Required parameter HEIGHT not specified"); return; } if (context.Request.Params["FORMAT"] == null) { WmsException.ThrowWmsException("Required parameter FORMAT not specified"); return; } //Set background color of map if (String.Compare(context.Request.Params["TRANSPARENT"], "TRUE", ignorecase) == 0) map.BackColor = System.Drawing.Color.Transparent; else if (context.Request.Params["BGCOLOR"] != null) { try { map.BackColor = System.Drawing.ColorTranslator.FromHtml(context.Request.Params["BGCOLOR"]); } catch { WmsException.ThrowWmsException("Invalid parameter BGCOLOR"); return; }; } else map.BackColor = System.Drawing.Color.White; //Get the image format requested System.Drawing.Imaging.ImageCodecInfo imageEncoder = GetEncoderInfo(context.Request.Params["FORMAT"]); if (imageEncoder == null) { WmsException.ThrowWmsException("Invalid MimeType specified in FORMAT parameter"); return; } //Parse map size int width = 0; int height = 0; if (!int.TryParse(context.Request.Params["WIDTH"], out width)) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Invalid parameter WIDTH"); return; } else if (description.MaxWidth > 0 && width > description.MaxWidth) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.OperationNotSupported, "Parameter WIDTH too large"); return; } if (!int.TryParse(context.Request.Params["HEIGHT"], out height)) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Invalid parameter HEIGHT"); return; } else if (description.MaxHeight > 0 && height > description.MaxHeight) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.OperationNotSupported, "Parameter HEIGHT too large"); return; } map.Size = new System.Drawing.Size(width, height); IEnvelope bbox = ParseBBOX(context.Request.Params["bbox"]); if (bbox == null) { WmsException.ThrowWmsException("Invalid parameter BBOX"); return; } map.PixelAspectRatio = ((double)width / (double)height) / (bbox.Width / bbox.Height); map.Center = bbox.Centre; map.Zoom = bbox.Width; //Set layers on/off if (!String.IsNullOrEmpty(context.Request.Params["LAYERS"])) //If LAYERS is empty, use default layer on/off settings { string[] layers = context.Request.Params["LAYERS"].Split(new char[] { ',' }); if(description.LayerLimit>0) { if (layers.Length == 0 && map.Layers.Count > description.LayerLimit || layers.Length > description.LayerLimit) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.OperationNotSupported, "Too many layers requested"); return; } } foreach (SharpMap.Layers.ILayer layer in map.Layers) layer.Enabled = false; foreach (string layer in layers) { //SharpMap.Layers.ILayer lay = map.Layers.Find(delegate(SharpMap.Layers.ILayer findlay) { return findlay.LayerName == layer; }); SharpMap.Layers.ILayer lay = null; for (int i = 0; i < map.Layers.Count; i++) if (String.Equals(map.Layers[i].Name, layer, StringComparison.InvariantCultureIgnoreCase)) lay = map.Layers[i]; if (lay == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.LayerNotDefined, "Unknown layer '" + layer + "'"); return; } else lay.Enabled = true; } } //Render map System.Drawing.Image img = map.Render(); //Png can't stream directy. Going through a memorystream instead System.IO.MemoryStream MS = new System.IO.MemoryStream(); img.Save(MS, imageEncoder, null); img.Dispose(); byte[] buffer = MS.ToArray(); context.Response.Clear(); context.Response.ContentType = imageEncoder.MimeType; context.Response.OutputStream.Write(buffer, 0, buffer.Length); context.Response.End(); } else WmsException.ThrowWmsException(WmsException.WmsExceptionCode.OperationNotSupported, "Invalid request"); }
/// <summary> /// Generates a WMS 1.3.0 compliant response based on a <see cref="SharpMap.Map"/> and the current HttpRequest. /// </summary> /// <remarks> /// <para> /// The Web Map Server implementation in SharpMap requires v1.3.0 compatible clients, /// and support the basic operations "GetCapabilities" and "GetMap" /// as required by the WMS v1.3.0 specification. SharpMap does not support the optional /// GetFeatureInfo operation for querying. /// </para> /// <example> /// Creating a WMS server in ASP.NET is very simple using the classes in the SharpMap.Web.Wms namespace. /// <code lang="C#"> /// void page_load(object o, EventArgs e) /// { /// //Get the path of this page /// string url = (Request.Url.Query.Length>0?Request.Url.AbsoluteUri.Replace(Request.Url.Query,""):Request.Url.AbsoluteUri); /// SharpMap.Web.Wms.Capabilities.WmsServiceDescription description = /// new SharpMap.Web.Wms.Capabilities.WmsServiceDescription("Acme Corp. Map Server", url); /// /// // The following service descriptions below are not strictly required by the WMS specification. /// /// // Narrative description and keywords providing additional information /// description.Abstract = "Map Server maintained by Acme Corporation. Contact: [email protected]. High-quality maps showing roadrunner nests and possible ambush locations."; /// description.Keywords.Add("bird"); /// description.Keywords.Add("roadrunner"); /// description.Keywords.Add("ambush"); /// /// //Contact information /// description.ContactInformation.PersonPrimary.Person = "John Doe"; /// description.ContactInformation.PersonPrimary.Organisation = "Acme Inc"; /// description.ContactInformation.Address.AddressType = "postal"; /// description.ContactInformation.Address.Country = "Neverland"; /// description.ContactInformation.VoiceTelephone = "1-800-WE DO MAPS"; /// //Impose WMS constraints /// description.MaxWidth = 1000; //Set image request size width /// description.MaxHeight = 500; //Set image request size height /// /// //Call method that sets up the map /// //We just add a dummy-size, since the wms requests will set the image-size /// SharpMap.Map myMap = MapHelper.InitializeMap(new System.Drawing.Size(1,1)); /// /// //Parse the request and create a response /// SharpMap.Web.Wms.WmsServer.ParseQueryString(myMap,description); /// } /// </code> /// </example> /// </remarks> /// <param name="map">Map to serve on WMS</param> /// <param name="description">Description of map service</param> public static void ParseQueryString(Map map, Capabilities.WmsServiceDescription description) { ParseQueryString(map, description, 1, null); }
/// <summary> /// Generates a WMS 1.3.0 compliant response based on a <see cref="SharpMap.Map"/> and the current HttpRequest. /// </summary> /// <remarks> /// <para> /// The Web Map Server implementation in SharpMap requires v1.3.0 compatible clients, /// and support the basic operations "GetCapabilities" and "GetMap" /// as required by the WMS v1.3.0 specification. SharpMap does not support the optional /// GetFeatureInfo operation for querying. /// </para> /// <example> /// Creating a WMS server in ASP.NET is very simple using the classes in the SharpMap.Web.Wms namespace. /// <code lang="C#"> /// void page_load(object o, EventArgs e) /// { /// //Get the path of this page /// string url = (Request.Url.Query.Length>0?Request.Url.AbsoluteUri.Replace(Request.Url.Query,""):Request.Url.AbsoluteUri); /// SharpMap.Web.Wms.Capabilities.WmsServiceDescription description = /// new SharpMap.Web.Wms.Capabilities.WmsServiceDescription("Acme Corp. Map Server", url); /// /// // The following service descriptions below are not strictly required by the WMS specification. /// /// // Narrative description and keywords providing additional information /// description.Abstract = "Map Server maintained by Acme Corporation. Contact: [email protected]. /// High-quality maps showing roadrunner nests and possible ambush locations."; /// description.Keywords.Add("bird"); /// description.Keywords.Add("roadrunner"); /// description.Keywords.Add("ambush"); /// /// //Contact information /// description.ContactInformation.PersonPrimary.Person = "John Doe"; /// description.ContactInformation.PersonPrimary.Organisation = "Acme Inc"; /// description.ContactInformation.Address.AddressType = "postal"; /// description.ContactInformation.Address.Country = "Neverland"; /// description.ContactInformation.VoiceTelephone = "1-800-WE DO MAPS"; /// //Impose WMS constraints /// description.MaxWidth = 1000; //Set image request size width /// description.MaxHeight = 500; //Set image request size height /// /// //Call method that sets up the map /// //We just add a dummy-size, since the wms requests will set the image-size /// SharpMap.Map myMap = MapHelper.InitializeMap(new System.Drawing.Size(1,1)); /// /// //Parse the request and create a response /// SharpMap.Web.Wms.WmsServer.ParseQueryString(myMap,description); /// } /// </code> /// </example> /// </remarks> /// <param name="map">Map to serve on WMS</param> /// <param name="description">Description of map service</param> ///<param name="pixelSensitivity">Tolerance for GetFeatureInfo requests</param> ///<param name="intersectDelegate">Delegate for Getfeatureinfo intersecting, when null, the WMS will default to ICanQueryLayer implementation</param> public static void ParseQueryString(Map map, Capabilities.WmsServiceDescription description, int pixelSensitivity, InterSectDelegate intersectDelegate) { _pixelSensitivity = pixelSensitivity; _intersectDelegate = intersectDelegate; if (map == null) throw (new ArgumentException("Map for WMS is null")); if (map.Layers.Count == 0) throw (new ArgumentException("Map doesn't contain any layers for WMS service")); if (HttpContext.Current == null) throw new ApplicationException("An attempt was made to access the WMS server outside a valid HttpContext"); HttpContext context = HttpContext.Current; //IgnoreCase value should be set according to the VERSION parameter //v1.3.0 is case sensitive, but since it causes a lot of problems with several WMS clients, we ignore casing anyway. const bool ignorecase = true; //Collect parameters string request = context.Request.Params["REQUEST"]; string version = context.Request.Params["VERSION"]; //Check for required parameters //Request parameter is mandatory if (request == null) { WmsException.ThrowWmsException("Required parameter REQUEST not specified"); return; } //Check if version is supported if (version != null) { if (String.Compare(version, "1.3.0", ignorecase) != 0) { WmsException.ThrowWmsException("Only version 1.3.0 supported"); return; } } else { //Version is mandatory if REQUEST!=GetCapabilities. Check if this is a capabilities request, since VERSION is null if (String.Compare(request, "GetCapabilities", ignorecase) != 0) { WmsException.ThrowWmsException("VERSION parameter not supplied"); return; } } HandlerParams @params = new HandlerParams(context, map, description, ignorecase); GetFeatureInfoParams infoParams = new GetFeatureInfoParams(_pixelSensitivity, _intersectDelegate); IWmsHandler handler = null; if (String.Compare(request, "GetCapabilities", ignorecase) == 0) handler = new GetCapabilities(@params); else if (String.Compare(request, "GetFeatureInfo", ignorecase) == 0) handler = new GetFeatureInfo(@params, infoParams); else if (String.Compare(request, "GetMap", ignorecase) == 0) handler = new GetMap(@params); if (handler == null) { WmsException.ThrowWmsException( WmsException.WmsExceptionCode.OperationNotSupported, String.Format("Invalid request: {0}", request)); } else handler.Handle(); }
/// <summary> /// Generates a WMS 1.3.0 compliant response based on a <see cref="SharpMap.Map"/> and the current HttpRequest. /// </summary> /// <remarks> /// <para> /// The Web Map Server implementation in SharpMap requires v1.3.0 compatible clients, /// and support the basic operations "GetCapabilities" and "GetMap" /// as required by the WMS v1.3.0 specification. SharpMap does not support the optional /// GetFeatureInfo operation for querying. /// </para> /// <example> /// Creating a WMS server in ASP.NET is very simple using the classes in the SharpMap.Web.Wms namespace. /// <code lang="C#"> /// void page_load(object o, EventArgs e) /// { /// //Get the path of this page /// string url = (Request.Url.Query.Length>0?Request.Url.AbsoluteUri.Replace(Request.Url.Query,""):Request.Url.AbsoluteUri); /// SharpMap.Web.Wms.Capabilities.WmsServiceDescription description = /// new SharpMap.Web.Wms.Capabilities.WmsServiceDescription("Acme Corp. Map Server", url); /// /// // The following service descriptions below are not strictly required by the WMS specification. /// /// // Narrative description and keywords providing additional information /// description.Abstract = "Map Server maintained by Acme Corporation. Contact: [email protected]. High-quality maps showing roadrunner nests and possible ambush locations."; /// description.Keywords.Add("bird"); /// description.Keywords.Add("roadrunner"); /// description.Keywords.Add("ambush"); /// /// //Contact information /// description.ContactInformation.PersonPrimary.Person = "John Doe"; /// description.ContactInformation.PersonPrimary.Organisation = "Acme Inc"; /// description.ContactInformation.Address.AddressType = "postal"; /// description.ContactInformation.Address.Country = "Neverland"; /// description.ContactInformation.VoiceTelephone = "1-800-WE DO MAPS"; /// //Impose WMS constraints /// description.MaxWidth = 1000; //Set image request size width /// description.MaxHeight = 500; //Set image request size height /// /// //Call method that sets up the map /// //We just add a dummy-size, since the wms requests will set the image-size /// SharpMap.Map myMap = MapHelper.InitializeMap(new System.Drawing.Size(1,1)); /// /// //Parse the request and create a response /// SharpMap.Web.Wms.WmsServer.ParseQueryString(myMap,description); /// } /// </code> /// </example> /// </remarks> /// <param name="map">Map to serve on WMS</param> /// <param name="description">Description of map service</param> public static void ParseQueryString(Map map, Capabilities.WmsServiceDescription description) { if (HttpContext.Current == null) throw (new ApplicationException( "An attempt was made to access the WMS server outside a valid HttpContext")); ParseQueryString(map, description, HttpContext.Current); }
/// <summary> /// Generates a WMS 1.3.0 compliant response based on a <see cref="SharpMap.Map"/> and the current HttpRequest. /// </summary> /// <remarks> /// <para> /// The Web Map Server implementation in SharpMap requires v1.3.0 compatible clients, /// and support the basic operations "GetCapabilities" and "GetMap" /// as required by the WMS v1.3.0 specification. SharpMap does not support the optional /// GetFeatureInfo operation for querying. /// </para> /// <example> /// Creating a WMS server in ASP.NET is very simple using the classes in the SharpMap.Web.Wms namespace. /// <code lang="C#"> /// void page_load(object o, EventArgs e) /// { /// //Get the path of this page /// string url = (Request.Url.Query.Length>0?Request.Url.AbsoluteUri.Replace(Request.Url.Query,""):Request.Url.AbsoluteUri); /// SharpMap.Web.Wms.Capabilities.WmsServiceDescription description = /// new SharpMap.Web.Wms.Capabilities.WmsServiceDescription("Acme Corp. Map Server", url); /// /// // The following service descriptions below are not strictly required by the WMS specification. /// /// // Narrative description and keywords providing additional information /// description.Abstract = "Map Server maintained by Acme Corporation. Contact: [email protected]. High-quality maps showing roadrunner nests and possible ambush locations."; /// description.Keywords.Add("bird"); /// description.Keywords.Add("roadrunner"); /// description.Keywords.Add("ambush"); /// /// //Contact information /// description.ContactInformation.PersonPrimary.Person = "John Doe"; /// description.ContactInformation.PersonPrimary.Organisation = "Acme Inc"; /// description.ContactInformation.Address.AddressType = "postal"; /// description.ContactInformation.Address.Country = "Neverland"; /// description.ContactInformation.VoiceTelephone = "1-800-WE DO MAPS"; /// //Impose WMS constraints /// description.MaxWidth = 1000; //Set image request size width /// description.MaxHeight = 500; //Set image request size height /// /// //Call method that sets up the map /// //We just add a dummy-size, since the wms requests will set the image-size /// SharpMap.Map myMap = MapHelper.InitializeMap(new System.Drawing.Size(1,1)); /// /// //Parse the request and create a response /// SharpMap.Web.Wms.WmsServer.ParseQueryString(myMap,description); /// } /// </code> /// </example> /// </remarks> /// <param name="map">Map to serve on WMS</param> /// <param name="description">Description of map service</param> public static void ParseQueryString(Map map, Capabilities.WmsServiceDescription description) { _pixelSensitivity = 1; if (map == null) throw (new ArgumentException("Map for WMS is null")); if (map.Layers.Count == 0) throw (new ArgumentException("Map doesn't contain any layers for WMS service")); if (HttpContext.Current == null) throw (new ApplicationException( "An attempt was made to access the WMS server outside a valid HttpContext")); HttpContext context = HttpContext.Current; //IgnoreCase value should be set according to the VERSION parameter //v1.3.0 is case sensitive, but since it causes a lot of problems with several WMS clients, we ignore casing anyway. bool ignorecase = true; //Check for required parameters //Request parameter is mandatory if (context.Request.Params["REQUEST"] == null) { WmsException.ThrowWmsException("Required parameter REQUEST not specified"); return; } //Check if version is supported if (context.Request.Params["VERSION"] != null) { if (String.Compare(context.Request.Params["VERSION"], "1.3.0", ignorecase) != 0) { WmsException.ThrowWmsException("Only version 1.3.0 supported"); return; } } else //Version is mandatory if REQUEST!=GetCapabilities. Check if this is a capabilities request, since VERSION is null { if (String.Compare(context.Request.Params["REQUEST"], "GetCapabilities", ignorecase) != 0) { WmsException.ThrowWmsException("VERSION parameter not supplied"); return; } } //If Capabilities was requested if (String.Compare(context.Request.Params["REQUEST"], "GetCapabilities", ignorecase) == 0) { //Service parameter is mandatory for GetCapabilities request if (context.Request.Params["SERVICE"] == null) { WmsException.ThrowWmsException("Required parameter SERVICE not specified"); return; } if (String.Compare(context.Request.Params["SERVICE"], "WMS") != 0) WmsException.ThrowWmsException( "Invalid service for GetCapabilities Request. Service parameter must be 'WMS'"); XmlDocument capabilities = Capabilities.GetCapabilities(map, description); context.Response.Clear(); context.Response.ContentType = "text/xml"; XmlWriter writer = XmlWriter.Create(context.Response.OutputStream); capabilities.WriteTo(writer); writer.Close(); context.Response.End(); } else if (String.Compare(context.Request.Params["REQUEST"], "GetFeatureInfo", ignorecase) == 0) //FeatureInfo Requested { if (context.Request.Params["LAYERS"] == null) { WmsException.ThrowWmsException("Required parameter LAYERS not specified"); return; } if (context.Request.Params["STYLES"] == null) { WmsException.ThrowWmsException("Required parameter STYLES not specified"); return; } if (context.Request.Params["CRS"] == null) { WmsException.ThrowWmsException("Required parameter CRS not specified"); return; } else if (context.Request.Params["CRS"] != "EPSG:" + map.Layers[0].SRID) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidCRS, "CRS not supported"); return; } if (context.Request.Params["BBOX"] == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Required parameter BBOX not specified"); return; } if (context.Request.Params["WIDTH"] == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Required parameter WIDTH not specified"); return; } if (context.Request.Params["HEIGHT"] == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Required parameter HEIGHT not specified"); return; } if (context.Request.Params["FORMAT"] == null) { WmsException.ThrowWmsException("Required parameter FORMAT not specified"); return; } if (context.Request.Params["QUERY_LAYERS"] == null) { WmsException.ThrowWmsException("Required parameter QUERY_LAYERS not specified"); return; } if (context.Request.Params["INFO_FORMAT"] == null) { WmsException.ThrowWmsException("Required parameter INFO_FORMAT not specified"); return; } //parameters X&Y are not part of the 1.3.0 specification, but are included for backwards compatability with 1.1.1 (OpenLayers likes it when used together with wms1.1.1 services) if (context.Request.Params["X"] == null && context.Request.Params["I"] == null) { WmsException.ThrowWmsException("Required parameter I not specified"); return; } if (context.Request.Params["Y"] == null && context.Request.Params["J"] == null) { WmsException.ThrowWmsException("Required parameter J not specified"); return; } //sets the map size to the size of the client in order to calculate the coordinates of the projection of the client try { map.Size = new System.Drawing.Size(System.Convert.ToInt16(context.Request.Params["WIDTH"]), System.Convert.ToInt16(context.Request.Params["HEIGHT"])); } catch { WmsException.ThrowWmsException("Invalid parameters for HEIGHT or WITDH"); return; } //sets the boundingbox to the boundingbox of the client in order to calculate the coordinates of the projection of the client BoundingBox bbox = ParseBBOX(context.Request.Params["bbox"]); if (bbox == null) { WmsException.ThrowWmsException("Invalid parameter BBOX"); return; } map.ZoomToBox(bbox); //sets the point clicked by the client SharpMap.Geometries.Point p = new SharpMap.Geometries.Point(); Single x = 0; Single y = 0; //tries to set the x to the Param I, if the client send an X, it will try the X, if both fail, exception is thrown if (context.Request.Params["X"] != null) try { x = System.Convert.ToSingle(context.Request.Params["X"]); } catch { WmsException.ThrowWmsException("Invalid parameters for I"); } if (context.Request.Params["I"] != null) try { x = System.Convert.ToSingle(context.Request.Params["I"]); } catch { WmsException.ThrowWmsException("Invalid parameters for I"); } //same procedure for J (Y) if (context.Request.Params["Y"] != null) try { y = System.Convert.ToSingle(context.Request.Params["Y"]); } catch { WmsException.ThrowWmsException("Invalid parameters for I"); } if (context.Request.Params["J"] != null) try { y = System.Convert.ToSingle(context.Request.Params["J"]); } catch { WmsException.ThrowWmsException("Invalid parameters for I"); } p = map.ImageToWorld(new System.Drawing.PointF(x, y)); int fc; try { fc = System.Convert.ToInt16(context.Request.Params["FEATURE_COUNT"]); if (fc < 1) fc = 1; } catch { fc = 1; } String vstr = "GetFeatureInfo results: \n"; string[] requestLayers = context.Request.Params["QUERY_LAYERS"].Split(new[] { ',' }); foreach (string requestLayer in requestLayers) { bool found = false; foreach (ILayer mapLayer in map.Layers) { if (String.Equals(mapLayer.LayerName, requestLayer, StringComparison.InvariantCultureIgnoreCase)) { found = true; if (!(mapLayer is ICanQueryLayer)) continue; ICanQueryLayer queryLayer = mapLayer as ICanQueryLayer; if (queryLayer.IsQueryEnabled) { Single queryBoxMinX = x - (_pixelSensitivity); Single queryBoxMinY = y - (_pixelSensitivity); Single queryBoxMaxX = x + (_pixelSensitivity); Single queryBoxMaxY = y + (_pixelSensitivity); SharpMap.Geometries.Point minXY = map.ImageToWorld(new System.Drawing.PointF(queryBoxMinX, queryBoxMinY)); SharpMap.Geometries.Point maxXY = map.ImageToWorld(new System.Drawing.PointF(queryBoxMaxX, queryBoxMaxY)); BoundingBox queryBox = new BoundingBox(minXY, maxXY); SharpMap.Data.FeatureDataSet fds = new SharpMap.Data.FeatureDataSet(); queryLayer.ExecuteIntersectionQuery(queryBox, fds); if (_intersectDelegate != null) { fds.Tables[0] = _intersectDelegate(fds.Tables[0], queryBox); } if (fds.Tables.Count == 0) { vstr = vstr + "\nSearch returned no results on layer: " + requestLayer; } else { if (fds.Tables[0].Rows.Count == 0) { vstr = vstr + "\nSearch returned no results on layer: " + requestLayer + " "; } else { //if featurecount < fds...count, select smallest bbox, because most likely to be clicked vstr = vstr + "\n Layer: '" + requestLayer + "'\n Featureinfo:\n"; int[] keys = new int[fds.Tables[0].Rows.Count]; double[] area = new double[fds.Tables[0].Rows.Count]; for (int l = 0; l < fds.Tables[0].Rows.Count; l++) { SharpMap.Data.FeatureDataRow fdr = fds.Tables[0].Rows[l] as SharpMap.Data.FeatureDataRow; area[l] = fdr.Geometry.GetBoundingBox().GetArea(); keys[l] = l; } Array.Sort(area, keys); if (fds.Tables[0].Rows.Count < fc) { fc = fds.Tables[0].Rows.Count; } for (int k = 0; k < fc; k++) { for (int j = 0; j < fds.Tables[0].Rows[keys[k]].ItemArray.Length; j++) { vstr = vstr + " '" + fds.Tables[0].Rows[keys[k]].ItemArray[j].ToString() + "'"; } if ((k + 1) < fc) vstr = vstr + ",\n"; } } } } } } if (found == false) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.LayerNotDefined, "Unknown layer '" + requestLayer + "'"); return; } } context.Response.Clear(); context.Response.ContentType = "text/plain"; context.Response.Charset = "windows-1252"; context.Response.Write(vstr); context.Response.Flush(); context.Response.End(); } else if (String.Compare(context.Request.Params["REQUEST"], "GetMap", ignorecase) == 0) //Map requested { //Check for required parameters if (context.Request.Params["LAYERS"] == null) { WmsException.ThrowWmsException("Required parameter LAYERS not specified"); return; } if (context.Request.Params["STYLES"] == null) { WmsException.ThrowWmsException("Required parameter STYLES not specified"); return; } if (context.Request.Params["CRS"] == null) { WmsException.ThrowWmsException("Required parameter CRS not specified"); return; } else if (context.Request.Params["CRS"] != "EPSG:" + map.Layers[0].SRID) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidCRS, "CRS not supported"); return; } if (context.Request.Params["BBOX"] == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Required parameter BBOX not specified"); return; } if (context.Request.Params["WIDTH"] == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Required parameter WIDTH not specified"); return; } if (context.Request.Params["HEIGHT"] == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Required parameter HEIGHT not specified"); return; } if (context.Request.Params["FORMAT"] == null) { WmsException.ThrowWmsException("Required parameter FORMAT not specified"); return; } //Set background color of map if (String.Compare(context.Request.Params["TRANSPARENT"], "TRUE", ignorecase) == 0) map.BackColor = Color.Transparent; else if (context.Request.Params["BGCOLOR"] != null) { try { map.BackColor = ColorTranslator.FromHtml(context.Request.Params["BGCOLOR"]); } catch { WmsException.ThrowWmsException("Invalid parameter BGCOLOR"); return; } ; } else map.BackColor = Color.White; //Get the image format requested ImageCodecInfo imageEncoder = GetEncoderInfo(context.Request.Params["FORMAT"]); if (imageEncoder == null) { WmsException.ThrowWmsException("Invalid MimeType specified in FORMAT parameter"); return; } //Parse map size int width = 0; int height = 0; if (!int.TryParse(context.Request.Params["WIDTH"], out width)) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Invalid parameter WIDTH"); return; } else if (description.MaxWidth > 0 && width > description.MaxWidth) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.OperationNotSupported, "Parameter WIDTH too large"); return; } if (!int.TryParse(context.Request.Params["HEIGHT"], out height)) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.InvalidDimensionValue, "Invalid parameter HEIGHT"); return; } else if (description.MaxHeight > 0 && height > description.MaxHeight) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.OperationNotSupported, "Parameter HEIGHT too large"); return; } map.Size = new Size(width, height); BoundingBox bbox = ParseBBOX(context.Request.Params["bbox"]); if (bbox == null) { WmsException.ThrowWmsException("Invalid parameter BBOX"); return; } map.PixelAspectRatio = (width / (double)height) / (bbox.Width / bbox.Height); map.Center = bbox.GetCentroid(); map.Zoom = bbox.Width; //Set layers on/off if (!String.IsNullOrEmpty(context.Request.Params["LAYERS"])) //If LAYERS is empty, use default layer on/off settings { string[] layers = context.Request.Params["LAYERS"].Split(new[] { ',' }); if (description.LayerLimit > 0) { if (layers.Length == 0 && map.Layers.Count > description.LayerLimit || layers.Length > description.LayerLimit) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.OperationNotSupported, "Too many layers requested"); return; } } foreach (ILayer layer in map.Layers) layer.Enabled = false; foreach (string layer in layers) { //SharpMap.Layers.ILayer lay = map.Layers.Find(delegate(SharpMap.Layers.ILayer findlay) { return findlay.LayerName == layer; }); ILayer lay = null; for (int i = 0; i < map.Layers.Count; i++) if (String.Equals(map.Layers[i].LayerName, layer, StringComparison.InvariantCultureIgnoreCase)) lay = map.Layers[i]; if (lay == null) { WmsException.ThrowWmsException(WmsException.WmsExceptionCode.LayerNotDefined, "Unknown layer '" + layer + "'"); return; } else lay.Enabled = true; } } //Render map Image img = map.GetMap(); //Png can't stream directy. Going through a memorystream instead MemoryStream MS = new MemoryStream(); img.Save(MS, imageEncoder, null); img.Dispose(); byte[] buffer = MS.ToArray(); context.Response.Clear(); context.Response.ContentType = imageEncoder.MimeType; context.Response.OutputStream.Write(buffer, 0, buffer.Length); context.Response.End(); } else WmsException.ThrowWmsException(WmsException.WmsExceptionCode.OperationNotSupported, "Invalid request"); }