HttpClient send XML PostAsync Malformed request: Premature end of file? - c#

I am trying to send a xml to a server and it always throw an exception Malformed request: Premature end of file.. . Using the Postman it works well but using HttpClient it doesn't, I think the problem is with headers what server needs is Content-Type", "application/xml and I cannot do it works
How could I fix it ?
trying
//HttpClient
HttpClient hClient = new HttpClient();
hClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/xml");
//post
var contentString = new StringContent(xml, Encoding.UTF8, "application/xml");
HttpResponseMessage response = hClient.PostAsync(URL_FINAL, contentString).GetAwaiter().GetResult();
var resultContent = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
xml
<?xml version="1.0" encoding="utf-16"?>
<payment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<mode>default</mode>
<method>creditCard</method>
<sender>
<name>Meu Nome</name>
<email>email#gmail.com</email>
<phone>
<areaCode>17</areaCode>
<number>9999999999</number>
</phone>
<documents>
<document>
<type>CPF</type>
<value>9999999999</value>
</document>
</documents>
<hash>5e5240axxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxea8a</hash>
</sender>
<currency>BRL</currency>
<notificationURL>https://dominio.com/StatusPagamentoTransaction</notificationURL>
<items>
<item>
<id>2</id>
<description>produto</description>
<quantity>2</quantity>
<amount>2.00</amount>
</item>
</items>
<extraAmount>0.00</extraAmount>
<reference>R748</reference>
<shipping>
<addressRequired>false</addressRequired>
</shipping>
<creditCard>
<token>91999999999999999999b0f</token>
<installment>
<quantity>1</quantity>
<value>2.00</value>
</installment>
<holder>
<name>nome proprietario cartao</name>
<documents>
<document>
<type>CPF</type>
<value>99999999999</value>
</document>
</documents>
<birthDate>18/12/1964</birthDate>
<phone>
<areaCode>17</areaCode>
<number>99999999</number>
</phone>
</holder>
<billingAddress>
<street>rua A</street>
<number>3333</number>
<district>bairro</district>
<city>cidade</city>
<state>SP</state>
<country>BRA</country>
<postalCode>05407002</postalCode>
</billingAddress>
</creditCard>
</payment>
Exception
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?><errors><error><code>11213</code><message>Malformed request: Premature end of file..</message></error></errors>

Try to set Accept header
hClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
Instead of
hClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/xml");

Related

How to read an existing SOAP XML message?

I am trying to read a SOAP message such as the following one:
https://raw.githubusercontent.com/mrjeffstevenson3/mmimproc/master/data/testdata/examcard/PHANTOM_QT1_SLU_20151230.ExamCard
This is an XML file which starts with:
<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:ExamCard id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/Philips.PmsMR.ExamCards.ECModel/philips.pmsmr.examcards.ecmodel_cs">
How am I supposed to read such file ? How can I write the code for rootClass ? Pseudo code:
var mySerializer = new XmlSerializer(typeof(rootClass));
using var myFileStream = new FileStream("PHANTOM_QT1_SLU_20151230.ExamCard", FileMode.Open);
var myObject = (rootClass)mySerializer.Deserialize(myFileStream);

How to pass XML input to API call using C#

I have below XML input. I need to call API and pass this as input but values will change dynamically. How can I build this input structure?
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Test xmlns="http://tempuri.org/">
<acc>test</acc>
<pass>abc</pass>
<xmlInvData>
<![CDATA[
<MyData>
<name>test</name>
<number>900</number>
</MyData>
]]>
</xmlInvData>
<username>test</username>
<password>123</password>
</Test>
</soap:Body>
</soap:Envelope>
I have MyData Class in C# which can be useful to setup name and number values.
But how can I form a complete structure and pass to Api call? soap:Envelop and soap body?
HttpClient httpClient = new HttpClient();
string requestUri = "https://testurl";
var byteArray = Encoding.ASCII.GetBytes("username:password");
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
HttpResponseMessage response = await httpClient.PostAsync(requestUri, httpContent);
I need to understand how to form httpContent as above my input json.
Assuming you've built the data structure and serialized it to a string called xml:
var httpContent = new StringContent(xml, Encoding.UTF8, "application/xml");

