Having trouble parsing XML with .Net Core 3 - c#

I haven't had much experience working with XML so forgive me if this is basic stuff. I have a feed that I'm trying to deserialize into an object(s) and some of it work but some doesn't. Here is a sample of the XML in question
<rss version ='2.0' xmlns:n='http://something.com/1.0'>
<group>
<title>Sample data</title>
<description>Sample feed description</description>
<link>https://www.sampledealership.co.uk/index.php/</link>
<item>
<n:id>xxx567</n:id>
<title>Ford Fiesta</title>
<description>A black Ford Fiesta</description>
</item>
<item>
<n:id>gg567</n:id>
<title>2019 Camero</title>
<description>A red Chevrolet Camero</description>
</item>
</group>
</rss>
Here are my classes
public class rss
{
[XmlAttribute(AttributeName = "version", Namespace = "")]
public decimal version { get; set; }
[XmlElement(ElementName = "group", Namespace = "")]
public Group group { get; set; }
}
public class Group
{
[XmlElement(ElementName = "title", Namespace = "")]
public string title { get; set; }
[XmlElement(ElementName = "description", Namespace = "")]
public string description { get; set; }
[XmlElement(ElementName = "link", Namespace = "")]
public string link { get; set; }
//[XmlArray("group")]
//[XmlArrayItem("item", typeof(Item))]
[XmlElement(ElementName = "item", Namespace = "")]
private List<Item> item { get; set; }
}
public class Item
{
[XmlElement(ElementName = "id", Namespace = "http://something.com/1.0")]
public string id { get; set; }
[XmlElement(ElementName = "title", Namespace = "")]
public string title { get; set; }
[XmlElement(ElementName = "description", Namespace = "")]
public string description { get; set; }
}
And here is the code in my test that is trying to deserialize it.
using (var stream = System.IO.File.OpenRead(#"Resources/carfeed.xml"))
{
var root = new XmlRootAttribute();
root.ElementName = "rss";
var serializer = new XmlSerializer(typeof(rss), root);
var car = ((rss) serializer.Deserialize(stream));
};
I get all the data contained in the group except for the Items, they are null. I have tried using the XmlArray annotation but still nothing. I'm hoping I have made a spelling mistake somewhere. Anyway, your help would be much appreciated.

Related

There is an error in XML document (0, 0) - Error Deserializing XML to object

please advice how do i map the response into class because from every example i came across body always don't have symbol like core:transactionResponse
my code:
string fileName = #"C:\Users\Lenovo\Downloads\GLResponseXml.xml";
XDocument xDoc = XDocument.Load(fileName);
var unwrappedResponse = xDoc.Descendants((XNamespace)"http://schemas.xmlsoap.org/soap/envelope/" + "Body")
.First()
.FirstNode;
XmlSerializer xmlSerializer = new XmlSerializer(typeof(TransactionResponse));
TransactionResponse response = (TransactionResponse)xmlSerializer.Deserialize(xDoc.Descendants((XNamespace)"http://schemas.xmlsoap.org/soap/envelope/" + "Body")
.First()
.FirstNode
.CreateReader()
);
for deserealizing this soap xml:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dpss0="bons">
<soapenv:Header/>
<soapenv:Body>
<core:transactionResponse xmlns:bo="http://service.example.co.id/core/bo" xmlns:core="http://service.example.co.id/core">
<response>
<header>
<coreJournal>149326</coreJournal>
</header>
<content xsi:type="bo:OKMessage">
<message/>
</content>
</response>
</core:transactionResponse>
</soapenv:Body>
</soapenv:Envelope>
but i got this error: InvalidOperationException: <transactionResponse xmlns='http://service.example.co.id/core'> was not expected.
i'm mapping the response into this class:
public class GLXmlResponse
{
[XmlRoot(ElementName = "response")]
public class Response
{
[XmlElement(ElementName = "header")]
public Header Header { get; set; }
[XmlElement(ElementName = "content")]
public Content Content { get; set; }
}
[XmlRoot(ElementName = "header")]
public class Header
{
[XmlElement(ElementName = "coreJournal")]
public string CoreJournal { get; set; }
}
[XmlRoot(ElementName = "content")]
public class Content
{
[XmlElement(ElementName = "message")]
public string Message { get; set; }
[XmlAttribute(AttributeName = "type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
public string Type { get; set; }
}
[XmlRoot(ElementName = "transactionResponse", Namespace = "http://service.example.co.id/core")]
public class TransactionResponse
{
[XmlElement(ElementName = "response")]
public Response Response { get; set; }
[XmlAttribute(AttributeName = "bo", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Bo { get; set; }
[XmlAttribute(AttributeName = "core", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Core { get; set; }
}
[XmlRoot(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Body
{
[XmlElement(ElementName = "transactionResponse", Namespace = "http://service.example.co.id/core")]
public TransactionResponse TransactionResponse { get; set; }
}
[XmlRoot(ElementName = "Envelope", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope
{
[XmlElement(ElementName = "Header", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public string Header { get; set; }
[XmlElement(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public Body Body { get; set; }
[XmlAttribute(AttributeName = "soapenv", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Soapenv { get; set; }
[XmlAttribute(AttributeName = "soapenc", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Soapenc { get; set; }
[XmlAttribute(AttributeName = "xsd", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Xsd { get; set; }
[XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Xsi { get; set; }
[XmlAttribute(AttributeName = "dpss0", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Dpss0 { get; set; }
}
}
need help on getting the class object right
I can't repro the exact error you're seeing, so you might want to check from a minimal repro; I'm using:
var env = (GLXmlResponse.Envelope)new XmlSerializer(typeof(GLXmlResponse.Envelope))
.Deserialize(new StringReader(xml));
System.Console.WriteLine(env.Body.TransactionResponse.Response.Header.CoreJournal);
where:
string xml = #"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:soapenc=""http://schemas.xmlsoap.org/soap/encoding/"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:dpss0=""bons"">
<soapenv:Header/>
<soapenv:Body>
<core:transactionResponse xmlns:bo=""http://service.example.co.id/core/bo"" xmlns:core=""http://service.example.co.id/core"">
<response>
<header>
<coreJournal>149326</coreJournal>
</header>
<content xsi:type=""bo:OKMessage"">
<message/>
</content>
</response>
</core:transactionResponse>
</soapenv:Body></soapenv:Envelope>";
which just has a null for .Response. The reason for that is that this is actually in the empty namespace (prefixes are not inherited), so you need
[XmlElement(ElementName = "response", Namespace = "")]
public Response Response { get; set; }
However, this then causes a problem with the OKMessage in the xml. If I comment out the <content>, then it works and I can see the output 149326.
However, it might be simpler to start by just copying the xml into the clipboard, Edit -> Paste Special -> Paste XML As Classes, and see what it generates, and work from there.

Deserializing XML has null object

I have the following XML class structure:
[XmlRoot(ElementName = "Envelope", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope
{
[XmlElement(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public Body Body { get; set; }
}
[XmlRoot(ElementName = "Body")]
public class Body
{
[XmlElement(ElementName = "CustomerBundleMaintainConfirmation_sync_V1", Namespace = "http://sap.com/xi/SAPGlobal20/Global")]
public CustomerMaintainConfirmation CustomerMaintainConfirmation { get; set; }
}
[XmlRoot(ElementName = "CustomerBundleMaintainConfirmation_sync_V1")]
public class CustomerMaintainConfirmation
{
[XmlElement(ElementName = "Log")]
public Log Log { get; set; }
}
[XmlRoot(ElementName = "Log")]
public class Log
{
[XmlElement(ElementName = "MaximumLogItemSeverityCode")]
public string MaximumLogItemSeverityCode { get; set; }
[XmlElement(ElementName = "Item")]
public Item Item { get; set; }
}
[XmlRoot(ElementName = "Item")]
public class Item
{
[XmlElement(ElementName = "TypeID")]
public string TypeID { get; set; }
[XmlElement(ElementName = "CategoryCode")]
public string CategoryCode { get; set; }
[XmlElement(ElementName = "SeverityCode")]
public string SeverityCode { get; set; }
[XmlElement(ElementName = "Note")]
public string Note { get; set; }
}
And this is the XML I am working with:
<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header />
<soap-env:Body>
<n0:CustomerBundleMaintainConfirmation_sync_V1 xmlns:n0="http://sap.com/xi/SAPGlobal20/Global" xmlns:prx="urn:sap.com:proxy:LBK:/1SAI/TAE6F3228CC6D723FF1823E:804">
<Log>
<MaximumLogItemSeverityCode>3</MaximumLogItemSeverityCode>
<Item>
<TypeID>018</TypeID>
<CategoryCode>YES</CategoryCode>
<SeverityCode>0</SeverityCode>
<Note>TestNotes</Note>
</Item>
</Log>
</n0:CustomerBundleMaintainConfirmation_sync_V1>
</soap-env:Body>
</soap-env:Envelope>
When I attempt to deserialize this data into my classes, for whatever reason the "Log" class is null. Envelope, Body and CustomerMaintainConfirmation are all populated correctly. I see no reason why this is the case, but I've been staring at this for so long as this point I'm absolutely sure I am missing a mistake in and amongst my code somewhere.
This last piece of code is inside of the method that does the actual deserializing:
XmlSerializer serializer = new XmlSerializer(typeof(Envelope));
using (StreamReader responseReader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
{
return (Envelope)serializer.Deserialize(responseReader);
}
I'm still working through it, but if anyone could point out any issues they might see with what I've provided, please let me know.
It's a namespace inconsistency. It deserializes with this change:
[XmlRoot(ElementName = "CustomerBundleMaintainConfirmation_sync_V1")]
public class CustomerMaintainConfirmation
{
[XmlElement(ElementName = "Log", Namespace = "")]
public Log Log { get; set; }
}
You just miss the empty namespace indication on your element:
[XmlRoot(ElementName = "CustomerBundleMaintainConfirmation_sync_V1")]
public class CustomerMaintainConfirmation
{
[XmlElement(ElementName = "Log", Namespace = "")]
public Log Log { get; set; }
}
This is required, as apparently, your Log element has the empty namespace even though the CustomerBundleMaintainConfirmation_sync_V1 above has a nonempty one.
That's the only change in your code to make it work as shown in a fiddle.

How to fix values being null when deserializing XML

I have an XML that I want to deserialize according to my own classes. It deserializes properly, but some of the values become null. It doesn't give an errors, and I'm not sure where the error lies.
I've tried changing the classes, serializing a memory model and then checking the output, but none of it worked to my liking. It needs to follow the XML that is provided.
My model:
[XmlRoot(ElementName = "model", Namespace = "http://www.archimatetool.com/archimate")]
public class Model
{
[XmlElement(ElementName = "folder")]
public List<Folder> Folders { get; set; }
[XmlElement(ElementName = "purpose")]
public string Purpose { get; set; }
[XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Xsi { get; set; }
[XmlAttribute(AttributeName = "archimate", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Archimate { get; set; }
[XmlAttribute(AttributeName = "name")]
public string Name { get; set; }
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
[XmlAttribute(AttributeName = "version")]
public string Version { get; set; }
}
My XML
<?xml version="1.0" encoding="UTF-8"?>
<archimate:model xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:archimate="http://www.archimatetool.com/archimate" name="Archisurance" id="11f5304f" version="3.1.1">
<folder name="Business" id="8c90fdfa" type="business">
<folder name="Actors" id="fa63373b">
<element xsi:type="archimate:BusinessInterface" id="1544" name="mail"/>
</folder>
</folder>
<purpose>An example of a fictional Insurance company.</purpose>
</archimate:model>
This the result im getting after deserializing.
I cant post pictures (due to reputation) so i am just posting a link.
result
I would expect the purpose field to say "An example of a fictional Insurance company", but it is null.
You can deserialize your XML with the following data model:
[XmlRoot(ElementName = "model", Namespace = "http://www.archimatetool.com/archimate")]
[XmlType(Namespace = "http://www.archimatetool.com/archimate")]
public class Model
{
[XmlElement(ElementName = "folder", Form = XmlSchemaForm.Unqualified)]
public List<Folder> Folders { get; set; }
[XmlElement(ElementName = "purpose", Form = XmlSchemaForm.Unqualified)]
public string Purpose { get; set; }
[XmlAttribute(AttributeName = "name")]
public string Name { get; set; }
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
[XmlAttribute(AttributeName = "version")]
public string Version { get; set; }
}
[XmlType(Namespace = "http://www.archimatetool.com/archimate")]
public class Folder
{
[XmlAttribute(AttributeName = "name")]
public string Name { get; set; }
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
[XmlAttribute(AttributeName = "type")]
public string Type { get; set; }
[XmlElement(ElementName = "folder", Form = XmlSchemaForm.Unqualified)]
public List<Folder> Folders { get; set; }
[XmlElement(ElementName = "element", Form = XmlSchemaForm.Unqualified)]
public List<Element> Element { get; set; }
}
[XmlType(Namespace = "http://www.archimatetool.com/archimate")]
[XmlInclude(typeof(BusinessInterface))]
public abstract class Element
{
[XmlAttribute(AttributeName = "name")]
public string Name { get; set; }
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
}
[XmlType(TypeName = "BusinessInterface", Namespace = "http://www.archimatetool.com/archimate")]
public class BusinessInterface : Element
{
}
Notes:
The root element <archimate:model> is in the archimate: namespace, but its child elements are not in any namespace, since the archimate: namespace is not the default namespace. Thus it's necessary to indicate to XmlSerializer that these child elements are in a different namespace from their parent. Setting XmlElementAttribute.Form = XmlSchemaForm.Unqualified accomplishes this.
(It is not necessary to specify that attributes are in the default namespace, since all XML attributes are assumed to be unqualified unless otherwise specified.)
The presence of the xsi:type="archimate:BusinessInterface" attribute indicates the <element> attribute is part of a polymorphic type hierarchy. The xsi:type attribute is a standard w3c attribute that allows an element to explicitly assert its type. XmlSerializer supports this attribute and in fact requires the presence of a subtype corresponding to the xsi:type and declared through the [XmlInclude] attribute.
For details see How to: Control Serialization of Derived Classes.
Here I made an arbitrary choice of properties to include in the base class Element and the derived class BusinessInterface. You may need to adjust this choice given a more complete XML sample.
Sample fiddle here.

How to deserialize xml

I am load xml file like
<?xml version="1.0" encoding="UTF-8"?>
<OrderHeadUpload xmlns="http://www.sample-package.org" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Number>Z-00006453580748</Number>
<Number_confirm>000033477</Number_confirm>
<Positions>
<id>168816</Product_id>
<Tare_id>2442</Tare_id>
</Positions>
</OrderHeadUpload>
Make 2 class
[XmlRoot(ElementName = "Head", Namespace = "http://www.sample-package.org")]
public class OrderHeadUpload
{
[XmlElement(ElementName = "Number_confirm", Namespace = "http://www.sample-package.org")]
public string Client_id { get; set; }
[XmlElement(ElementName = "Number", Namespace = "http://www.sample-package.org")]
public string Barcode_id { get; set; }
}
[XmlRoot(ElementName = "Positions", Namespace = "http://www.sample-package.org")]
public class Positions
{
[XmlElement(ElementName = "id", Namespace = "http://www.sample-package.org")]
public string id { get; set; }
[XmlElement(ElementName = "Tare_id", Namespace = "http://www.sample-package.org")]
public string Tare_id {get; set;}
}
i am load xml file (temp.xml) then serializer on classes 2 Position and Head
then StringReader, which reads strings from a file
and then var position = (Positions) serializer.Deserialize (reader); class serialized become deserialized
doc.Load(temp);
XmlSerializer serializer = new XmlSerializer(typeof(Positions));
XmlSerializer serializer2 = new XmlSerializer(typeof(Head));
StringReader reader = new StringReader(temp);
var position = (Positions)serializer.Deserialize(reader);
var Head = (OrderHeadUpload)serializer2.Deserialize(reader);
but i see error
Error msg There is an error in XML document (1, 1).
Where?: at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
at System.Xml.Serialization.XmlSerializer.Deserialize(TextReader textReader)
at .cs:line 64 (var position = (Positions)serializer.Deserialize(reader);)
How to correctly deserialize this xml?
Try:
[XmlRoot(ElementName = "Positions", Namespace = "http://www.sample-package.org")]
public class Positions
{
[XmlElement(ElementName = "id", Namespace = "http://www.sample-package.org")]
public string id { get; set; }
[XmlElement(ElementName = "Tare_id", Namespace = "http://www.sample-package.org")]
public string Tare_id { get; set; }
}
[XmlRoot(ElementName = "Head", Namespace = "http://www.sample-package.org")]
public class OrderHeadUpload
{
[XmlElement(ElementName = "Number_confirm", Namespace = "http://www.sample-package.org")]
public string Client_id { get; set; }
[XmlElement(ElementName = "Number", Namespace = "http://www.sample-package.org")]
public string Barcode_id { get; set; }
[XmlElement(ElementName = "Positions")]
public Positions positions;
}
Use:
var order = (OrderHeadUpload)serializer.Deserialize(reader);
And you need to deserialize just onetime with OrderHeadUpload. If you have more than one Positions, you can declare like a List<T>

WCF receives empty model from XML

We have a WCF service with defined class (class was autogenerated from XML using http://xmltocsharp.azurewebsites.net/ ):
namespace CRMtoQLM.DAL
{
[Serializable]
[DataContract(Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope
{
[XmlElement(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
[DataMember]
public Body Body { get; set; }
[XmlAttribute(AttributeName = "soapenv", Namespace = "http://www.w3.org/2000/xmlns/")]
[DataMember]
public string Soapenv { get; set; }
[XmlAttribute(AttributeName = "xsd", Namespace = "http://www.w3.org/2000/xmlns/")]
[DataMember]
public string Xsd { get; set; }
[XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
[DataMember]
public string Xsi { get; set; }
}
//[Serializable]
[XmlRoot(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
[DataContract(Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Body
{
[XmlElement(ElementName = "notifications", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataMember]
public Notifications Notifications { get; set; }
}
//[Serializable]
[XmlRoot(ElementName = "notifications", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataContract(Namespace = "http://soap.sforce.com/2005/09/outbound")]
public class Notifications
{
[XmlElement(ElementName = "OrganizationId", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataMember]
public string OrganizationId { get; set; }
[XmlElement(ElementName = "ActionId", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataMember]
public string ActionId { get; set; }
[XmlElement(ElementName = "SessionId", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataMember]
public string SessionId { get; set; }
[XmlElement(ElementName = "EnterpriseUrl", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataMember]
public string EnterpriseUrl { get; set; }
[XmlElement(ElementName = "PartnerUrl", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataMember]
public string PartnerUrl { get; set; }
[XmlElement(ElementName = "Notification", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataMember]
public Notification Notification { get; set; }
[XmlAttribute(AttributeName = "xmlns")]
[DataMember]
public string Xmlns { get; set; }
}
//[Serializable]
[XmlRoot(ElementName = "Notification", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataContract(Namespace = "http://soap.sforce.com/2005/09/outbound")]
public class Notification
{
[XmlElement(ElementName = "Id", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataMember]
public string Id { get; set; }
[XmlElement(ElementName = "sObject", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataMember]
public SObject SObject { get; set; }
}
//[Serializable]
[XmlRoot(ElementName = "sObject", Namespace = "http://soap.sforce.com/2005/09/outbound")]
[DataContract(Namespace = "http://soap.sforce.com/2005/09/outbound")]
public class SObject
{
[XmlElement(ElementName = "Id", Namespace = "urn:sobject.enterprise.soap.sforce.com")]
[DataMember]
public string Id { get; set; }
[XmlElement(ElementName = "Asset_Account_City__c", Namespace = "urn:sobject.enterprise.soap.sforce.com")]
[DataMember]
public string Asset_Account_City__c { get; set; }
[XmlElement(ElementName = "Asset_Account_Country__c", Namespace = "urn:sobject.enterprise.soap.sforce.com")]
[DataMember]
public string Asset_Account_Country__c { get; set; }
[XmlElement(ElementName = "Asset_Account_Name__c", Namespace = "urn:sobject.enterprise.soap.sforce.com")]
[DataMember]
public string Asset_Account_Name__c { get; set; }
[XmlElement(ElementName = "Asset_Customer_ID__c", Namespace = "urn:sobject.enterprise.soap.sforce.com")]
[DataMember]
public string Asset_Customer_ID__c { get; set; }
[XmlElement(ElementName = "Expiration_Date__c", Namespace = "urn:sobject.enterprise.soap.sforce.com")]
[DataMember]
public string Expiration_Date__c { get; set; }
[XmlElement(ElementName = "License__c", Namespace = "urn:sobject.enterprise.soap.sforce.com")]
[DataMember]
public string License__c { get; set; }
[XmlElement(ElementName = "Reader_Code__c", Namespace = "urn:sobject.enterprise.soap.sforce.com")]
[DataMember]
public string Reader_Code__c { get; set; }
[XmlElement(ElementName = "Reader_Quantity__c", Namespace = "urn:sobject.enterprise.soap.sforce.com")]
[DataMember]
public string Reader_Quantity__c { get; set; }
[XmlAttribute(AttributeName = "type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
[DataMember]
public string Type { get; set; }
[XmlAttribute(AttributeName = "sf", Namespace = "http://www.w3.org/2000/xmlns/")]
[DataMember]
public string Sf { get; set; }
}
}
IService.cs defined like this:
[OperationContract]
[WebInvoke(Method = "POST",
UriTemplate = "Test",
RequestFormat = WebMessageFormat.Xml)]
//[XmlSerializerFormat]
string Test(Envelope parameter);
and implementation:
public string Test(Envelope parameter)
{
return "";
}
but "parameter" in Test function contains NULL objects. I know there is a problem with XML deserialization but can't figure out where exactly.
EDIT: this is the request that I'm sending via Postman
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<notifications xmlns="http://soap.sforce.com/2005/09/outbound">
<OrganizationId>123456</OrganizationId>
<ActionId>123456</ActionId>
<SessionId>123456</SessionId>
<EnterpriseUrl>https://eu8.salesforce.com/</EnterpriseUrl>
<PartnerUrl>https://eu8.salesforce.com/</PartnerUrl>
<Notification>
<Id>123456</Id>
<sObject xsi:type="sf:Asset" xmlns:sf="urn:sobject.enterprise.soap.sforce.com">
<sf:Id>123456</sf:Id>
<sf:Asset_Account_City__c>123456</sf:Asset_Account_City__c>
<sf:Asset_Account_Country__c>123456</sf:Asset_Account_Country__c>
<sf:Asset_Account_Name__c>123456</sf:Asset_Account_Name__c>
<sf:Asset_Customer_ID__c>123456</sf:Asset_Customer_ID__c>
<sf:Expiration_Date__c>123456</sf:Expiration_Date__c>
<sf:License__c>123456</sf:License__c>
<sf:Reader_Code__c>123456</sf:Reader_Code__c>
<sf:Reader_Quantity__c>123456</sf:Reader_Quantity__c>
</sObject>
</Notification>
</notifications>
</soapenv:Body>
</soapenv:Envelope>
SOAP-based bindings unpack the SOAP envelope for you, so you shouldn't need to define the SOAP envelope types. The WebHttpBinding which you say you're using, which doesn't know anything about SOAP, would expect that the contract type (the argument of your service method IService.Test) would match the entire HTTP body, so I see the logic of what you're doing, however I don't think it's necessary to work against the framework like this.
To fix this scenario do a couple of things:
amend your implementation of IService.Test to take an argument of type Notifications
string Test(Notifications notifications)
amend the service config to specify an HTTP-based SOAP binding, probably BasicHttpBinding
<endpoint address="/relativeaddress/" binding="basicHttpBinding" ... />
I think a SOAP binding will probably ignore WebInvokeAttribute, but to be on the safe side, remove it. It's superfluous for a SOAP binding because SOAP is always POST.
I don't think you need to delete the Envelope and Body types but they won't do anything if they're not referenced, which is what you want. WCF bindings understand the SOAP envelope natively and don't need it to be specified, it's the content of the SOAP Body element that types need to be provided for.
Your XML sample contains a single instance of Notification under Notifications but the name implies that this child element could be repeating - if it is, I don't think the generated classes will work for you because the Notifications class has a singular Notification property - the generator you linked to has no way to know this so I don't fault it in any way. I added a copy of the Notification element as a sibling and ran it through again - this time it generated a list member:
[XmlElement(ElementName="Notification", Namespace="http://soap.sforce.com/2005/09/outbound")]
public List<Notification> Notification { get; set; }
You can use the xsd.exe tool supplied with Visual Studio (I think) to generate classes - see the documentation. I wouldn't be surprised if that web tool is driving this behind the scenes but I'd trust xsd.exe to generate classes that have the best possible compliance with what WCF expects of them.

Categories

Resources