Geospatial and location based services became very popular these days. One concern for developers of such applications is how to represent the data in the system. This includes simple data types such as points or coordinate systems and complex ones such as advanced topologies. The correct approach is of course to use types from the standard schema set of the Open Geospatial Consortium (OGC).
For a .Net developer this may imply the following needs:
Use xsd.exe to generate classes for serizliation
Create .Net 2.0 / WCF web services that utilize these schemas
Consume Wsdl's with these schemas
Unfortunetely the OpenGIS standard schemas are not interoperable with .Net. This has already been noticed by developers for older OpenGIS versions but newer versions seem to be equality incompatible.
If you only want the fix without the details download it here and see in the end of the post the fix details:
Here are some of the errors one gets when trying to consume Gml 3.1.1 and Gml 3.2.1 schemas in .Net:
Gml 3.1.1 - WCF
While using "add service reference" we get this error:
And after this an empty proxy code is generated:
Gml 3.1.1 - .Net 2.0
The wsdl importing stage seems to work fine. Let's build a one line client:
Such a simple client - what can possibly go wrong? Well nothing, except this:
And this is after I have omitted some inner exceptions.
In some cases (depending on .Net 2.0 patch level) the below exception will appear - not much improvement:
Finally, depending in the types we reference, we might get this one as well:
Gml 3.2.1 - WCF
Proxy is generated but the simplest client throws this exception chain:
Gml 3.2.1 - .Net 2.0
Guess what?
Why these errors happen?
The errors appear in run-time when we instantiate the client proxy or web service. At this stage .Net creates the serialization assembly for each type and fails to do it for the proxy. Actually if we have marked the "generate serialization assembly" build option we could already see these errors in compile time.
Now what?
We need to fix the schemas or the proxy in order to make them interoperable with .Net. The fix must be compatible with the original schema, so it may change the schema syntax but must result in an isomorphic schema.
Making Gml 3.2.1 work
There are two reasons for this schema incomparability:
Cyclic schema references
From gml.xsd:
From deprecatedTypes.xsd:
One way to solve this is to remove deprecatedTypes.xsd altogether - it is not really required. We'll be nicer and just replace inside it the reference to gml.xsd with these direct references:
Non-string lists
.Net does not support the xsd:list data type. When the list is of strings it works anyway since unresolved types are treated as strings. But for other types it is not supported. MSDN contains some more information on xsd:list support in .Net.
basicTypes.xsd contains this:
Which becomes this in the .Net proxy:
which causes a run-time error since the XmlTextAttribute is only appropriate on strings.
The solutions is to replace all non-string lists in the schema to strings so the above becomes:
And after this Gml 3.2.1 classes are serializable by .Net!
Making Gml 3.1.1 work
This version has two issues:
Same issue with lists as in 3.2.1 - same fix
I've seen this one a couple of times. Basically when there is a multidimensional array of a type which has a single child element in some cases .Net code generation is incorrect. Don't ask, long story... Just replace in geometryPrimitives.xsd:
With:
And we have 3.1.1 working as well!
Download fix
I have uploaded the fixed schemas to save your time:
After you extract the zip the fixed schemas are in the below folders:
Maybe the formatting in the comments is not good - it is the same command as suggested here http://oegeo.wordpress.com/2008/04/10/importing-the-gml-321-namespace-into-net/
The xsd.exe command you gave to build classes work only if you use GML 3.1.2. Can you please post the command for creating classes of GML 3.1.1. If you use the same command (even after fixing the resolution of directory), a lot of errors and warning come up.
Just an update. I have modified the command to the following: xsd.exe gml.xsd ..\smil\smil20.xsd ..\smil\smil20-language.xsd ..\..\..\xlink/1.0.0\xlinks.xsd ..\..\..\iso\19139\20060504\gmd\gmd.xsd ..\..\..\iso\19139\20060504\gco\gco.xsd ..\..\..\iso\19139\20060504\gss\gss.xsd ..\..\..\iso\19139\20060504\gts\gts.xsd ..\..\..\iso\19139\20060504\gsr\gsr.xsd /classes
It causes less errors and warnings but still some errors left. Could you please have a look and see what else I can do.
I have no experience whatsoever on GMX/XML with C#. I want to read Oracle spatial objects as GML 3.0. Can the classes you describe help me to create 3D geometry classes in C# from a GML 3.0 stream? And what would be the steps to do so?
I do not have experience with the graphics itself so I cannot help. Generally the gml classes are just the model for the xml. Maybe there are other libraries that can actually create the graphic objects.
I succesfully implemented the fixes working on a c# client in VS2008. I'm using the Java built service at http://www.dinoservices.nl/geo3dmodelwebservices-1/Geo3DModelService?wsdl. I've added it as a WebReference as suggested in one of your other posts.
However, all the GML made available through this service seems to disappear in the proxy. Included is a response (to the listModels request) as seen by SoapUI: area xsi:type="ns2:PolygonType" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ns2:exterior ns2:LinearRing srsName="urn:ogc:def:crs:EPSG::0" ns2:posList srsDimension="2"275550.0 531050.0 275550.0 514550.0 275550.0 498050.0 275550.0 481550.0 275550.0 465050.0 261050.0 465050.0 261050.0 448550.0 261050.0 432050.0 246550.0 432050.0 246550.0 415550.0 232050.0 415550.0 217550.0 415550.0 203050.0 415550.0 203050.0 399050.0 203050.0 382550.0 203050.0 366050.0 188550.0 366050.0 174050.0 366050.0 174050.0 349550.0 159550.0 349550.0 145050.0 349550.0 130550.0 349550.0 130550.0 366050.0 116050.0 366050.0 101550.0 366050.0 87050.0 366050.0 72550.0 366050.0 72550.0 349550.0 58050.0 349550.0 43550.0 349550.0 29050.0 349550.0 14550.0 349550.0 14550.0 366050.0 50.0 366050.0 50.0 382550.0 14550.0 382550.0 14550.0 399050.0 14550.0 415550.0 29050.0 415550.0 29050.0 432050.0 43550.0 432050.0 58050.0 432050.0 58050.0 448550.0 58050.0 465050.0 72550.0 465050.0 72550.0 481550.0 87050.0 481550.0 87050.0 498050.0 87050.0 514550.0 101550.0 514550.0 101550.0 531050.0 101550.0 547550.0 101550.0 564050.0 101550.0 580550.0 116050.0 580550.0 130550.0 580550.0 145050.0 580550.0 145050.0 597050.0 159550.0 597050.0 174050.0 597050.0 174050.0 613550.0 188550.0 613550.0 203050.0 613550.0 217550.0 613550.0 217550.0 597050.0 232050.0 597050.0 246550.0 597050.0 261050.0 597050.0 275550.0 597050.0 280050.0 597050.0 280050.0 580550.0 280050.0 564050.0 280050.0 547550.0 275550.0 547550.0 275550.0 531050.0/ns2:posList /ns2:LinearRing /ns2:exterior /area However, in the proxy class the model.area property contains an empty (null) exterior ring. Any ideas how and where this can happen?
Try to create the model class from the proxy type and apply xml serialization on it. Then check how the serialized xml differes from the above (WRT the area element)
Oops. This is way over my head for a first time Soap client developer. How do I create the model class from the proxy type and apply xml serialization on it?
That's exactly what I did. I created the proxy from the wsdl (http://www.dinoservices.nl/geo3dmodelwebservices-1/Geo3DModelService?wsd) using add Web reference in VS. Then I applied the fixes (replacing double[] for string [] and replacing [][] with [] in the indicated places) you mentioned in reference.cs. Most of the proxy works OK, except for all the GML stuff. Any method that's supposed to return a geometry returns a Null. Using the SoapUI desktop client I noticed that the problem is not on the server side as SoapUI is able to retrieve the geometries. Any suggestions how to attack this problem?
As i am developing for another part of the DinoService (uitwisselservice) and i'm encountering the same problem with .Net & GML, maybe we should contact ? Serialization from MultiSurfaceType does not play well as well as some other issues ..
18 comments:
Thank you!
Exactly what I needed!
Mosish
Yaron,
This is greatly appreciated. When using XSD I am still getting many errors - relating to gmd then gcd...
PLease could you post the steps to create the final C# class? - or better still the class itself?
Cheers
Mike
Mike
If you extract the zip and in the vs command prompt go to "opengis_net_fixed\gml\3.2.1_Fixed"folder then run this:
xsd.exe gml.xsd ..\..\xlink/1.0.0\xlinks.xsd ..\..\iso\19139\20070417\gmd\gmd.xsd ..\..\iso\19139\20070417\gco\gco.xsd ..\..\iso\19139\20070417\gss\gss.xsd ..\..\iso\19139\20070417\gts\gts.xsd ..\..\iso\19139\20070417\gsr\gsr.xsd /classes
This should create the classes
Maybe the formatting in the comments is not good - it is the same command as suggested here http://oegeo.wordpress.com/2008/04/10/importing-the-gml-321-namespace-into-net/
Yaron,
The xsd.exe command you gave to build classes work only if you use GML 3.1.2. Can you please post the command for creating classes of GML 3.1.1. If you use the same command (even after fixing the resolution of directory), a lot of errors and warning come up.
Cheers,
Javed
Hi,
Just an update. I have modified the command to the following:
xsd.exe gml.xsd ..\smil\smil20.xsd ..\smil\smil20-language.xsd ..\..\..\xlink/1.0.0\xlinks.xsd ..\..\..\iso\19139\20060504\gmd\gmd.xsd ..\..\..\iso\19139\20060504\gco\gco.xsd ..\..\..\iso\19139\20060504\gss\gss.xsd ..\..\..\iso\19139\20060504\gts\gts.xsd ..\..\..\iso\19139\20060504\gsr\gsr.xsd /classes
It causes less errors and warnings but still some errors left. Could you please have a look and see what else I can do.
Cheers,
Javed
Anonymous
Try this:
xsd.exe gml.xsd ..\smil\smil20.xsd ..\smil\smil20-language.xsd ..\..\..\xli
nk/1.0.0\xlinks.xsd ..\..\..\iso\19139\20060504\gmd\gmd.xsd ..\..\..\iso\19139\2
0060504\gco\gco.xsd ..\..\..\iso\19139\20060504\gss\gss.xsd ..\..\..\iso\19139\2
0060504\gts\gts.xsd ..\..\..\iso\19139\20060504\gsr\gsr.xsd ..\..\..\iso\19139\2
0060504\gml\temporal.xsd ..\..\..\iso\19139\20060504\gml\basicTypes.xsd ..\..\..
\iso\19139\20060504\gml\geometryBasic0d1d.xsd ..\..\..\iso\19139\20060504\gml\r
eferenceSystems.xsd /classes
Hi Yaron,
I have no experience whatsoever on GMX/XML with C#. I want to read Oracle spatial objects as GML 3.0. Can the classes you describe help me to create 3D geometry classes in C# from a GML 3.0 stream? And what would be the steps to do so?
Cheers,
Tom
Hi Tom
I do not have experience with the graphics itself so I cannot help. Generally the gml classes are just the model for the xml. Maybe there are other libraries that can actually create the graphic objects.
Hi Yaron,
I succesfully implemented the fixes working on a c# client in VS2008. I'm using the Java built service at http://www.dinoservices.nl/geo3dmodelwebservices-1/Geo3DModelService?wsdl. I've added it as a WebReference as suggested in one of your other posts.
However, all the GML made available through this service seems to disappear in the proxy. Included is a response (to the listModels request) as seen by SoapUI:
area xsi:type="ns2:PolygonType" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
ns2:exterior
ns2:LinearRing srsName="urn:ogc:def:crs:EPSG::0"
ns2:posList srsDimension="2"275550.0 531050.0 275550.0 514550.0 275550.0 498050.0 275550.0 481550.0 275550.0 465050.0 261050.0 465050.0 261050.0 448550.0 261050.0 432050.0 246550.0 432050.0 246550.0 415550.0 232050.0 415550.0 217550.0 415550.0 203050.0 415550.0 203050.0 399050.0 203050.0 382550.0 203050.0 366050.0 188550.0 366050.0 174050.0 366050.0 174050.0 349550.0 159550.0 349550.0 145050.0 349550.0 130550.0 349550.0 130550.0 366050.0 116050.0 366050.0 101550.0 366050.0 87050.0 366050.0 72550.0 366050.0 72550.0 349550.0 58050.0 349550.0 43550.0 349550.0 29050.0 349550.0 14550.0 349550.0 14550.0 366050.0 50.0 366050.0 50.0 382550.0 14550.0 382550.0 14550.0 399050.0 14550.0 415550.0 29050.0 415550.0 29050.0 432050.0 43550.0 432050.0 58050.0 432050.0 58050.0 448550.0 58050.0 465050.0 72550.0 465050.0 72550.0 481550.0 87050.0 481550.0 87050.0 498050.0 87050.0 514550.0 101550.0 514550.0 101550.0 531050.0 101550.0 547550.0 101550.0 564050.0 101550.0 580550.0 116050.0 580550.0 130550.0 580550.0 145050.0 580550.0 145050.0 597050.0 159550.0 597050.0 174050.0 597050.0 174050.0 613550.0 188550.0 613550.0 203050.0 613550.0 217550.0 613550.0 217550.0 597050.0 232050.0 597050.0 246550.0 597050.0 261050.0 597050.0 275550.0 597050.0 280050.0 597050.0 280050.0 580550.0 280050.0 564050.0 280050.0 547550.0 275550.0 547550.0 275550.0 531050.0/ns2:posList
/ns2:LinearRing
/ns2:exterior
/area
However, in the proxy class the model.area property contains an empty (null) exterior ring. Any ideas how and where this can happen?
Marc
Compukab
Try to create the model class from the proxy type and apply xml serialization on it. Then check how the serialized xml differes from the above (WRT the area element)
Hi Yaron,
Oops. This is way over my head for a first time Soap client developer. How do I create the model class from the proxy type and apply xml serialization on it?
Marc
Marc
Is there a wsdl to the web service? If so you should do "add web reference" from visual studio to create the client proxy.
Hi Yaron,
That's exactly what I did. I created the proxy from the wsdl (http://www.dinoservices.nl/geo3dmodelwebservices-1/Geo3DModelService?wsd) using add Web reference in VS. Then I applied the fixes (replacing double[] for string [] and replacing [][] with [] in the indicated places) you mentioned in reference.cs. Most of the proxy works OK, except for all the GML stuff. Any method that's supposed to return a geometry returns a Null. Using the SoapUI desktop client I noticed that the problem is not on the server side as SoapUI is able to retrieve the geometries. Any suggestions how to attack this problem?
Marc
If you have a response which is relatively small please mail it to me, together with reference.cs
@Marc,
As i am developing for another part of the DinoService (uitwisselservice) and i'm encountering the same problem with .Net & GML, maybe we should contact ? Serialization from MultiSurfaceType does not play well as well as some other issues ..
Mail me g.postma[at]nazcai.nl
This page saves me time and time again. Thanks!
Hi,
I use this command to build the c# classes. "xsd.exe gml.xsd ..\smil\smil20.xsd ..\smil\smil20-language.xsd ..\..\..\xli
nk/1.0.0\xlinks.xsd ..\..\..\iso\19139\20060504\gmd\gmd.xsd ..\..\..\iso\19139\2
0060504\gco\gco.xsd ..\..\..\iso\19139\20060504\gss\gss.xsd ..\..\..\iso\19139\2
0060504\gts\gts.xsd ..\..\..\iso\19139\20060504\gsr\gsr.xsd ..\..\..\iso\19139\2
0060504\gml\temporal.xsd ..\..\..\iso\19139\20060504\gml\basicTypes.xsd ..\..\..
\iso\19139\20060504\gml\geometryBasic0d1d.xsd ..\..\..\iso\19139\20060504\gml\r
eferenceSystems.xsd /classes "
But i dont know which is the starting class to work with the XmlSerializer.
So which type i have to use?
XmlSerializer mySerializer = new XmlSerializer(typeof(???));
Post a Comment