C#.NET Generating web service reference using WSDL (from XML schema) problem - c#

I am using VS2010 and using the "add service reference" feature, to generate client classes from my WSDL. I am having a problem with one of my elements, which is defined in the WSDL as follows:
<xs:simpleType name="NumberType">
<xs:restriction base="xs:string">
<xs:enumeration value="ONE" />
<xs:enumeration value="TWO" />
<xs:enumeration value="THREE" />
</xs:restriction>
</xs:simpleType>
This type is used in one of my elements like this:
<xs:element name="NumberTypes">
<xs:simpleType>
<xs:list itemType="tns:NumberType" />
</xs:simpleType>
</xs:element>
The problem is that VS is converting this particular element to a string type, when it should be an enumeration. so it converts it to a string NumberTypes which has a get method returning numberTypesField also of type string.
I think the problem is related to the fact that my schema NumberTypes element uses the xs:list, with 'itemType' attribute. if I change this to xs:element with type="tns:NumberType" attribute instead then the enumeration is generated as it should be.
So how can I make the enumeration work with xs:list? Why is it not converting correctly in the first place?
Thanks for any help.

I haven't had much luck getting xs:list to serialize properly. Instead, I just allow for multiple instances of the same node, and .NET knows how to put it into a "list" or "array" properly.
<xs:element minOccurs="0" maxOccurs="unbounded" name="NumberTypes">
...
</xs:element>

Related

XML Schema Union getting "string" is not valid for the element error

I am an experienced programmer but just recently took on a job maintaining an app that uses xml schema. They want to add some validation on an item that accepts Longitude. They want to continue to accept a blank and also 0, 0.0000000, or if another value is entered they want to make sure that at the least it is in the United States. (i.e. between -125 and -67)
The current xml schema simply allows any value.
<xs:element name="Location">
<xs:complexType>
<xs:sequence>
<xs:element name="LocLongitude"/>
</xs:sequence>
</xs:complexType>
</xs:element>
There are multiple venders sending this info in. Here is an example of what they may send:
<Location>
<LocLongitude xsi:type="xsd:string"></LocLongitude>
</Location>
Now looking at what the users want I found that I can use a union to encapsulate multiple checks. This is what I am using now.
<xs:element name="Location">
<xs:complexType>
<xs:sequence>
<xs:element name="LocLongitude" nillable="true">
<xs:simpleType>
<xs:union>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value=""/>
<xs:enumeration value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType>
<xs:restriction base="xs:double">
<xs:minInclusive value="0.00000000"/>
<xs:maxInclusive value="0.00000000"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType>
<xs:restriction base="xs:double">
<xs:minInclusive value="-125"/>
<xs:maxInclusive value="-67"/>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
It validates correctly if I use:
<Location>
<LocLongitude />
</Location>
Now if I use what the current vendors are using (see below):
<Location>
<LocLongitude xsi:type="xsd:string"></LocLongitude>
</Location>
We get an error:
THE XSI:TYPE ATTRIBUTE VALUE '' IS NOT VALID FOR THE ELEMENT 'LOCLONGITUDE', EITHER BECAUSE IT IS NOT A TYPE VALIDLY DERIVED FROM THE TYPE IN THE SCHEMA, OR BECAUSE IT HAS XSI:TYPE DERIVATION BLOCKED.
My question is, can I get this to work while still allowing the vendors to include xsi:type="xsd:string"?
No, the type chosen for xs:type must be validly derived from the type provided by the associated element. You cannot on the one hand define a type that restricts the value space and on the other hand supports a broader xs:type declaration.
See also: How to restrict the value of an XML element using xsi:type in XSD?

How to write a XSD to validate random element names?