Connecting To Web Services through Xamarin

I am new to Xamarin and am trying to connect to my client web services whose address is http://smartasset-utw.malaysiaairports.com.my:5010/service1.asmx?op=GetUserLogin. This is used to authenticate logins. The code that I have used is below.
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/xml"));
httpClient.DefaultRequestHeaders.Add("SOAPAction", "http://smartasset-utw.malaysiaairports.com.my:5010/service1.asmx?WSDL");
string wUser = "XXXXX";
string wPassword = "xxxxxxxx";
string soapstr = string.Format(#"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
<soap:Body>
<GetUserLogin xmlns=""http://tempuri.org/"">
<userName>{0}</userName>
<password>{1}</password>
</GetUserLogin>
</soap:Body>
</soap:Envelope>", wUser, wPassword);
var response = httpClient.PostAsync("http://smartasset-utw.malaysiaairports.com.my:5010/service1.asmx?WSDL", new StringContent(soapstr, Encoding.UTF8, "text/xml")).Result;
var content = response.Content.ReadAsStringAsync().Result;
Unfortunately, the response that I get is:
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><faultcode>soap:Client</faultcode><faultstring>Server did not recognize the value of HTTP Header SOAPAction: http://smartasset-utw.malaysiaairports.com.my:5010/service1.asmx.</faultstring><detail /></soap:Fault></soap:Body></soap:Envelope>
Any help would be appreciated,
Thanks

XmlDocument CreateElement without xmlns under a prefixed element

I'm trying to compose a SOAP request to ebay FindingAPI web service by using C# XmlDocument class in the following code:
XmlDocument doc = new XmlDocument();
XmlElement root = (XmlElement)doc.AppendChild(doc.CreateElement("soap", "Envelope", "http://www.w3.org/2003/05/soap-envelope"));
root.SetAttribute("xmlns", "http://www.ebay.com/marketplace/search/v1/services");
XmlElement header = (XmlElement)root.AppendChild(doc.CreateElement("soap", "Header", "http://www.w3.org/2003/05/soap-envelope"));
XmlElement body = (XmlElement)root.AppendChild(doc.CreateElement("soap", "Body", "http://www.w3.org/2003/05/soap-envelope"));
XmlElement request = (XmlElement)body.AppendChild(doc.CreateElement("findItemsByKeywordsRequest"));
XmlElement param = (XmlElement)request.AppendChild(doc.CreateElement("keywords"));
param.InnerText = "harry potter phoenix";
And, the XML output of above code is:
<soap:Envelope xmlns="http://www.ebay.com/marketplace/search/v1/services" xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header />
<soap:Body>
<findItemsByKeywordsRequest xmlns="">
<keywords>harry potter phoenix</keywords>
</findItemsByKeywordsRequest>
</soap:Body>
</soap:Envelope>
However, this XML can't be recognized by the server because of the extra xmlns="" attribute in the findItemsByKeywordsRequest element. The desired XML output should be as below:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns="http://www.ebay.com/marketplace/search/v1/services">
<soap:Header/>
<soap:Body>
<findItemsByKeywordsRequest>
<keywords>harry potter phoenix</keywords>
</findItemsByKeywordsRequest>
</soap:Body>
</soap:Envelope>
Does anyone know what is the problem of my code and please give me some hints. Thanks!
Because your document has default namespace declared in the most outer element you have to repeat that namespace on every child element to avoid adding additional empty one.
Change request and param elements declaration to contain "http://www.ebay.com/marketplace/search/v1/services" namespace
XmlElement request = (XmlElement)body.AppendChild(doc.CreateElement("findItemsByKeywordsRequest", "http://www.ebay.com/marketplace/search/v1/services"));
XmlElement param = (XmlElement)request.AppendChild(doc.CreateElement("keywords", "http://www.ebay.com/marketplace/search/v1/services"));
With these changes your code produces following XML:
<soap:Envelope xmlns="http://www.ebay.com/marketplace/search/v1/services" xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header />
<soap:Body>
<findItemsByKeywordsRequest>
<keywords>harry potter phoenix</keywords>
</findItemsByKeywordsRequest>
</soap:Body>
</soap:Envelope>

Customize XML Serialize With new Tags And Attributes And Root

This is my Type:
public class MyObject {
public string destAdd { get; set; }
public long Time { get; set; }
public int maxNumb { get; set; }
public Account AccountCredentials { get; set; }
public System.String Serialize() {
String result = "";
XmlSerializer xs = new XmlSerializer(typeof(MyObject));
MemoryStream ms = new MemoryStream();
xs.Serialize(ms, this);
result = System.Text.Encoding.UTF8.GetString(ms.ToArray());
ms.Close();
ms.Dispose();
xs = null;
return result;
}
public static MyObject DeSerialize(String s) {
MyObject result = new MyObject();
XmlSerializer xs = new XmlSerializer(typeof(MyObject));
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(s));
result = (MyObject)xs.Deserialize(ms);
ms.Close();
ms.Dispose();
xs = null;
return result;
}
}
Then I serialize it like this:
MyObject obj = new MyObject();
obj.destAdd = "Destination";
obj.maxNumb = 99;
obj.Time = 128;
obj.Account = new Account { username = "user", password = "pass" };
string seializeObj = obj.Serialize();
The result is:
<?xml version="1.0"?>
<MyObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<destAdd>Destination</destAdd>
<Time>128</Time>
<maxNumb>99</maxNumb>
<Account>
<username>user</username>
<password>pass</password>
</Account>
</MyObject>
But I need the following result:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:smag="http://targetaddress.com/">
<soapenv:Header>
<Account>
<username>user</username>
<password>pass</password>
</Account>
</soapenv:Header>
<soapenv:Body>
<smag:myobjinfos>
<destAdd>Destination</destAdd>
<Time>128</Time>
<maxNumb>99</maxNumb>
</smag:myobjinfos>
</soapenv:Body>
</soapenv:Envelope>
How can I implement the serialize to get this result? any suggestion?
It appears that you are trying to call a web service, with a custom security header. Usually, the easiest way to do this would be to generate a set of proxy classes from the WSDL of the target webservice.
Either
Right click on the use Add Service Reference / Add Web Reference from the Visual Studio
Or, if you have the WSDL and xsd files of the service, then use wsdl.exe command line tool (e.g. wsdl.exe *.wsdl *.xsd //language:c#)
See here on how to set security information on the ws:security header
However, if you are 100% sure that you need to obtain the exact soapEnv Xml above, I would suggest you keep your code 'as is' (i.e. just serialize MyObject in its default format using XmlSerializer or DataContractSerializer), and then use a XslCompiledTransform.
This XSLT will do exactly this:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="/MyObject">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:smag="http://targetaddress.com/">
<soapenv:Header>
<Account>
<username><xsl:value-of select="Account/username"/></username>
<password><xsl:value-of select="Account/password"/></password>
</Account>
</soapenv:Header>
<soapenv:Body>
<smag:myobjinfos>
<destAdd><xsl:value-of select="destAdd"/></destAdd>
<Time><xsl:value-of select="Time"/></Time>
<maxNumb><xsl:value-of select="maxNumb"/></maxNumb>
</smag:myobjinfos>
</soapenv:Body>
</soapenv:Envelope> </xsl:template>
</xsl:stylesheet>
Converts
<?xml version="1.0"?>
<MyObject>
<destAdd>Destination</destAdd>
<Time>128</Time>
<maxNumb>99</maxNumb>
<Account>
<username>user</username>
<password>pass</password>
</Account>
</MyObject>
To this:
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:smag="http://targetaddress.com/">
<soapenv:Header>
<Account>
<username>user</username>
<password>pass</password>
</Account>
</soapenv:Header>
<soapenv:Body>
<smag:myobjinfos>
<destAdd>Destination</destAdd>
<Time>128</Time>
<maxNumb>99</maxNumb>
</smag:myobjinfos>
</soapenv:Body>
</soapenv:Envelope>

Categories

Resources