Date with timezone not parseable by generated code from WSDL in C# - c#

My C# client has generated service based on WSDL file with these fields:
[System.Xml.Serialization.XmlElementAttribute(DataType="date", Order=6)]
public System.DateTime SomeDate{
get {
return this.SomeDateField;
}
set {
this.SomeDateField = value;
this.RaisePropertyChanged("SomeDate");
}
}
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool SomeDateSpecified {
...
}
Service is sending value
<v12:SomeDate>1972-07-05+01:00</v12:SomeDate>
According to documentation https://www.w3schools.com/xml/schema_dtypes_date.asp
The Xml DataType "date" format should accept the timezone, However I am receiving error:
Error in deserializing body of reply message for operation '...'. ---> System.InvalidOperationException: There is an error in XML document (2, 2047). ---> System.FormatException: String was not recognized as a valid DateTime.
at System.DateTimeParse.ParseExactMultiple(String s, String[] formats, DateTimeFormatInfo dtfi, DateTimeStyles style)
I am aware that I can implement IClientMessageInspector and remove the timezone so it can be parsed, but I would like to avoid this.
The WSDL was provided to me from customer as
<xs:element name="SomeDate" type="xs:date" minOccurs="0">
<xs:annotation>
<xs:documentation>
...
</xs:documentation>
</xs:annotation>
</xs:element>

Related

CDATA section as string using service reference

Using c# and visual studio 2015
I'm working with an external webservice and I have build a service reference using a delivered WSDL. That is all working, and I can call the service, but I get a error because the request is not in correct format...
Part of the service definition is this:
<xsd:complexType name="GCTPLookupRequestType">
<xsd:sequence>
<xsd:element name="gctpMessage" type="xsd:string" minOccurs="1" maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
The gctpMessage is a string element but is expected to contain a CDATA section like this:
<![CDATA[
<Gctp v="1.0">
<System r="CprSoeg">
<Service r="STAM+">
<CprServiceHeader r="STAM+">
<Key>
<Field r="PNR" v="0000000000"/>
</Key>
</CprServiceHeader>
</Service>
</System>
</Gctp>
]]>
If I append this as a string as expected to the gctpMessage property all seems fine, but when I inspect the request using Fiddler I se that it is all wrong:
<gctpMessage>
<![CDATA[<Gctp v="1.0"><System r="CprSoeg"><
Service r="STAM+"><CprServiceHeader r="STAM+"><Key><
Field r="PNR" v="0000000000"/></Key></CprServiceHeader></
Service></System></Gctp>]]>
</gctpMessage>
I know this is caused by the XML serializer enterpreting this as a string and therefore escapes the tags.
But how do I get around this? The WSDL has defined it as a string and I really want to use the service reference but I do not know how to handle this...
Changing the service is not an option.
Any suggestion would be appriciated :)
Just perfect dbc, it did the trick :)
Thanks for that..
[System.Xml.Serialization.XmlIgnore]
public string gctpMessage {
get {
return this.gctpMessageField;
}
set {
this.gctpMessageField = value;
this.RaisePropertyChanged("gctpMessage");
}
}
[System.Xml.Serialization.XmlElementAttribute(Order = 1, ElementName = "gctpMessage")]
public XmlNode[] CDataContent
{
get
{
var dummy = new XmlDocument();
return new XmlNode[] { dummy.CreateCDataSection(gctpMessage) };
}
set
{
if (value == null)
{
gctpMessage = null;
return;
}
if (value.Length != 1)
{
throw new InvalidOperationException(
String.Format(
"Invalid array length {0}", value.Length));
}
gctpMessage = value[0].Value;
}
}

Connecting to Salesforce Problems C#

