ThinkGeo.com    |     Documentation    |     Premium Support

Map Suite as a standard web service?

Hi,


I'm normally working with the Web Edition, but has been assigned the task of building a small (standard) web service utilizing Map Suite to return a map image. And no, it need to be standard WS, not WMS etc. (normal ASP.netters don't understand OGC :-))


When working with web forms, an ASPX page is used to initialize the MAP component. This is not possible in a WS, afaik.


So I need to create a Map with a base map from scratch, the base map being a WMS service, to which my WS acts as a client.


First, is this possible with the core libraries in Web Edition ? I'm under the impression that the Services Edition is "just" the core library.


Second, my WS errs when I set up the WMS connection. Are there any caveats in this kind of setup to be aware of ?


I'm having my WS return an image without base map (with just background color), but adding the WMS layer throws an error: "Data on root level are invalid, Line 1 Position 1". The setup has been copied from another project, although from a WMSOverlay.


All help is appriciated.


TIA


 



Hi again,


I've stripped down my code, so it's clear what I'm doing:



Dim Map1 As ThinkGeo.MapSuite.Core.MapEngine
Dim Canvas1 As ThinkGeo.MapSuite.Core.GeoCanvas
Dim ResImage As System.Drawing.Bitmap = Nothing

Map1 = New MapEngine()
Canvas1 = Map1.Canvas

Dim mapExtent = New RectangleShape(...)

ResImage = New Bitmap(request.ImageWidth, request.ImageHeight)
Canvas1.BeginDrawing(ResImage, mapExtent, GeographyUnit.Meter)

Map1.StaticLayers.Add(New WMSRasterLayer(New Uri("..."))) '<<< THIS IS WHAT ERRS

Map1.DrawStaticLayers(ResImage, GeographyUnit.Meter)
Canvas1.EndDrawing()


TIA


 



Hi, 
  
 I’ve narrowed it down to being something to do with “opening” the WMS layer. 
  
 Either it errs in the creation of the WMSRasterLayer object, if I try to invoke its Open method (claiming my layer object is not defined), or it errs in DrawStaticLayers if I omit the call to the layer’s Open method. 
  
 The layer also has an ImageSource, but I’m not able to determine whether this is handled internally, or I should do something. 
  
 Please advise. 
  


Lars,


Thanks for your questions!


I'm afraid of I misunderstood something for your questions, in your last comment for this post, I don't know what's the issues you mentioned, you said when creating the WmsRasterLayer object there is an error, but I cannot reproduce the problem, if it is possible can you arrange a sample to me so that I can reproduce your problem correctly?


Also please check the webservice sample in the HowDoISamples of service edition below, maybe it is useful for you:



Thanks,


Scott,



Hi Scott,


Thanks, I hadn't actually installed the Services Edition, I was using the Core libraries from Web Edition.


I've now had a look at the webservices sample, and can see that it differs a lot from my code. So one doesn't need MapEngine at all, one just draws layers onto a GeoCanvas ?


However, my WMS layer still errs, so I don't have a working solution yet.


I've attached the error returned to my testing app.


I'm using a WMS service that is publically accessable for your convenience.


Here's the code for my service:



<WebMethod()> _
Public Function GetMapImage(ByVal request As GetMap_Request) As Byte()
'...

mapExtent = New RectangleShape(request.BoundingBox_LowerLeft.Easting, request.BoundingBox_UpperRight.Northing, request.BoundingBox_UpperRight.Easting, request.BoundingBox_LowerLeft.Northing)

myGeoImage = GdiPlusGeoCanvas.CreateGeoImage(request.ImageWidth, request.ImageHeight)
Dim myGdiPlusGeoCanvas As GdiPlusGeoCanvas = New GdiPlusGeoCanvas()

layer = WMS_Layer_Demo(mapExtent, request.ImageWidth, request.ImageHeight) '<<< Line 442
SyncLock layer
    layer.Draw(myGdiPlusGeoCanvas, New Collection(Of SimpleCandidate)())
End SyncLock

'...
End Function

Here's the code for the WMS returning function in question:



Private Function WMS_Layer_Demo(ByVal mapExtent As RectangleShape, ByVal width As Double, ByVal height As Double) As WmsRasterLayer
    Dim lyr As New WmsRasterLayer
    Dim msg As String = "Init WMS_Layer_Demo"

    'Valid GetMap URL: kort.arealinfo.dk/wms?service=wms&servicename=fyn_wms&VERSION=1.1.1&REQUEST=GetMap&LAYERS=420_40021_byzone_rp&SRS=EPSG:25832&format=image/GIF&WIDTH=800&HEIGHT=800&bbox=582700,6134800,592700,6144800

    Try
        msg = "Defining WMS uri"
        lyr.Name = "Demo service"
        lyr.Uri = New Uri("kort.arealinfo.dk/wms")
        msg = "Defining WMS parameters"
        lyr.Parameters.Add("servicename", "fyn_wms")
        lyr.Parameters.Add("version", "1.1.1")
        lyr.Parameters.Add("srs", "epsg:25832")
        lyr.Parameters.Add("FORMAT", "image/jpeg")
        lyr.OutputFormat = "image/jpeg"
        lyr.Parameters.Add("BBOX", Extent2Bbox(mapExtent))
        lyr.Parameters.Add("width", width)
        lyr.Parameters.Add("height", height)
        lyr.Parameters.Add("LAYERS", "420_40021_byzone_rp")
        lyr.Parameters.Add("STYLES", "")

        '
        msg = "Opening WMS"
        lyr.Open() '<<< THIS IS WHERE IT CRASHES

        msg = "Returning WMS"

        Return lyr

    Catch ex As Exception
        Throw New Exception("Cannot set base layer: DEMO" + vbCrLf + "Last: " + msg + vbCrLf + ex.Message) '<<< LINE 359

    End Try