I have written an application which receives many variation of XML requests. In our business we have to validate XMLs against XSD at the beginning of any request.
The problem:
As I said above I have to validate them at the beginning and those XMLs have almost the same schema and I need to write a general XSD for them.
I have provided some prototype XML for my question:
XML1:
<_9D94DEB4-7C2D-45A5-A4FB-89FB1CF20672>
<Param1>value</Param1>
<Type>Category</Type>
</_9D94DEB4-7C2D-45A5-A4FB-89FB1CF20672>
XML2: Almost the same schema but root element name is different and it has an extra child element.
<_7603DCD1-F270-43EA-86E3-0FB3161478F6>
<Param1>value</Param1>
<Type>Page</Type>
<SearchText>Sample</SearchText>
</_7603DCD1-F270-43EA-86E3-0FB3161478F6>
As you can see the root element names are different but their schema is almost the same, How could I write a general XSD for them?
Thanks in advance.
The only thing these two XML instances have in common is that both have a Type element whose value is a string. Calling that "almost the same schema" seems rather an exageration. But perhaps there is more commonality than you have shown us?
In principle XSD allows you to validate the instance against a global type in your schema, irrespective of the element name. Whether your particular schema processor provides an API to do that is another question.
Your schema could then simply define the top-level type:
<xs:complexType name="myTopLevelType">
<xs:sequence>
<xs:element name="Param1" type="xs:string"/>
<xs:element name="Type" type="xs:string"/>
etc
</xs:sequence>
</xs:complexType>
If you choose Saxon as your schema validator then you can invoke "validation-by-type" from the Java API but not from the command line. In fact, probably the easiest way to do it is to invoke the validation from XSLT:
<xsl:import-schema schemaLocation="mySchema.xsd"/>
then:
<xsl:copy-of select="doc('instance.xml')/*" type="myTopLevelType"/>
All you need to do is write each of roots as direct children of your schema element and define types in your XSD.
For example:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="_9D94DEB4-7C2D-45A5-A4FB-89FB1CF20672">
...
<xs:complexType>
<xs:attribute name="Param2" type="Param2" use="required">
</xs:attribute>
<xs:attribute name="Type" type="Type" use="required">
</xs:attribute>
<xs:attribute name="SearchText" type="SearchText" use="required">
</xs:attribute>
</xs:complexType>
...
</xs:element>
<xs:element name="_7603DCD1-F270-43EA-86E3-0FB3161478F6">
...
<xs:complexType>
<xs:attribute name="Param1" type="Param1" use="required">
</xs:attribute>
<xs:attribute name="Type" type="Type" use="required">
</xs:attribute>
</xs:complexType>
...
</xs:element>
</xs:schema>
<!-- Your defenition and restriction of types-->
<xs:simpleType name="Param1">
<xs:restriction base="xs:string">
</xs:simpleType>
<xs:simpleType name="Param2">
<xs:restriction base="xs:string">
</xs:simpleType>
<xs:simpleType name="Type">
<xs:restriction base="xs:string">
</xs:simpleType>
<xs:simpleType name="SearchText">
<xs:restriction base="xs:string">
</xs:simpleType>

WCF Schema common elements always null

I am using xsd to generate the object available in the OperationContract. The address, city, state and zip elements of the XSD are common
<xs:element name="Address" nillable="true">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="50"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
and used throughout the XML.
<xs:element ref="Address" />
When I compile the schema the classes generate correctly using the common elements.
When I run the service the OperationContext contains the expected request from the client:
<NameLast>Last</NameLast>
<NameFirst>First</NameFirst>
<Address xmlns="http://tempuri.org/">123 2nd St</Address>
<City xmlns="http://tempuri.org/">Somewhere</City>
However the common elements have the xmlns attribute (shown above) and in the received object all common elements contain null values.
My reputation is not high enough to show screenshot, but all data NOT in common elements are passed correct. Such as NameLast = "Last", Address = Null.
I am new to using Schemas and would appreciate any direction. Thanks.
I believe what you want is this, placed before your closing </xs:schema> tag:
<xs:simpleType name="AddressType">
<xs:restriction base="xs:string">
<xs:maxLength value="50"/>
</xs:restriction>
</xs:simpleType>
and used throughout the schema:
<xs:element name="Address" type="AddressType" />

Error parsing an XSD schema - Undefined complexType

