I have some problems with the deserialization of my Soap response, i get an exception when try to deserialize with XmlSerializer class
Soap Data:
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<IsWmsLoginCorrectResponse xmlns="http://pehade.be/">
<IsWmsLoginCorrectResult>
<UserId>int</UserId>
<LoginToken>guid</LoginToken>
<ErrorId>int</ErrorId>
<ErrorDescription>string</ErrorDescription>
</IsWmsLoginCorrectResult>
</IsWmsLoginCorrectResponse>
</soap12:Body>
</soap12:Envelope>
TokenInfo model:
public const string DefaultSoapNamespace = "http://pehade.be/";
//...
[XmlRoot("IsWmsLoginCorrectResponse", Namespace = Consts.DefaultSoapNamespace)]
public class TokenInfo : BaseSoapInfo
{
[XmlAttribute(AttributeName = "UserId", Namespace = Consts.DefaultSoapNamespace)]
public int UserId { get; set; }
[XmlAttribute(AttributeName = "LoginToken", Namespace = Consts.DefaultSoapNamespace)]
public string LoginToken { get; set; }
}
public class BaseSoapInfo
{
[XmlAttribute(AttributeName = "ErrorId", Namespace = Consts.DefaultSoapNamespace)]
public int ErrorId { get; set; }
[XmlAttribute(AttributeName = "ErrorDescription", Namespace = Consts.DefaultSoapNamespace)]
public string ErrorDescription { get; set; }
}
Parse Method:
public override T ParseSoap<T>(string resultSoap)
{
var document = XDocument.Parse(resultSoap);
var xmlSerializer = new XmlSerializer(typeof(T));
var soapBody = XName.Get("Body", Consts.DefaultSoapNamespace);
// Exception
var tokenInfo = (T)xmlSerializer.Deserialize(document.Descendants(soapBody)
.First()
.FirstNode
.CreateReader());
return tokenInfo;
}
Did I make the model correctly? Can there is other method to receive stream for XmlSerializer?
Update: Add exception details
System.InvalidOperationException: Sequence contains no elements
at System.Linq.Enumerable.First[TSource] (System.Collections.Generic.IEnumerable`1[T] source) [0x00010] in :0
at DAL.SoapConverters.LoginSoapConverter.ParseSoap[T] (System.String resultSoap) [0x00031] in C:\Work\Projects\Apro\Other MDO\WarehouseMS\DAL\SoapConverters\LoginSoapConverter.cs:40 08-30 14:56:01.858 I/mono-stdout( 4702): System.InvalidOperationException: Sequence contains no elements
I think that the XmlAttribute(s) should be changed to XmlElement. For instance the UserId should be:
[XmlElement(Namespace = Consts.DefaultSoapNamespace)]
public int UserId { get; set; }
Related
There is a WSDL scheme for SOAP in OTRS, unfortunately with an automaton (connecting links), it does not work, because Sharp considers the file to be incorrect. for normal operation, you must obtain the following:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tic="http://www.otrs.org/TicketConnector/">
<soapenv:Header/>
<soapenv:Body>
<SessionCreate>
<tic:UserLogin>ULogin</tic:UserLogin>
<tic:CustomerUserLogin>CustUser</tic:CustomerUserLogin>
<tic:Password>ULPassword</tic:Password>
</SessionCreate>
</soapenv:Body>
</soapenv:Envelope>
I tried through System.Runtime.Serialization.Formatters.Soap as follows:
[Serializable]
public partial class Envelope
{
/// <remarks/>
public object Header { get; set; }
/// <remarks/>
public EnvelopeBody Body { get; set; }
}
[Serializable]
public partial class EnvelopeBody
{
public SessionCreate SessionCreate { get; set; }
}
[Serializable]
[System.Xml.Serialization.SoapType(IncludeInSchema =true, Namespace = "")]
public partial class SessionCreate
{
/// <remarks/>
[System.Xml.Serialization.SoapElement("http://www.otrs.org/TicketConnector/")]
public string UserLogin { get; set; }
/// <remarks/>
[System.Xml.Serialization.SoapElement("http://www.otrs.org/TicketConnector/")]
public string CustomerUserLogin { get; set; }
/// <remarks/>
[System.Xml.Serialization.SoapElement("http://www.otrs.org/TicketConnector/")]
public string Password { get; set; }
}
class TEST
{
void GetSoap()
{
var model = new SessionCreate
{
UserLogin ="ULogin",
CustomerUserLogin="CustUser",
Password="ULPassword"
};
var en = new Envelope
{
Body = new EnvelopeBody
{
SessionCreate = model
}
};
SoapFormatter formatter = new SoapFormatter();
var ms = new MemoryStream();
formatter.Serialize(ms, en);
Console.WriteLine(StreamToString(ms));
}
string StreamToString(Stream stream)
{
stream.Position = 0;
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
{
return reader.ReadToEnd();
}
}
}
As a result, it displays the following:
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<a1:Envelope id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/OTRS.Request/OTRS%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
<_x003C_Header_x003E_k__BackingField xsi:type="xsd:anyType" xsi:null="1"/>
<_x003C_Body_x003E_k__BackingField href="#ref-3"/>
</a1:Envelope>
<a1:EnvelopeBody id="ref-3" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/OTRS.Request/OTRS%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
<_x003C_SessionCreate_x003E_k__BackingField href="#ref-4"/>
</a1:EnvelopeBody>
<a1:SessionCreate id="ref-4" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/OTRS.Request/OTRS%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
<_x003C_UserLogin_x003E_k__BackingField id="ref-5">ULogin</_x003C_UserLogin_x003E_k__BackingField>
<_x003C_CustomerUserLogin_x003E_k__BackingField id="ref-6">CustUser</_x003C_CustomerUserLogin_x003E_k__BackingField>
<_x003C_Password_x003E_k__BackingField id="ref-7">ULPassword</_x003C_Password_x003E_k__BackingField>
</a1:SessionCreate>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
The question arises, how to do it normally, and what am I doing wrong?
I need the following output from Pojo classes to Xml.
It's .net 4.6.1, C#.
Problem is in the namespaces and the produced prefixes.
How can I get the node:
<blablubb:Message SOAP-ENV:mustUnderstand="1" xmlns:blablubb="urn:blablubb-com:schemas:blablubb">
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<blablubb:Message SOAP-ENV:mustUnderstand="1" xmlns:blablubb="urn:blablubb-com:schemas:blablubb">
<blablubb:Type>INET_TRANS</blablubb:Type>
<blablubb:Function>RECEIVE_CUSTOMER_ORDER</blablubb:Function>
<blablubb:Sender>CONNECT</blablubb:Sender>
<blablubb:Receiver>CONNECT</blablubb:Receiver>
<blablubb:SentAt>2018-08-30T10:43:37+02:00</blablubb:SentAt>
<blablubb:ExpiresAt>2018-09-30T10:43:37+02:00</blablubb:ExpiresAt>
</blablubb:Message>
</SOAP-ENV:Header>
<SOAP-ENV:Body><ORDERS xmlns="urn:blablubb-com:schemas:inbound_distribution_transactions_create_customer_order_request" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<BUYER></BUYER>
<CONTACT_REFERENCE>OAK</CONTACT_REFERENCE>
<EAN_LOCATION_DELIVERY_ADDRESS>10901000</EAN_LOCATION_DELIVERY_ADDRESS>
<CURRENCY_CODE>EUR</CURRENCY_CODE>
<ORDER_DATE>2018-08-27T09:01:01</ORDER_DATE>
<OUR_CUSTOMER_NO>2</OUR_CUSTOMER_NO>
<SUPPLIER_ADDRESS_NO></SUPPLIER_ADDRESS_NO>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Pojos that get serialized:
SoapDocument:
[Serializable]
[XmlRoot("Envelope", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
[XmlInclude(typeof(SoapHeader))]
public class SoapDocument {
[XmlElement("Header")]
public SoapHeader soapHeader { get; set; }
[XmlElement("Body",typeof(IfsOrdersXmlDocument))]
public object soapBody { get; set; }
}
SoapHeader :
[Serializable]
[XmlRoot("Header")]
[XmlInclude(typeof(SoapMessage))] // include type class IfsOrderLineXmlDocument
public class SoapHeader {
[XmlElement("Message", Namespace = "urn:blablubb-com:schemas:blablubb")]
public SoapMessage soapMessage { get; set; }
}
SoapBody :
[Serializable]
[XmlInclude(typeof(IfsXmlDocument)), XmlInclude(typeof(IfsOrdersXmlDocument))]
[SoapInclude(typeof(IfsXmlDocument)), SoapInclude(typeof(IfsOrdersXmlDocument))]
public class SoapBody {
[XmlElement("Body")]
public IfsXmlDocument soapBody { get; set; }
}
SoapMessage:
[Serializable]
//[XmlType("blablubb")]
[XmlRoot("Message", Namespace = "urn:blablubb-com:schemas:blablubb")]
public class SoapMessage {
[XmlElement("Type")]
public string Type { get; set; }
[XmlElement("Function")]
public string Function { get; set; }
[XmlElement("Sender")]
public string Sender { get; set; }
[XmlElement("Receiver")]
public string Receiver { get; set; }
[XmlElement("SentAt")]
public string SentAt { get; set; }
[XmlElement("ExpiresAt")]
public string ExpiresAt { get; set; }
}
Code that produces the Xml,
So the problem is in the namespaces and prefixes ......
XmlSerializerNamespaces ns = createSoapDocument();
XmlSerializer serializer = new XmlSerializer(typeof(HeinzApi.Soap.SoapDocument), new Type[] { typeof(IfsXmlDocument), typeof(IfsOrdersXmlDocument) });
FileStream fs = new FileStream(xmlTargetPath, FileMode.Create);
serializer.Serialize(fs, soapDocument, ns);
fs.Close();`
And this is what I get:
<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<Message xmlns="urn:blablubb-com:schemas:blablubb">
<Type>INET_TRANS</Type>
<Function>RECEIVE_CUSTOMER_ORDER</Function>
<Sender>CONNECT</Sender>
<Receiver>CONNECT</Receiver>
<SentAt>2018-01-03T10:43:37+02:00</SentAt>
<ExpiresAt>2018-08-02T10:43:37+02:00</ExpiresAt>
</Message>
</SOAP-ENV:Header>
</SOAP-ENV:Envelope>
This is the createSoapDocument method that adds namespaces to the XmlSerializer Namespaces object:
private XmlSerializerNamespaces createSoapDocument() {
soapMessage.Type = "INET_TRANS";
soapMessage.Function = "RECEIVE_CUSTOMER_ORDER";
soapMessage.Sender = "CONNECT";
soapMessage.Receiver = "CONNECT";
soapMessage.SentAt = "2018-01-03T10:43:37+02:00";
soapMessage.ExpiresAt = "2018-08-02T10:43:37+02:00";
soapHeader.soapMessage = soapMessage;
soapDocument.soapHeader = soapHeader;
//soapDocument.soapBody = (IfsXmlDocument)targetXmlBaseDocument; ;
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/");
ns.Add("blablubb", "urn:blablubb-com:schemas:blablubb");
return ns;
}
Edit: This is the result after adding the namespaces to XmlSerializerNamespaces:
<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:blablubb="urn:blablubb-com:schemas:blablubb" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<blablubb:Message>
<blablubb:Type>INET_TRANS</blablubb:Type>
<blablubb:Function>RECEIVE_CUSTOMER_ORDER</blablubb:Function>
<blablubb:Sender>CONNECT</blablubb:Sender>
<blablubb:Receiver>CONNECT</blablubb:Receiver>
<blablubb:SentAt>2018-01-03T10:43:37+02:00</blablubb:SentAt>
<blablubb:ExpiresAt>2018-08-02T10:43:37+02:00</blablubb:ExpiresAt>
</blablubb:Message>
</SOAP-ENV:Header>
</SOAP-ENV:Envelope>
You need to tell the serializer about your blahblubb namespace by adding it to your XmlSerializerNamespaces object.
ns.Add("blablubb", "urn:bla-com:schemas:blablubb");
Don't forget to change
[XmlElement("Body")]
to
[XmlElement("Body", Namespace="urn:bla-com:schemas:blablubb")]
This queston may possible duplicated but I am calling a service as the following below :
HttpClient httpClinet = new HttpClient();
httpClinet.DefaultRequestHeaders.Accept.Clear();
httpClinet.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/xml"));
var str = "XrayService.asmx/GetOrdData?" + string.Format("ordId={0}&code={1}", range.ordId, range.code);
HttpResponseMessage response;
httpClinet.BaseAddress = new Uri("http://172.16.203.27:6043/");
response = httpClinet.GetAsync(str).Result;
if (response.IsSuccessStatusCode)
var caseInfos = response.Content.ReadAsAsync<IEnumerable<PI>>().Result;//Here is exception
everything is going fine, but when I want to run ReadAsAsync I got the exception as below:
Error:System.AggregateException: One or more errors occurred. ---> System.AggregateException: One or more errors occurred. ---> System.Runtime.Serialization.SerializationException: Error in line 1 position 5. Expecting element 'ArrayOfPI' from namespace 'http://schemas.datacontract.org/2004/07/SATA_DTOs'.. Encountered 'Element' with name 'PI', namespace ''.
at System.Runtime.Serialization.DataContractSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.DataContractSerializer.ReadObject(XmlReader reader)
at System.Net.Http.Formatting.XmlMediaTypeFormatter.ReadFromStream(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
at System.Net.Http.Formatting.XmlMediaTypeFormatter.ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
--- End of stack trace from previous location where exception was thrown ---
I am testing that service by Google Advanced Rest Client and see the result as :
Status : 200 OK
Response Header:
cache-control: private, max-age=0
content-length: 360
content-type: text/xml; charset=utf-8
server:Microsoft-IIS/8.5
x-aspnet-version:4.0.30319
x-powered-by: ASP.NET
date: Sun, 03 Dec 2017 08:37:21 GMT
and OutPut :
<?xml version="1.0" encoding="utf-8" ?>
<PI>
<ordId>950177248</ordId>
<fnm>بهسا</fnm>
<lnm>حسنی</lnm>
<fthNm>علی</fthNm>
<pId>p2535154</pId>
<sex>F</sex>
<brthD>2003-02-05</brthD>
<addrs />
<nId>0025351540</nId>
<srvNm>|دندان بصورت پانورک</srvNm>
<rfrPhy>مهرزاد اميري-41853</rfrPhy>
</PI>
I also decorated DTO like :
namespace SATA_DTOs
{
[DataContract(Name = "PI")]
public class PI
{
[DataMember] public string ordId { get; set; }
[DataMember] public string fnm { get; set; }
[DataMember] public string lnm { get; set; }
[DataMember] public string fthNm { get; set; }
[DataMember] public string pId { get; set; }
[DataMember] public string sex { get; set; }
[DataMember] public string brthD { get; set; }
[DataMember] public string addrs { get; set; }
[DataMember] public string nId { get; set; }
[DataMember] public string srvNm { get; set; }
[DataMember] public string rfrPhy { get; set; }
}
}
UPDATE:
Just as another try I want to get the result here either JSON or XML but this is also does not make difference:
List<PI> model = null;
var client = new HttpClient();
var task = client.GetAsync(httpClinet.BaseAddress.ToString() + str)
.ContinueWith((taskwithresponse) =>
{
var response1 = taskwithresponse.Result;
var jsonString = response1.Content.ReadAsStringAsync();
m_Logging.Log(SharedLib.LoggingMode.Prompt, "JSON string created {0}...", jsonString);
jsonString.Wait();
model = Newtonsoft.Json.JsonConvert.DeserializeObject<List<PI>>(jsonString.Result);
});
task.Wait();
After many copy pasting patch on server and improving the log I finally resolve the problem,
As the last try which #NKosi suggested with little changes:
var response1 = httpClinet.GetAsync(str).Result;
IEnumerable<PI> caseInfos1 = Enumerable.Empty<PI>();
try
{
caseInfos1 = response1.Content.ReadAsAsync<IEnumerable<PI>>().Result;
}
catch (Exception ex)
{
try
{
m_Logging.Log(SharedLib.LoggingMode.Error, "IEnumerable failed, EXP:{0}", ex);
var singleObject = response1.Content.ReadAsAsync<PI>().Result;
if (singleObject != null)
{
m_Logging.Log(SharedLib.LoggingMode.Error, "singleObject succeeded...");
caseInfos1 = new[] { singleObject };
}
}
catch (Exception exp)
{
m_Logging.Log(SharedLib.LoggingMode.Error, "singleObject failed, EXP:{0}", exp);
}
}
I crossed with the below exception also:
System.Runtime.Serialization.SerializationException: Error in line 1 position 5. Expecting element 'ArrayOfPI' from namespace 'http://schemas.datacontract.org/2004/07/SATA_DTOs'.. Encountered 'Element' with name 'PI', namespace ''....
.....
as the exception mentioned it can't be able to deserialize the result I guessed the out put type may is text/html not text/xml although Rest Client Tester specified it as text/xml,
for this reason I came to this conclusion to use ReadAsStringAsync and deserialize it to PI, so by the below snipped code I finally get the result:
PI caseInfos = null;
try
{
string strasd = response.Content.ReadAsStringAsync().Result;
m_Logging.Log(SharedLib.LoggingMode.Prompt, "ReadAsStringAsync() result:{0}", strasd);
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(PI));
using (TextReader reader = new StringReader(strasd))
caseInfos = (PI)serializer.Deserialize(reader);
m_Logging.Log(SharedLib.LoggingMode.Prompt, "Deserializing caseInfos model succeeded...");
}
catch (Exception ex)
{
m_Logging.Log(SharedLib.LoggingMode.Error, "creating model failed, EXP:{0}", ex);
}
I appreciate all crossed this question especially those who shared his/her knowledge in this discussion!!!
This is can be quite confusing. This might seem obvious the eye but still, not understandable to some.
Look at this line:
var caseInfos = response.Content.ReadAsAsync<IEnumerable<PI>>().Result
You are rendering the result as PI, which results in <pi> tag.
Thus, you get the following error:
System.Runtime.Serialization.SerializationException: Error in line 1
position 5. Expecting element 'ArrayOfPI' from namespace
'http://schemas.datacontract.org/2004/07/SATA_DTOs'.. Encountered
'Element' with name 'PI', namespace ''
The solution is this,
change your data contract and your class name:
namespace SATA_DTOs
{
[DataContract(Name = "ArrayOfPI")]
public class ArrayOfPI
{
[DataMember] public string ordId { get; set; }
[DataMember] public string fnm { get; set; }
[DataMember] public string lnm { get; set; }
[DataMember] public string fthNm { get; set; }
[DataMember] public string pId { get; set; }
[DataMember] public string sex { get; set; }
[DataMember] public string brthD { get; set; }
[DataMember] public string addrs { get; set; }
[DataMember] public string nId { get; set; }
[DataMember] public string srvNm { get; set; }
[DataMember] public string rfrPhy { get; set; }
}
}
Then assign it like this:
var caseInfos = response.Content.ReadAsAsync<IEnumerable<ArrayOfPI>>().Result
Thus, you will receive this:
<?xml version="1.0" encoding="utf-8" ?>
<ArrayOfPI>
<ordId>950177248</ordId>
<fnm>بهسا</fnm>
<lnm>حسنی</lnm>
<fthNm>علی</fthNm>
<pId>p2535154</pId>
<sex>F</sex>
<brthD>2003-02-05</brthD>
<addrs />
<nId>0025351540</nId>
<srvNm>|دندان بصورت پانورک</srvNm>
<rfrPhy>مهرزاد اميري-41853</rfrPhy>
</ArrayOfPI>
Which is what the serialization looks for and expects to find.
When using ReadAsAsync the framework tries to interpret the desired type for deserialization using the provided media type formatter.
You have IEnumerable<PI> so it assumes that the content being read is a collection ArrayOfPI based on standards.
In your example a single object is being returned while you tell it to expect a collection so it fails.
I suggest checking for collection and if that fails then check for single object given the dynamic nature of the responses that can be returned.
Simplified example
public async Task<IEnumerable<PI>> GetDataAsync() {
var httpClinet = buildClient();
var str = buildRequestUrl();
var response = await httpClinet.GetAsync(str);
IEnumerable<PI> caseInfos = Enumerable.Empty<PI>();
if (response.IsSuccessStatusCode) {
try {
caseInfos = await response.Content.ReadAsAsync<IEnumerable<PI>>();
} catch {
//Log?
}
if (caseInfos == null) {
try {
var singleObject = await response.Content.ReadAsAsync<PI>();
if (singleObject != null) {
caseInfos = new[] { singleObject };
}
} catch {
//Log?
}
}
}
return caseInfos;
}
SOLVED with this link
I'm developing a wcf service, with rest pattern. Now it is on a IIS server.
It has got a method callable with a post, which has to receive a xml data.
I'm trying to send this xml (with other parameter), but I'm getting only deserial errors:
in System.ServiceModel.Dispatcher.OperationFormatter.DeserializeRequest(Message message, Object[] parameters)
in System.ServiceModel.Dispatcher.DemultiplexingDispatchMessageFormatter.DeserializeRequest(Message message, Object[] parameters)
in System.ServiceModel.Dispatcher.UriTemplateDispatchFormatter.DeserializeRequest(Message message, Object[] parameters)
in System.ServiceModel.Dispatcher.DispatchOperationRuntime.DeserializeInputs(MessageRpc& rpc)
in System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
in System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
in System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
in System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
This is the request:
retista=0019&hashedStrig=dkfjdkfjd&dati=<ArrayOfWrapClienti xmlns="http://schemas.datacontract.org/2004/07/MultipayOnline" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><WrapClienti><CODRETE>0018</CODRETE><CODICE>20685</CODICE><NOME>A.T.E.R. Azienda Territoriale</NOME><INDIRIZZO>PIAZZA POZZA</INDIRIZZO><CITTA>Verona</CITTA><CAP>37123</CAP><PROV>VR</PROV><CODICEFISCALE>00223640236</CODICEFISCALE><PIVA>223640236</PIVA><EMAIL/><ESPOSIZ_CONTABILE>937,02</ESPOSIZ_CONTABILE><STATO>FALSE</STATO></WrapClienti></ArrayOfWrapClienti>
and this is the xml I'm trying to send:
<ArrayOfWrapClienti xmlns="http://schemas.datacontract.org/2004/07/aaa" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<WrapClienti>
<CODRETE>1111</CODRETE>
<CODICE>111</CODICE>
<NOME>AAA</NOME>
<INDIRIZZO>PIAZZA</INDIRIZZO>
<CITTA>AAA</CITTA>
<CAP>111</CAP>
<PROV>aa</PROV>
<CODICEFISCALE>111</CODICEFISCALE>
<PIVA>223611140236</PIVA>
<EMAIL/>
<ESPOSIZ_CONTABILE>1111</ESPOSIZ_CONTABILE>
<STATO>FALSE</STATO>
</WrapClienti>
</ArrayOfWrapClienti>
If you click here, you can find out how an xml is returned by my wcf. I thought I have to send the same xml with other data, but I get the deserial error.
Why?
How can I send the xml to my wcf? In this test phase, I'm using this.
If I can give to you other useful infos, ask me and I'll write them here.
UPDATE: The text of the error message says that there are invalid data at root level, row 1, pos 1. Also if I put
<?xml version="1.0" encoding="utf-8" ?>
at the root level.
Maybe are there some missing headers?
UPDATE server side:
this is how my server wcf is configured:
[OperationContract]
[WebGet(UriTemplate = "cliente.xml?retista={codret}&cliente={codiceCliente}&H={hashedString}", ResponseFormat = WebMessageFormat.Xml)]
List<WrapClienti> GetClienteXML(string codret, string codiceCliente, string hashedString);
and this is the called method:
public GenericResponse SetClientiXML(List<WrapClienti> clienti, string retista, string hashedString)
{
var api = new API();
return api.SetClienti(clienti, retista, hashedString);
}
as you can I see, I don't manage any xml/json deserialzing phase, it is managed by the wcf routine. For example, if I send a json list, it converts it to a List. This is what also with xml I want to see, but I'm getting the error at the top of this question.
ANOTHER UPDATE: I have to send 3 parameters in xml, so.... this is my last attempt, I think it is more correct than previouses. Now the server gives null reference error:
<?xml version="1.0" encoding="utf-8" ?>
<SetClientiXML
xmlns="http://tempuri.org/">
<XMLRequest>
<ArrayOfWrapClienti
xmlns="http://schemas.datacontract.org/2004/07/aaa"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<WrapClienti>
<CODRETE>111</CODRETE>
<CODICE>111</CODICE>
<NOME>aaa</NOME>
<INDIRIZZO>aaa</INDIRIZZO>
<CITTA>aaa</CITTA>
<CAP>aaa</CAP>
<PROV>aa</PROV>
<CODICEFISCALE>111</CODICEFISCALE>
<PIVA>2236401111236</PIVA>
<EMAIL/>
<ESPOSIZ_CONTABILE>111</ESPOSIZ_CONTABILE>
<STATO>FALSE</STATO>
</WrapClienti>
</ArrayOfWrapClienti>
<RETISTA>1111</RETISTA>
<HASHEDSTRING>oklkokokokok</HASHEDSTRING>
</XMLRequest>
</SetClientiXML>
I have also created this class:
[DataContract]
public class XMLRequest
{
[DataMember]
public List<WrapClienti> XML;
[DataMember]
public string RETISTA;
[DataMember]
public string HASHEDSTRING;
public XMLRequest() { }
public XMLRequest(List<WrapClienti> x, string r, string h)
{
this.HASHEDSTRING = h;
this.XML = x;
this.RETISTA = r;
}
}
and the portotype now is:
public GenericResponse SetClientiXML(XMLRequest xr)
Does this work?
string input =
"<ArrayOfWrapClienti xmlns=\"http://schemas.datacontract.org/2004/07/MultipayOnline\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
"<WrapClienti>" +
"<CODRETE>0018</CODRETE>" +
"<CODICE>20685</CODICE>" +
"<NOME>A.T.E.R. Azienda Territoriale</NOME>" +
"<INDIRIZZO>PIAZZA POZZA</INDIRIZZO>" +
"<CITTA>Verona</CITTA>" +
"<CAP>37123</CAP>" +
"<PROV>VR</PROV>" +
"<CODICEFISCALE>00223640236</CODICEFISCALE>" +
"<PIVA>223640236</PIVA>" +
"<EMAIL/>" +
"<ESPOSIZ_CONTABILE>937,02</ESPOSIZ_CONTABILE>" +
"<STATO>FALSE</STATO>" +
"</WrapClienti>" +
"</ArrayOfWrapClienti>";
input = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + input;
Here is code to serialize and de-serialize your xml
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication2
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
SetClientiXML client = new SetClientiXML()
{
xmlRequest = new XMLRequest()
{
arrayOfWrapClienti = new ArrayOfWrapClienti()
{
wrapClient = new List<WrapClient>() {
new WrapClient {
codrete = "0018",
codice = "20685",
nome = "A.T.E.R. Azienda Territoriale",
indirizzo = "PIAZZA POZZA",
citta = "Verona",
cap = "37123",
prov = "VR",
codiceFiscale = "00223640236",
piva = "223640236",
esposizContabile = "937,02",
stato = false
}
}
}
},
retista = "3303903",
hashedString = "oklkokokokok"
};
XmlSerializer serializer = new XmlSerializer(typeof(SetClientiXML));
StreamWriter writer = new StreamWriter(FILENAME);
serializer.Serialize(writer, client);
writer.Flush();
writer.Close();
writer.Dispose();
XmlSerializer xs = new XmlSerializer(typeof(SetClientiXML));
XmlTextReader reader = new XmlTextReader(FILENAME);
SetClientiXML newClient = (SetClientiXML)xs.Deserialize(reader);
}
}
[XmlRoot("SetClientiXML")]
public class SetClientiXML
{
[XmlElement("XMLRequest")]
public XMLRequest xmlRequest { get; set; }
[XmlElement("RETISTA")]
public string retista { get; set; }
[XmlElement("HASHEDSTRING")]
public string hashedString { get; set; }
}
[XmlRoot("XMLRequest")]
public class XMLRequest
{
[XmlElement("ArrayOfWrapClienti")]
public ArrayOfWrapClienti arrayOfWrapClienti { get; set; }
}
[XmlRoot("ArrayOfWrapClienti")]
public class ArrayOfWrapClienti
{
[XmlElement("WrapClient")]
public List<WrapClient> wrapClient { get; set; }
}
[XmlRoot("WrapClient")]
public class WrapClient
{
[XmlElement("CODRETE")]
public string codrete { get; set; }
[XmlElement("CODICE")]
public string codice { get; set; }
[XmlElement("NOME")]
public string nome { get; set; }
[XmlElement("INDIRIZZO")]
public string indirizzo { get; set; }
[XmlElement("CITTA")]
public string citta { get; set; }
[XmlElement("CAP")]
public string cap { get; set; }
[XmlElement("PROV")]
public string prov { get; set; }
[XmlElement("CODICEFISCALE")]
public string codiceFiscale { get; set; }
[XmlElement("PIVA")]
public string piva { get; set; }
[XmlElement("EMAIL")]
public string email { get; set; }
[XmlElement("ESPOSIZ_CONTABILE")]
public string esposizContabile { get; set; }
[XmlElement("STATO")]
public Boolean stato { get; set; }
}
}
Question: How does the class for the serialization of this XML content look ?
<?xml version="1.0" encoding="utf-8"?>
<vcc:CreateTextSearchResponse xmlns:vcc="urn:veloconnect:catalog-1.1" xmlns:vct="urn:veloconnect:transaction-1.0">
<vct:BuyersID>12345</vct:BuyersID>
<vct:ResponseCode>200</vct:ResponseCode>
<vct:TransactionID>225</vct:TransactionID>
<vct:StatusCode>2</vct:StatusCode>
<vct:IsTest>false</vct:IsTest>
<vcc:TotalCount>3876</vcc:TotalCount>
</vcc:CreateTextSearchResponse>
If I let it run through xsd.exe, it generates an error.
I have no problem generating this:
<?xml version="1.0" encoding="utf-8"?>
<CreateTextSearchResponse>
<BuyersID>15942</BuyersID>
<ResponseCode>200</ResponseCode>
<TransactionID>225</TransactionID>
<StatusCode>2</StatusCode>
<IsTest>false</IsTest>
<TotalCount>3876</TotalCount>
</CreateTextSearchResponse>
It's just that I need those namespaces to deserialize it (and later on reserialize), so I can't just leave it like this (it's needed by a 3rd party web-service)...
Like this:
[XmlRoot(Namespace = CreateTextSearchResponse.CatalogNamespace)]
public class CreateTextSearchResponse
{
public const string CatalogNamespace = "urn:veloconnect:catalog-1.1",
TransactionNamespace = "urn:veloconnect:transaction-1.0";
[XmlElement(Namespace=TransactionNamespace)]
public int BuyersId { get; set; }
[XmlElement(Namespace = TransactionNamespace)]
public int ResponseCode { get; set; }
[XmlElement(Namespace = TransactionNamespace)]
public int TransactionID { get; set; }
[XmlElement(Namespace = TransactionNamespace)]
public int StatusCode { get; set; }
[XmlElement(Namespace = TransactionNamespace)]
public bool IsTest { get; set; }
[XmlElement(Namespace = CatalogNamespace)]
public int TotalCount { get; set; }
}
public static void Main()
{
var ser = new XmlSerializer(typeof(CreateTextSearchResponse));
var obj = new CreateTextSearchResponse
{
BuyersId = 12345,
ResponseCode = 200,
TransactionID = 225,
StatusCode = 2,
IsTest = false,
TotalCount = 3876
};
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("vcc", CreateTextSearchResponse.CatalogNamespace);
ns.Add("vct", CreateTextSearchResponse.TransactionNamespace);
ser.Serialize(Console.Out, obj, ns);
}
unfortunately there are special characters in your namesapce that Xml can't handle