End Function

TIA


 



Hmm, the attached JPEG disappeared.


Here it is again (?)


 




Hi Scott,


I tried to build the logic into a desktop edition to eliminate any services related problems.


It still complains (last line) about a namespace "sm" not being defined whenever I call the (WMSRaster)Layer.Open() method.


This must be something internally to Map Suite, so I need your assistance.


I've tried to upload the test project, but unfortunately its size of 2 Mb exceed the imposed limit on uploads.




Hi,


I abandoned trying to make sense of Map Suite, and launched my wms proxy script to debug the communication going on.


The primary problem is that Map Suite upon the Open() call emits a GetCapabilities request, but excludes any custom tags that's been added, only sending the two required parameters (SERVICE and REQUEST). This doesn't always work, as e.g. many Danish services also require a SERVICENAME parameter. The VERSION parameter is also optional, but is also required by many services.


You should add the possibility of adding custom parameters for this capabilities request to WMSRasterLayer. Or the ability to avoid this problematic Capabilities request.


Furthermore it seems like the WMS Client doesn't handle service exceptions very well, especially if they're in XML format. There is a special "inimage" exceptions parameter, getting error messages returned as an image, but not all services offer that possibility. Only XML is required as default.


So the implementation at hand (in 4.5) is rudimentary, and need some work, imho. I need to go set up a WMS cascading server to be able to ulitilize WMS in Map Suite at all :-(


Creating a new WMSRasterLayer implementation myself is not an option for me, as this would be overkill, maybe even impossible.


 



Lars, 
  
 Thanks for your investigations on that! 
  
 I reviewed your stack trace but I just can understand English, it seems that you used non-English languages, can you send the sample to my mailbox: chenzhiyong@thinkgeo.com so that I can reproduce the problem on my local machine and give you a solution on that, before that I have several suggestions on that maybe can help you: 
  
 1, When you call the WMSRasterLayer can you get the complete url of the WMS layer and put it in the IE browser to verify if the web service it correct and the image can be displayed in the IE browser? 
  
 2, If the problem is not from the WMS web service side, please check the client side where call the WMSRasterLayer, please use the WMSOverlay to instead of the WMSRasterLayer object to try again. 
  
 After that if you still occur this exception please arrange the sample to my mailbox and make sure your WMS web service side works fine, I will check the WMSRasterLayer or WMSOverlay object as well. 
  
 In addition, you mentioned you used the 4.5 version currently it is 5.0.117.0 version, please the latest version and override the current one. 
  
 Thanks, 
  
 Scott,

Hi Scott,


I built a cascading wms server using UMN MapServer. This clears the issue of the problematic GetCapabilities request, as Mapserver accepts the bare-bones request sent by Map Suite.


I've utilized the code you sent, creating a layer and using its Draw method to create a GeoImage, that I render in a form PíctureBox



Dim layer As Layer
Dim myGeoImage As GeoImage
Dim bbox() As Double = {582700, 6134800, 592700, 6144800}

PictureBox1.Width = 500
PictureBox1.Height = 500

Dim mapExtent = New RectangleShape(bbox(0), bbox(3), bbox(2), bbox(1))
myGeoImage = GdiPlusGeoCanvas.CreateGeoImage(PictureBox1.Width, PictureBox1.Height)
Dim myGdiPlusGeoCanvas As GdiPlusGeoCanvas = New GdiPlusGeoCanvas()

Try
    myGdiPlusGeoCanvas.BeginDrawing(myGeoImage, mapExtent, GeographyUnit.Meter)

    layer = WMS_Layer_Cascade("ArealInfo_Byzone", mapExtent, PictureBox1.Width, PictureBox1.Height)
    SyncLock layer
        layer.Draw(myGdiPlusGeoCanvas, New Collection(Of SimpleCandidate)())
    End SyncLock

    Dim res = GdiPlusGeoCanvas.ConvertGeoImageToMemoryStream(myGeoImage).ToArray()
    Dim ms As New MemoryStream(res)
    PictureBox1.BackgroundImage = New Bitmap(ms)

Catch ex As Exception
    MsgBox("Error: " + ex.Message)

Finally
    If myGdiPlusGeoCanvas.IsDrawing Then
        myGdiPlusGeoCanvas.EndDrawing()
    End If
End Try

But I'm still having trouble getting the requested map image back.


I can see that MapServer gets the correct image, as it stores this as a temp file. But it doesn't get transformed into anything useful in Map Suite. I'm having Map Suite save the requested image as files, but they're empty (black or transparent, but valid images).


One of the problem is that Map Suite apparently always requests PNG even when I try to specify JPEG !? But even when I go with PNG all the way, it still doesn't work.


Can you make your code sample work with the below WMS service, rendering the result as a PicuireBox ? This is a valid GetMap request URL:


kort.arealinfo.dk/wms?service=wms&servicename=fyn_wms&VERSION=1.1.1&REQUEST=GetMap&LAYERS=420_40021_byzone_rp&SRS=EPSG:25832&format=image/jpeg&WIDTH=800&HEIGHT=800&bbox=582700,6134800,592700,6144800


TIA



 



Doh, solved it myself. Sometimes a day away from the code clears one’s mind. 
  
 I added myGdiPlusGeoCanvas.EndDrawing() immidiatedly after the SyncLock construct, and it worked ! 
  
 Now back to the original project of making it into a service … 


Lars, 
  
 That’s a great news from you! Any more questions please let us know again, 
  
 Thanks, 
  
 Scott,