I'm currently trying to add this XSD as a Service Reference to My ASP .Net MVC 4 project (http://voip.letscall.pt/PortalWebAPI/metadata?xsd=1). The problem is that whether I'm doing something wrong or the file has some kind of problem.
When I try to use the XSD.exe to parse the XSD, it gives me this error
Undefined complexType
'http://schemas.datacontract.org/2004/07/VS.PortalWebAPI:SupportTypes:Paging'
is used as a base for complex type extension.
The Paging SupportType is used on complexTypes, such as
<xs:complexType name="GetPbxCompanyContacts">
<xs:complexContent mixed="false">
<xs:extension xmlns:q13="http://schemas.datacontract.org/2004/07/VS.PortalWebAPI.API.SupportTypes" base="q13:Paging">
<xs:sequence>
<xs:element minOccurs="0" name="BranchId" type="xs:int" />
<xs:element minOccurs="0" name="Login" nillable="true" type="xs:string" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="GetPbxCompanyContacts" nillable="true" type="tns:GetPbxCompanyContacts" />
The PortalWebAPI has 5 files:
XSDS
Service Types (voip.letscall.pt/PortalWebAPI/metadata?xsd=1)
Wcf Data Types (voip.letscall.pt/PortalWebAPI/metadata?xsd=0)
Wcf Collection Types (voip.letscall.pt/PortalWebAPI/metadata?xsd=2)
WSDLS
soap11 (voip.letscall.pt/PortalWebAPI/soap11)
soap12 (voip.letscall.pt/PortalWebAPI/soap12)
However, I've still not managed to find how to use it. Do I need only one, or do I need to import all?
I've also tried to add it straight to the project, through References -> Add Service Reference, only one or all of them, but no luck.
There should be a complexType named Paging in the XML schema document which has the target namespace mapped to the q13 prefix. Look for the document with:
targetNamespace="http://schemas.datacontract.org/2004/07/VS.PortalWebAPI.API.SupportTypes"
It should contain the Paging type.
You also should have an xs:import statement:
<xs:import namespace="http://schemas.datacontract.org/2004/07/VS.PortalWebAPI.API.SupportTypes"
schemaLocation="/path/to/your-schema.xsd"/>
If the Paging type is not declared in that namespace, or if you don't import the schema, it will not be found when you try to use it in your extension.

XSD, restrictions and code generation

I'm working on some code generation for an existing project and I want to start from a xsd. So I can use tools as Xsd2Code / xsd.exe to generate the code and also the use the xsd to validate the xml. That part works without any problems.
I also want to translate some of the restrictions to DataAnnotations (enrich Xsd2Code).
For example xs:minInclusive / xs:maxInclusive I can translate to a RangeAttribute.
But what to do with custom validation attributes that we created? Can I add custom facets / restrictions? And how? Or is there another solution / best practice.
I would like to collect everything in a single (xsd) file so that one file contains the structure of the class (model) including the validation (attributes) that has to be added.
<xs:element name="CertainValue">
<xs:simpleType>
<xs:restriction base="xs:double">
<xs:minInclusive value="1" />
<xs:maxInclusive value="100" />
<xs_custom:customRule attribute="value" />
</xs:restriction>
</xs:simpleType>
</xs:element>
XML schema is itself schema constrained, so you can't add an arbitrary (in its eyes) element. There is a facility for adding anything you like, xs:annotation/xs:appinfo, that's available for addition to most nodes. Perhaps try something like this:
<xs:element name="CertainValue">
<xs:simpleType>
<xs:restriction base="xs:double">
<xs:annotation>
<xs:appinfo>
<xs_custom:customRule attribute="value" />
</xs:appinfo>
</xs:annotation>
<xs:minInclusive value="1" />
<xs:maxInclusive value="100" />
</xs:restriction>
</xs:simpleType>
It depends on where Xsd2Code is looking for the stuff, but if they expect XSDs passed in to validate, appinfo is probably their only choice. Just which element to add the appinfo on it also of question.

Categories

Resources