I am getting the following error and can not seem to figure out why.
An unhandled exception of type 'System.InvalidOperationException' occurred in System.Xml.dll
Additional information: Unable to generate a temporary class (result=1).
error CS0030: Cannot convert type 'iDdataPrep.SFDC.ListViewRecordColumn[]' to 'iDdataPrep.SFDC.ListViewRecordColumn'
error CS0030: Cannot convert type 'iDdataPrep.SFDC.ListViewRecordColumn[]' to 'iDdataPrep.SFDC.ListViewRecordColumn'
error CS0029: Cannot implicitly convert type 'iDdataPrep.SFDC.ListViewRecordColumn' to 'iDdataPrep.SFDC.ListViewRecordColumn[]'
error CS0029: Cannot implicitly convert type 'iDdataPrep.SFDC.ListViewRecordColumn' to 'iDdataPrep.SFDC.ListViewRecordColumn[]'
Here is my code:
public static void sfLogin()
{
string userName = "***";
string password = "***";
string securityToken = "***";
SFDC.SforceService sfdcBinding = null;
SFDC.LoginResult currentLoginResult = null;
sfdcBinding = new SFDC.SforceService();
try
{
currentLoginResult = sfdcBinding.login(userName, password);
}
catch (System.Web.Services.Protocols.SoapException ex)
{
sfdcBinding = null;
MessageBox.Show(ex.Message);
}
catch(Exception ex)
{
sfdcBinding = null;
MessageBox.Show(ex.Message);
}
sfdcBinding.Url = currentLoginResult.serverUrl;
sfdcBinding.SessionHeaderValue = new SFDC.SessionHeader();
sfdcBinding.SessionHeaderValue.sessionId = currentLoginResult.sessionId;
}
Some .Net integrations with Salesforce do fail due to a bug in .NET's XmlSerializer as described in the this link.
The workaround is to add the following element to the Enterprise.WSDL.XML file:
<xsd:attribute name="tmp" type="xsd:string" />
in the ListViewRecord section. Your Enterprise.WSDL.XML should look like :
<complexType name="ListViewRecord">
<sequence>
<element name="columns" type="tns:ListViewRecordColumn" maxOccurs="unbounded"/>
</sequence>
<b>
<xsd:attribute name="tmp" type="xsd:string" />
</b>
</complexType>
Check out more in this link.
I just ran into this problem. Here is work around I used. Before you generate the proxy file from the wsdl (such as partner.wsdl), edit the file and add a dummy field to the ListViewRecord defintion.
<complexType name="ListViewRecord">
<sequence>
<element name="columns" type="tns:ListViewRecordColumn" minOccurs="1" maxOccurs="unbounded"/>
<element name="dummy" type="xsd:int"/>
</sequence>
</complexType>
When you generate the proxy file with wsdl.exe it will generate the classes ListViewRecord and ListViewRecordColumn correctly. Then delete the dummy field from the generated code and the classes and properties will be defined as they should be.
public partial class ListViewRecord {
private ListViewRecordColumn[] columnsField;
/// ** delete this member variable **
private int dummyField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("columns")]
public ListViewRecordColumn[] columns {
get {
return this.columnsField;
}
set {
this.columnsField = value;
}
}
/// ** delete this property **
public int dummy {
get {
return this.dummyField;
}
set {
this.dummyField = value;
}
}
}
There are two references to ListViewRecordColumn[][] in Reference.cs.
Change them both to ListViewRecordColumn[].

C# Deserialize XML to object: There is an error in XML document (3, 2)

