Consuming WSDL with multidimentional array with WSDL.exe fails - c#

I have the following in a WSDL I am consuming;
<xsd:complexType name="SomeClassType">
<xsd:sequence>
<xsd:element type="xsd:string" name="errorMessage" minOccurs="1" nillable="true" maxOccurs="1"> </xsd:element>
<xsd:element type="tp:ArrayOfArrayOfString" name="values" minOccurs="1" nillable="true" maxOccurs="1"> </xsd:element>
<xsd:element type="xsd:boolean" name="isEmpty" minOccurs="1" maxOccurs="1"> </xsd:element>
</xsd:sequence>
</xsd:complexType>
where
<xsd:complexType name="ArrayOfArrayOfString">
<xsd:complexContent>
<xsd:restriction base="soapenc:Array">
<xsd:attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[,]"></xsd:attribute>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
However using wsdl.exe from MS (Runtime Version: 1.1.4322.573) generates
public class SomeClassType {
///
public string errorMessage;
///
public string[] values;
///
public bool isEmpty;
}
I expected string[,] values not string[] values
Is there a fix or a work around to this problem? (other than manually changing the generated code)

I had to set the type="tp:ArrayOfArrayOfString" to type="tp:ArrayOfString" and the maxOccurs="unbounded"

I believe you could try the WCF proxy generator (I believe WCF uses some other util, not wsdl.exe) - maybe that would be useful, but if that fails - I think that manually editing the generated code is your only option.

Try svcutil.exe. it is advisable to try a newer version of .net.

Related

Is there a way to enforce generating *Specified property in Reference.cs for non-complex type fields in wsdl

