So I've been playing more with the AGS SOAP API, and have found a few things...
Generating Proxy Classes
While you could pass Xml back and forth, most people will opt to use some kind of proxy classes. Visual Studio will generate these for you when you add a web reference, and this is a good way to get up and running quickly.
There is one downside however - it seems that the WSDL returned by ArcGIS Server for any particular service injects the service name into itself. So if you were adding a web reference to http://myserver/arcgis/services/mytestService/MapServer?wsdl then you'd get a class that was named mytestService_mapserver. While you can change the actual service Url to point to another Map Service, you'll still have "mytestService_mapserver" littered all over your code. To me this is ugly and a code smell if you are trying to write something which is not bound to a single service. I guess the idea is that it helps a developer figure out which web service they are talking to, and I suppose that if you needed to write an app that used multiple connections to multiple mapservices, then it may *help*, but I doubt it. Any insight on why this was done would be great.
Creating Manual Proxies: wsdl.exe
In addition to simply using Add Web Reference, you can take a more manual route and use wsdl.exe to create the proxies. The wsdl.exe tool that ships with Visual Studio 2005 and it offers a little more control. The syntax is pretty simple - here's what I used:
wsdl.exe /nologo /l:CS /n:ArcDeveloper.AGS.SOAP.Proxies /o:c:\wsdl\proxies /urlkey:MapServerUrl MapServer.wsdl
So this creates a C# proxy class for the MapServer.wsdl file, in c:\wsdl\proxies, in the ArcDeveloper.AGS.SOAP.Proxies namespace.
However, if you run this against the WSDL you download from the MapServer WSDL page, you'll get an error:
Warning: This web reference does not conform to WS-I Basic Profile v1.1.R2028, R2029: A DESCRIPTION using the WSDL namespace and the WSDL SOAP binding namespace MUST be valid according to the XML Schemas found at http://schemas.xmlsoap.org/wsdl/2003-02-11.xsd and http://schemas.xmlsoap.org/wsdl/soap/2003-02-11.xsd. - Warning: The 'name' attribute is invalid - The value '#NAME#' is invalid according to its datatype 'http://www.w3.org/2001/XMLSchema:NCName' - The '#' character, hexadecimal value 0x23, cannot be included in a name. Line 2465, position 11. - Warning: The identity constraint 'http://schemas.xmlsoap.org/wsdl/:service' validation has failed. Either a key is missing or the existing key has an empty node. Line 2465, position 3. For more details on the WS-I Basic Profile v1.1, see the specification at http://www.ws-i.org/Profiles/BasicProfile-1.1.html. Writing file 'c:\wsdl\NAME.cs'.
Warning: This web reference does not conform to WS-I Basic Profile v1.1.R2028, R2029: A DESCRIPTION using the WSDL namespace and the WSDL SOAP binding namespace MUST be valid according to the XML Schemas found at http://schemas.xmlsoap.org/wsdl/2003-02-11.xsd and http://schemas.xmlsoap.org/wsdl/soap/2003-02-11.xsd. - Warning: The 'name' attribute is invalid - The value '#NAME#' is invalid according to its datatype 'http://www.w3.org/2001/XMLSchema:NCName' - The '#' character, hexadecimal value 0x23, cannot be included in a name. Line 2465, position 11. - Warning: The identity constraint 'http://schemas.xmlsoap.org/wsdl/:service' validation has failed. Either a key is missing or the existing key has an empty node. Line 2465, position 3.
For more details on the WS-I Basic Profile v1.1, see the specification at http://www.ws-i.org/Profiles/BasicProfile-1.1.html.
Writing file 'c:\wsdl\NAME.cs'.
The errors are not critical, since a file still gets written, but now the proxy class is named "NAME", which is worse than the <mapservicename>_mapservice that we got using Add Web Reference. If we look at the wsdl file, the culprit is in the last few lines of the file - we see this:
<service name="#NAME#"> <port name="MapServerPort" binding="e:MapServerBinding"> <soap:address location="#URL#"/> </port> </service>
I'm betting that the #NAME# and #URL# are tokens which get replaced when you get the WSDL from a live service (i.e. http://myserver/arcgis/services/mytestService/MapServer?wsdl ). So - the fix is pretty simple - just edit your copy of the wsdl file, and assign the name to whatever you want the proxy class to be called. In my case, I set the name to "MapServiceProxy" and the Url to http://localhost/use/app.settings to remind myself to always configure the url in the app settings (the "key" is part of the wsdl command line --> /urlkey)
Note: I think you can use Add Web Reference and just point to your own local "fixed" copy of the WSDL file, and this will produce nicely named proxy classes - I did not test this since I'd already baked my own using wsdl.exe
Anyhow - I've created a set of proxy classes (VB.NET and C#), and a batch file for cooking them yourself. Grab it here: ags-proxy.zip [UPDATE - link now works]
I'm Dave and this is my blog. I'm usually writing about .NET Software Development, ArcGIS, or Agile Practices, but other stuff does creep in from time to time. I hope you find something of use, and feel free to contact me if you have any questions. You can also check out my profile on LinkedIn
dojo.DTSAgile.com is our technology preview / demo site. As I and my team cook up cool things we post them here.
ArcDeveloper.net is a site that hosts a set of open source projects related to ArcGIS. This includes Tile Cache for .NET (TC4N) and Feature Server for .NET (FS4N). Come over and check it out!
Assembla is a free service that provides Subversion source control, wikis and work Tracking. The ArcDeveloper project is run from here. It rocks. Check them out today.
Agilistas is a LinkedIn group focused on discussing and promoting Agile practices. Everyone is welcome to join in the conversation as we evolve the process of creating software to make it more enjoyable for all involved.