I'm trying to deserialize XML into a C# object
I am getting the error:There is an error in XML document (3, 2).
Cannot seem to fix it! Here is the code:
The XSD is:
<?xml version="1.0" encoding="utf-8" ?>
<!--Created with Liquid XML Studio 2012 Developer Edition (Trial) 10.0.2.3955 (http://www.liquid-technologies.com)-->
<xs:schema xmlns:tns="http://www.adamroe.com/xsd/cameras.xsd" elementFormDefault="qualified" targetNamespace="http://www.adamroe.com/xsd/cameras.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="CameraBase">
<xs:complexType>
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="Cameras">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="Camera" type="tns:CameraType" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="CameraType">
<xs:sequence>
<xs:element name="Make" type="xs:string" />
<xs:element name="Model" type="xs:string" />
<xs:element name="Variable1" type="xs:double" />
<xs:element name="Variable2" type="xs:double" />
</xs:sequence>
</xs:complexType>
</xs:schema>
The XML is:
<?xml version="1.0" encoding="utf-8"?>
<!-- Created with Liquid XML Studio 2012 Developer Edition (Trial) 10.0.2.3955 (http://www.liquid-technologies.com) -->
<aroe:CameraBase xmlns:aroe="http://www.adamroe.com/xsd/cameras.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.adamroe.com/xsd/cameras.xsd C:\Users\Adam\Desktop\Cameras.xsd">
<aroe:Cameras>
<aroe:Camera>
<aroe:Make>SONY</aroe:Make>
<aroe:Model>DSC-W130</aroe:Model>
<aroe:Variable1>0.6352</aroe:Variable1>
<aroe:Variable2>22.375</aroe:Variable2>
</aroe:Camera>
<aroe:Camera>
<aroe:Make>Panasonic</aroe:Make>
<aroe:Model>DMC-FX30</aroe:Model>
<aroe:Variable1>0.8869</aroe:Variable1>
<aroe:Variable2>24.73</aroe:Variable2>
</aroe:Camera>
<aroe:Camera>
<aroe:Make>Olympus</aroe:Make>
<aroe:Model>X450</aroe:Model>
<aroe:Variable1>0.6003</aroe:Variable1>
<aroe:Variable2>20.654</aroe:Variable2>
</aroe:Camera>
<aroe:Camera>
<aroe:Make>Fujifilm</aroe:Make>
<aroe:Model>FinePix S9600</aroe:Model>
<aroe:Variable1>1.0024</aroe:Variable1>
<aroe:Variable2>35.704</aroe:Variable2>
</aroe:Camera>
<aroe:Camera>
<aroe:Make>Canon</aroe:Make>
<aroe:Model>EOS 400D</aroe:Model>
<aroe:Variable1>1.5143</aroe:Variable1>
<aroe:Variable2>69.409</aroe:Variable2>
</aroe:Camera>
</aroe:Cameras>
</aroe:CameraBase>
The class is:
public class Camera
{
public string Make;
public string Model;
public double Variable1;
public double Variable2;
}
Deserialize code:
public class PopulateXML
{
public void DeserializeObject(string filenameXML)
{
Console.WriteLine("Reading with XmlReader");
// Create an instance of the XmlSerializer specifying type and namespace.
XmlSerializer serializer = new
XmlSerializer(typeof(List<Camera>));
// A FileStream is needed to read the XML document.
FileStream fs = new FileStream(filenameXML, FileMode.Open);
XmlReader reader = new XmlTextReader(fs);
// Declare an object variable of the type to be deserialized.
List<Camera> i;
// Use the Deserialize method to restore the object's state.
i = (List<Camera>)serializer.Deserialize(reader);
}
}
Main:
PopulateXML x = new PopulateXML();
// Read a purchase order.
x.DeserializeObject("Cameras.xml");
The exception is thrown on: i = (List)serializer.Deserialize(reader);
XmlSerializer serializer = new XmlSerializer(typeof(Camera));
Stream fs = File.OpenRead(filenameXMLpath);
// Use the Deserialize method to restore the object's state.
Camera cam = serializer.Deserialize(fs) as Camera;
This will definitely work for you. In your case it was not working because you were type casting it to the incorrect data type i.e., List. This error generally pops-up whenever developer type cast deserialized object to incorrect data type.
You could use LinqToXml and these extensions: http://searisen.com/xmllib/extensions.wiki to parse the Xml easily.
XElement root = XElement.Load(file); // or .Parse(string)
List<Camera> cameras = root.GetEnumerable("Cameras/Camera", x => new Camera()
{
Make = x.Get("Make", string.Empty),
Model = x.Get("Model", string.Empty),
Variable1 = x.Get<double>("Variable1", 0),
Variable2 = x.Get<double>("Variable2", 0)
}).ToList();
PS I've tested it and it works on your xml.
PSS Consider adding this attribute [DebuggerDisplay("{Make} - {Model}")] to your camera class to make viewing the list/array in the debugger nicer.

What is the best way to create an XML document conforming to an XSD Schema?

I have an XSD and I have to generate an XML document to send to the customers of the company I work with. The documents I send will be validated against this XSD schema.
What is the best way to create a XML document conforming to a XSD Schema? I mean, I'm searching for best practices and the like. I'm new to this and while "Googling" around here and there, I found people using XmlTextWriter, DataSet.WriteXml, and others.
DataSet.WriteXml seems to not work well for me. This is what I did:
var ds = new DataSet();
ds.ReadXmlSchema(schemaFile);
ds.Tables["TableName"].Rows.Add("", "", 78, true, DateTime.Now);
...
ds.WriteXml("C:\\xml.xml");
I found it generates a node with NewDataSet, and the nodes are not in the proper order.
XmlTextWriter, I find it a bit long to do... but I will if there is no other choice.
What do you think is the best way to do this? Are there other approaches to do it?
I would put the schema here if it wasn't so long, and if it were relevant to the question.
The mainstream practice in .NET is to use XML Serialization.
In your case, I would do this:
run the xsd.exe too on .XSD to generate source code for classes (xsd /c)
build your app that utilizes those generated classes. Keep in mind you can extend those classes via the "partial classes" technique
in code, instantiate an XmlSerializer, and Serialize the class instances.
Example:
Given this schema:
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Foo" nillable="true" type="Foo" />
<xs:complexType name="Foo">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="Bar" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="Baz" type="UntypedArray" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="UntypedArray">
<xs:choice minOccurs="1" maxOccurs="unbounded">
<xs:element name="Type1" type="Type1" minOccurs="1" maxOccurs="1"/>
<xs:any namespace="##other" processContents="lax" minOccurs="1" maxOccurs="1"/>
</xs:choice>
</xs:complexType>
<xs:complexType name="Type1" mixed="true">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="Child" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:schema>
xsd.exe generates this source code:
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=true)]
public partial class Foo {
private string barField;
private object[] bazField;
/// <remarks/>
public string Bar {
get {
return this.barField;
}
set {
this.barField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlArrayItemAttribute("", typeof(System.Xml.XmlElement), IsNullable=false)]
[System.Xml.Serialization.XmlArrayItemAttribute(typeof(Type1), IsNullable=false)]
public object[] Baz {
get {
return this.bazField;
}
set {
this.bazField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class Type1 {
private string childField;
private string[] textField;
/// <remarks/>
public string Child {
get {
return this.childField;
}
set {
this.childField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string[] Text {
get {
return this.textField;
}
set {
this.textField = value;
}
}
}
In your app you can instantiate a Foo and then serialize, like this:
Foo foo = new Foo();
// ...populate foo here...
var builder = new System.Text.StringBuilder();
XmlSerializer s = new XmlSerializer(typeof(Foo));
using ( var writer = System.Xml.XmlWriter.Create(builder))
{
s.Serialize(writer, foo, ns);
}
string rawXml = builder.ToString();
This example serializes into a string. Of course you can serialize to other XmlWriters, you can write out to a file, to any arbitrary stream, and so on.
Normally I tweak the serialization to omit the XML declaration, omit the default xml namespaces, and so on. Like this:
Foo foo = new Foo();
// ...populate foo here...
var builder = new System.Text.StringBuilder();
var settings = new System.Xml.XmlWriterSettings { OmitXmlDeclaration = true, Indent= true };
var ns = new XmlSerializerNamespaces();
ns.Add("","");
XmlSerializer s = new XmlSerializer(typeof(Foo));
using ( var writer = System.Xml.XmlWriter.Create(builder, settings))
{
s.Serialize(writer, foo, ns);
}
string rawXml = builder.ToString();
You can also do the reverse - map from an XML document to an in-memory object graph - using the XmlSerializer. Use the Deserialize method.
A post I wrote a while ago may be of interest to you. I had to work with BizTalk and found that generating my classes from an XSD and then serializing that class over the wire (wa-la XML) worked quite well!
http://blog.andrewsiemer.com/archive/2008/04/30/accepting-xmldocuments-from-biztalk-de-serializing-them-to-xsd-generated-serializable.aspx
This allows you to work with the data as a class and all the perks that go along with that. And it totally allows you to bypass the XML writers!
Such a great reference ..
http://msdn.microsoft.com/en-us/library/x6c1kb0s%28v=vs.110%29.aspx
I just generated classes with fields for csharp:
First you open visual studio command prompt (programs->visualStudio->visualstudioTools->VisualstudioCommandPrompt)
Then you change to the directory of your xsd file and then run the following command:
xsd /classes /fields /language:CS MyXSDSCHEMAFILE.xsd
(replace the MyXSDSCHEMAFILE.xsd with your xsd file name)
After your cs file is created, copy it into your project folder where all the other cs file are and add it to the project in visual studio by right clicking the project and adding existing item. Once that is completed go to your code segment where you want to use your class and initialize like this (classname is the class that was created in the cs file):
classname myvariablename = new classname(); // so easy :)
// now you just fill with content
myvariablename.whatever.andever.field = "JaWerHatDasErfunden";// you just set a field
then serialize as xml (tons of examples on the web )
Useful Hint:
Be aware that instantiation is not always part of the xsd created classes.
Make sure you create your objects properly to avoid Null Pointer exceptions.
You can create the XML and then run it through an Xml Schema Validator that I wrote.

how to generate custom collection type in .Net from WSDL?

I am running a custom application that imports WSDLs and generates C# source code, using WSDLImporter class to read in contracts.
XSD sequence types are translated into native arrays. What options can I set in order to be able to generate custom collection types?
Schema:
<xs:complexType name="getAllSourcesResponse">
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0"
name="return" type="tns:Source"/>
</xs:sequence>
</xs:complexType>
becomes code:
public partial class getAllSourcesResponse
{
[System.Xml.Serialization.XmlElementAttribute("return",
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public PaymentSource[] #return;
public getAllSourcesResponse()
{
}
public getAllSourcesResponse(Source[] #return)
{
this.#return = #return;
}
}
I looked into SvcUtil.exe code, it appears to do the following, but it does not seem to make any difference in what code my application produces.
WsdlImporter importer = ...
XsdDataContractImporter contractImporter =
new XsdDataContractImporter(codeCompileUnit);
ImportOptions importOptions = new ImportOptions();
importOptions.ReferencedCollectionTypes.Add(
typeof(System.Collections.Generic.IList<>));
contractImporter.Options = importOptions;
importer.State.Add(typeof(XsdDataContractImporter), contractImporter);
#CasperOne, this schema snippet
<xs:complexType name="getClassesForPackageResponse">
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="return" type="xs:string"/>
</xs:sequence>
</xs:complexType>
generates a string[] type:
public partial class getClassesForPackageResponse
{
public string[] #return;
public getClassesForPackageResponse() {}
public getClassesForPackageResponse(string[] #return)
{ this.#return = #return; }
}
This does not cause string collection to use List:
ImportOptions importOptions = new ImportOptions();
importOptions.ReferencedCollectionTypes.Add(
typeof(System.Collections.Generic.List<string>));
First, I believe you need to indicate a collection implementation, not just the interface, so that means List<T> instead of IList<T> (although you can certainly try it with the interface).
Second, you need to specify the type parameter T:
ImportOptions importOptions = new ImportOptions();
importOptions.ReferencedCollectionTypes.Add(
typeof(System.Collections.Generic.List<getAllSourcesResponse>));
As it was, you were passing the open generic type, which will not match with anything when the importer is trying to resolve the collection.
Just stumbled upon this while trying to figure out how to do this in Mono's WSDL importer.
After reading some MSDN docs and playing around a bit with this, I got it working like this, using .NET 4.5:
var importer = new WsdlImporter (mset);
var xsdImporter = new XsdDataContractImporter ();
var options = new ImportOptions ();
options.ReferencedCollectionTypes.Add (typeof (LinkedList<>));
xsdImporter.Options = options;
importer.State.Add (typeof (XsdDataContractImporter), xsdImporter);
You can also specify specific generic instance types such as List<int>.
This is also documented here: http://msdn.microsoft.com/en-us/library/aa702680.aspx

Categories

Resources