Is there a way to actually enforce generating FooSpecified for non-complex types like strings or integers?
The Web Service I am working with defines all record fields as nillable and minOccurs = 0
<xsd:complexType name="Constituent">
<xsd:complexContent mixed="false">
<xsd:extension base="tns:Record">
<xsd:sequence>
<xsd:element minOccurs="0" maxOccurs="1" name="ConsId" nillable="true" type="xsd:nonNegativeInteger" />
<xsd:element minOccurs="0" maxOccurs="1" name="SiteId" nillable="true" type="xsd:nonNegativeInteger" />
<xsd:element minOccurs="0" maxOccurs="1" name="PredupStatus" nillable="true" type="xsd:string" />
It also specifies Update method with Record as argument:
<xsd:element name="Update">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="0" maxOccurs="1" name="PartitionId" nillable="true" type="xsd:nonNegativeInteger" />
<xsd:element minOccurs="0" maxOccurs="1" name="Force" nillable="true" type="xsd:boolean" />
<xsd:element minOccurs="1" maxOccurs="unbounded" name="Record" type="ens:Record" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
Constituent Record has nearly 200 elements, which can be null.
At the same time, Update method on the server side is programmed to ignore all null values if there are more than 10 of them in the update request.
Reference.cs generated from the file does not contain *Specified properties for strings or integers
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.7.3062.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:object.soap.convio.com")]
public partial class Constituent : Record {
private string consIdField;
private string siteIdField;
private string predupStatusField;
private System.Nullable<AdministratorStatus> adminStatusField;
private bool adminStatusFieldSpecified;
hich causes XmlSerializer to generate lines for each field:
<q1:ConsId xsi:nil="true"/>
<q1:SiteId xsi:nil="true"/>
<q1:PredupStatus xsi:nil="true"/>
<q1:AdminStatus xsi:nil="true"/>
<q1:ConsName><q1:Title xsi:nil="true"/>
<q1:FirstName>234234</q1:FirstName>
<q1:MiddleName xsi:nil="true"/>
<q1:LastName>412341234</q1:LastName>
Which works fine until I try to blank a field out. At that point the field I am trying to blank out is being send as null and is being ignored by the server because there are more than 10 null fields in the request. To be able to remove unwanted null lines from serialization I need all fields to have *Specified property and send in the request only the field I want to be null. I can add them manually, but it's a lot of work that I need to remember to save somewhere else to avoid being removed when refreshing service reference...
Alternatively, is there a way to enforce generating ShouldSerialize property in Reference.cs?

C# xsd xmlreader, how to count attribute names

This is probably very simple for you guys, but I need to be able to count the attribute names within an xml document when validating xml against a schema using c#. Specifically duplicate attribute names (not valid).
If my xsd has these in it:
<xsd:schema>
<xsd:complexType name="scheduleEvent">
<xsd:all>
<xsd:element name="Basic" type="MyBasic"/>
</xsd:all>
</xsd:complexType>
<xsd:complexType name="MyBasic">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="Descriptor" type="Descriptor" maxOccurs="1"/>
<xsd:element name="Descriptor1" type="Descriptor1" maxOccurs="1"/>
</xsd:choice>
</xsd:complexType>
<xsd:complexType name="Descriptor">
<xsd:attribute name="Test" type="typ:Test"/>
</xsd:complexType>
<xsd:complexType name="Descriptor1">
<xsd:attribute name="Test1" type="typ:Test1"/>
</xsd:complexType>
And my xml to validate against looks like (not valid, I know just a quick mock up example for reference:
Declarations etc...
<ScheduleEvent>
<MyBasic>
<Descriptor Test="02"/>
<Descriptor1 Test1="02" Test1="02"/>
</MyBasic>
</ScheduleEvent>
How can I count the number of "Test1" attributes? C# xmlreader (without using exceptions, long story).
First of all, that isn't a valid xml. An attribute is unique per element.
If what you ment is that you can have multiple "Test1" attributes throughout the different elements, then you can do the following using LINQ to XML:
var xml = XDocument.Load(#"PathToXml");
var testCount = xml.Descendants().Attributes("Test1").Count();
Try this :
XDocument doc=XDocument.Load(XMLFile or XMLFilePath);
var Sample=doc.Descendants("Test1").Count();

.NET SOAP serialization, omit/remove enclosing tags for generic list<t>

I need to call a Web Service, created by someone else, from a .Net C# application.
The web service requires me to send a list of items ("articles"), without enclosing them in a parent element. This is a simplified illustration of the "desired" look of the call:
<body>
<info>something</info>
<moreinfo>something else</moreinfo>
<article>
<articleno>123</articleno>
</article>
<article>
<articleno>456</articleno>
</article>
</body>
On my end, the articles is a generic List<Article>, and my call to the web service tends to contain something looking more like this:
<body>
<info>something</info>
<moreinfo>something else</moreinfo>
<articles><!-- parent element -->
<article>
<articleno>123</articleno>
</article>
<article>
<articleno>456</articleno>
</article>
</articles><!-- parent element end -->
</body>
The WSDL file from the web service is corrupted, so I've hade to manually create a working subset of the functions in it that I need. Using that "hand coded" WSDL I add a Service Reference using Visual Studio 2013.
I have been trying to solve the problem by modifying the WSDL, and by modifying the code that is created by Visual Studio when adding the service reference, but so far I haven't succeeded.
I've bee trying various attributes for the list parameter, such as XmlElement, XmlIgnore, MessageHeaderArrayAttribute and others, but to be honest I don't know how they work or which ones could actually be useful in this scenario.
Can the WSDL be altered to make Visual Studio's auto generated code create the correct output when calling the web service? (Preferred solution)
Or is there a way to force soap serialization to produce the list of articles without an enclosing element? (Acceptable solution)
Here is a simplified version of the relevant (as far as I can tell) portions of the WSDL
<xsd:element name="PriceRequest">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="0" maxOccurs="1" name="info" type="xsd:string" />
<xsd:element minOccurs="0" maxOccurs="1" name="moreinfo" type="xsd:string" />
<xsd:element minOccurs="0" maxOccurs="1" name="articles" type="tns:ArrayOfArticlestructObj" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
...
<xsd:complexType name="ArticlestructObj">
<xsd:sequence>
<xsd:element minOccurs="0" maxOccurs="1" name="articleno" type="xsd:string" />
<xsd:element minOccurs="0" maxOccurs="1" name="otherinfo..." type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="ArticlestructObj" type="tns:ArticlestructObj" />
<xsd:complexType name="ArrayOfArticlestructObj">
<xsd:sequence>
<xsd:element minOccurs="0" maxOccurs="unbounded" name="ArticlestructObj" nillable="true" type="tns:Articlestruct" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="ArrayOfArticlestruct" type="tns:ArrayOfArticlestruct" />
I am a noob on WSDL as well as on StackOverflow, so please excuse me if this question is hard to read.

path/node order of XSD in C#

Does anyone have an idea about how keep track of a paths in xsd in deep-first traverse
For example: if I have this schema,
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:books" xmlns:bks="urn:books">
<xsd:element name="books" type="bks:BooksForm"/>
<xsd:complexType name="BooksForm">
<xsd:sequence>
<xsd:element name="book" type="bks:BookForm" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="BookForm">
<xsd:sequence>
<xsd:element name="author" type="xsd:string"/>
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="genre" type="xsd:string"/>
<xsd:element name="price" type="xsd:float" />
<xsd:element name="pub_date" type="xsd:date" />
<xsd:element name="review" type="xsd:string"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string"/>
</xsd:complexType>
</xsd:schema>
how can I get like this output in c#
path1 : books.book.author
path2 : books.book.title
.. so on
for any schema structure
does anyone have an idea about this or any good starting points
thanks in advance
thanks for reply
I tried to code your advice but I am still getting stuck
while (r.Read())
{
switch (r.Name)
{
case "xsd:element":
myStringBuilder.Append(r.GetAttribute("name"));
break;
case "xsd:complexType":
checkComplex(r);
wholepath += r.GetAttribute("name");
//this will only concatenate complex elements only
Console.WriteLine("checkComplexcaller{1}", wholepath);
break;
}
}
for recursive part.. I did
public static void checkComplex(/*what I should send here*/)
{
if (r.GetAttribute("name") == "xsd:complexType")
{
//What I sould to do for this recursive
}
else if (r.GetAttribute("name") == "xsd:element")
{
myStringBuilder.Append(r.GetAttribute("name"));
}
}
How could setup the path correctly
If I am getting this right: (pseudocode)
(make a xml document of the xsd)
foreach node of type xsd:element:
track path to the node as input
apend it with values of 'name' and 'type' attributes
if its a complex type: apply this recursively on all elements

.NET xsd importer creates unserializable class

I am using the .NET XSD.EXE importer to generate C# classes from a collection of XSD files. When I tried to serialize one of the classes to XML it failed (InvalidOperationException), and when I dug into it I discovered it one of the created classes appears to be wrong.
Here is the pertinent XSD code:
<xsd:complexType name="SuccessType">
<xsd:annotation>
<xsd:documentation>Indicates in a response message that a request was successfully processed.</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element ref="Warnings" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<!-- .. snip .. -->
<xsd:element name="Warnings" type="WarningsType">
<xsd:annotation>
<xsd:documentation>The processing status of a business message and any related warnings or informational messages.</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- .. snip .. -->
<xsd:complexType name="WarningsType">
<xsd:annotation>
<xsd:documentation>A collection of warnings generated by the successful processing of a business message.</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element ref="Warning" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<!-- .. snip .. -->
<xsd:element name="Warning" type="WarningType">
<xsd:annotation>
<xsd:documentation>Defines details of a warning that occurred during message processing.</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- .. snip .. -->
<xsd:complexType name="WarningType">
<xsd:annotation>
<xsd:documentation>Defines details of a warning that occurred during message processing.</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element ref="WarningCategory"/>
<xsd:element ref="WarningCode"/>
<xsd:element ref="WarningShortMessage"/>
<xsd:element ref="WarningMessage"/>
</xsd:sequence>
</xsd:complexType>
And here is the C# code generated from it:
public partial class SuccessType
{
private WarningType[][] warningsField;
/// <remarks/>
[System.Xml.Serialization.XmlArrayItemAttribute("Warning", typeof(WarningType), IsNullable = false)]
public WarningType[][] Warnings
{
get
{
return this.warningsField;
}
set
{
this.warningsField = value;
}
}
}
It made Warnings an array of an array of WarningType. When I attempt to serialize that to XML I get an InvalidOperationException exception:
Unable to generate a temporary class (result=1).
error CS0030: Cannot convert type 'WarningType[]' to 'WarningType'
error CS0030: Cannot convert type 'WarningType[]' to 'WarningType'
error CS0029: Cannot implicitly convert type 'WarningType' to 'WarningType[]'
error CS0029: Cannot implicitly convert type 'WarningType' to 'WarningType[]'
But if I change the generated code from WarningType[][] to WarningType[] then it serializes fine.
Short of editing the generated C# class whenever I regenerate this (which hopefully will be less frequently going forward), is there any other solution? Is this a bug in xsd.exe or is the XSD file incorrect? Maybe there is a problem in the XmlSerializer?
What I want is C# code that correctly serializes to XML that validates against the XSD. Right now the jagged array seems to be wrong because if I remove it then it generates the XML.
I am using Visual Studio 2008.
There are bugs in the xsd.exe tool. I don't remember this particular one, but I do remember finding problems with jagged arrays, and it's possible this remains a bug. if you're willing, you could use the XsdObjbectGen tool, also from Microsoft, but released independently and out-of-band from the .NET SDK.
One thing you could do is go the reverse direction: write the C# code, then generate the schema with xsd.exe, and see what is different. It's possible xsd.exe wants the schema to look a particular way, in order to correctly generate correct code for jagged arrays.
Actually, upon re-reading your question, you never said what you really wanted. Do you want SuccessType to contain an array-of-arrays, or not?
And is it WarningsType or WarningType? There's some disagreement between the code snips you provided.
Assuming you wanted the array-of-arrays, I wrote this C# code:
public class WarningType
{
public String oof;
}
public partial class SuccessType
{
private WarningType[][] warningsField;
/// <remarks/>
[System.Xml.Serialization.XmlArrayItemAttribute("Warning", typeof(WarningType[]), IsNullable = false)]
public WarningType[][] Warnings
{
get
{
return this.warningsField;
}
set
{
this.warningsField = value;
}
}
}
... then compiled it into a DLL. Then I ran xsd.exe on that DLL, and generated this XSD:
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="WarningType" nillable="true" type="WarningType" />
<xs:complexType name="WarningType">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="oof" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:element name="SuccessType" nillable="true" type="SuccessType" />
<xs:complexType name="SuccessType">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="Warnings" type="ArrayOfArrayOfWarningType" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="ArrayOfArrayOfWarningType">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="Warning" type="ArrayOfWarningType" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="ArrayOfWarningType">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="WarningType" nillable="true" type="WarningType" />
</xs:sequence>
</xs:complexType>
</xs:schema>
...and it round-trips. If I then run xsd.exe on that schema, I get a type that wraps an array-of-arrays.

Categories