Post SOAP envelop to MS Dynamics NAV Web Service - c#

I am trying to post SOAP Envelope directly to Dynamics NAV Webservices using HttpWebRequest, HttpWebResponse.
Code:
private void button1_Click(object sender, EventArgs e)
{
string requestString = LoadData();
HttpWebRequest request;
HttpWebResponse response = null;
string url = "http://localhost:7047/DynamicsNAV70/WS/Page/nav_Item";
byte[] requestBuffer = null;
Stream postStream = null;
Stream responseStream = null;
StreamReader responseReader = null;
request = (HttpWebRequest)WebRequest.Create(url);
request.ProtocolVersion = new Version(1,1);
request.Method = "POST";
//request.Headers.Add("SOAPAction", #"urn:microsoft-dynamics-schemas/page/nav_item:create");
request.Headers.Add("Action", #"urn:microsoft-dynamics-schemas/page/nav_item");
//request.Headers.Add("Content-Type", #"text/xml; charset=utf-8");
request.ContentType = #"application/xml; charset=utf-8";
requestBuffer = Encoding.ASCII.GetBytes(requestString);
request.ContentLength = requestBuffer.Length;
request.UseDefaultCredentials = true;
postStream = request.GetRequestStream();
postStream.Write(requestBuffer, 0, requestBuffer.Length);
postStream.Close();
response = (HttpWebResponse)request.GetResponse();
responseStream = response.GetResponseStream();
string response_result=string.Empty;
if (responseStream != null)
{
responseReader = new StreamReader(responseStream);
response_result = responseReader.ReadToEnd();
}
MessageBox.Show(response_result);
}
private string LoadData()
{
// throw new NotImplementedException();
XmlDocument oCustomer = new XmlDocument();
oCustomer.Load(#"C:\Users\kishore.LOCAL.000\Desktop\NAV_DEMO\NAV_DEMO\bin\Debug\input\item.xml");
return oCustomer.InnerXml;
}
Format of SOAP Envelope is below:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ins="urn:microsoft-dynamics-schemas/page/nav_item">
<soapenv:Header/>
<soapenv:Body>
<ins:Create>
<ins:nav_Item>
<!--Optional:-->
<ins:Key>?</ins:Key>
<!--Optional:-->
<ins:No>1234</ins:No>
<!--Optional:-->
<ins:Description>Test Item</ins:Description>
</ins:nav_Item>
</ins:Create>
</soapenv:Body>
</soapenv:Envelope>
But when I am trying to get response without Header in HttpWebRequest, its returning whole web service in xml format with Status OK, but Item is not inserting in NAV.
When I am trying to get response with Header in HttpWebRequest, its {"The remote server returned an error: (500) Internal Server Error." System.Net.WebExceptionStatus.ProtocolError}
I want to create Item in NAV using soap envelope not by direct referencing the service.
Any help will helpful to me.
With Regards
Kishore K

It looks like you using SOAPui to create request xml. This app always adds invisible chars at the end of each line. Delete them.
Also try to unformat your request, e.g. make it in one line. For unknown reason Nav threats linebreake between certain tags as error (throws http 500). I just forgot which tags (header and body may be). The rest linebreaks are fine.
And SOAPAction header is mandatory so use it or you will get wsdl in response all the time.
P.s. beta of SOAPui works fine with Nav and supports NTLM so you can use it to test different request xml and find which format is correct.

I am new to using intergrating with nav web services, I am trying to send an xml request using a simple c# console application but it is always returning a 401(unauthorised)
static void Main(string[] args)
{
Console.WriteLine("We have started");
string pageName = "http://hrp-dmu.uganda.hrpsolutions.co.ug:9047/DynamicsNAV80/WS/Uganda%20Management%20Institute/Page/CustomerWS";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(pageName);
req.Method = "POST";
req.ContentType = "text/xml;charset=UTF-8";
req.ProtocolVersion = new Version(1, 1);
req.Headers.Add("SOAPAction", #"urn:microsoftdynamicsschemas/page/customerws:Create");
Console.WriteLine("After preparing request object");
string xmlRequest = GetTextFromXMLFile("E:\\tst3.xml");
Console.WriteLine("xml request : "+xmlRequest);
byte[] reqBytes = new UTF8Encoding().GetBytes(xmlRequest);
req.ContentLength = reqBytes.Length;
try
{
using (Stream reqStream = req.GetRequestStream())
{
reqStream.Write(reqBytes, 0, reqBytes.Length);
}
}
catch (Exception ex)
{
Console.WriteLine("GetRequestStreamException : " + ex.Message);
}
HttpWebResponse resp = null;
try
{
resp = (HttpWebResponse)req.GetResponse();
}
catch (Exception exc)
{
Console.WriteLine("GetResponseException : " + exc.Message);
}
string xmlResponse = null;
if (resp == null)
{
Console.WriteLine("Null response");
}
else
{
using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
xmlResponse = sr.ReadToEnd();
}
Console.WriteLine("The response");
Console.WriteLine(xmlResponse);
}
Console.ReadKey();
}
private static string GetTextFromXMLFile(string file)
{
StreamReader reader = new StreamReader(file);
string ret = reader.ReadToEnd();
reader.Close();
return ret;
}

Related

HttpWebRequest.getResponse() returning NULL

I am attempting to create a console app that sends a WebRequest to a website so that I can get some information back from it in JSON format. Once I build up the request and try to get response I just want to simply print out the data, but when I call httpWebRequest.getResponse() it returns NULL.
I have tried multiple other methods of sending the data to the the url but those are all giving me like 404, or 400 errors, etc. This method at least isn't giving me any error, just a NULL.
Here is a snapshot of the documentation I am using for the API (albeit the docs aren't complete yet):
Here is the console app code that I have right now:
try
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://api.remot3.it/apv/v27/user/login");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
httpWebRequest.Headers.Add("developerkey", "***KEY***");
using (var streamWriter = new
StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = new JavaScriptSerializer().Serialize(new
{
email = "***EMAIL***",
password = "***PASSWORD***"
});
Console.WriteLine(json);
streamWriter.Write(json);
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
Console.WriteLine(result);
Console.ReadLine();
}
}catch(Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
Console.ReadLine();
}
Expected output is some JSON data, but I am getting a NULL back from getResponse().
Try to serialize the credential in your form and for header send as parameter for this class.
Check below for my code. It is not 100 % fit to your requirement, but atleast it will help to get through your logic.
Here is what I get Json Response from this code. Its work Perfect. Please remember to add timeout option on your webrequest and at the end close the streamreader and stream after completing your task. please check this code.
public static string httpPost(string url, string json)
{
string content = "";
byte[] bs;
if (json != null && json != string.Empty)
{
bs = Encoding.UTF8.GetBytes(json);
}
else
{
bs = Encoding.UTF8.GetBytes(url);
}
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url);
req.Method = "POST";
if (json != string.Empty)
req.ContentType = "application/json";
else
req.ContentType = "application/x-www-form-urlencoded";
req.KeepAlive = false;
req.Timeout = 30000;
req.ReadWriteTimeout = 30000;
//req.UserAgent = "test.net";
req.Accept = "application/json";
req.ContentLength = bs.Length;
using (Stream reqStream = req.GetRequestStream())
{
reqStream.Write(bs, 0, bs.Length);
reqStream.Flush();
reqStream.Close();
}
using (WebResponse wr = req.GetResponse())
{
Stream s = wr.GetResponseStream();
StreamReader reader = new StreamReader(s, Encoding.UTF8);
content = reader.ReadToEnd();
wr.Close();
s.Close();
reader.Close();
}
return content;
}

Why does my API POST Request keep failing?

I am doing an API Post request and cant seem to get it to work. I always get a sendFailure webexception and the response for the exception is always null so catching the exception is useless. It keeps happening when I try to get the httpWebResponse. I noticed too the request.contentlength gave errors at postream getrequeststream so i commented it out. Test.json is the file I use for the request body. I also tested this on different API testers by including the URL, body, and content-type in the header and they worked. I just cant seem to code it for myself. The credentials work I just dont know if im doing the request correctly?
JSON File:
{
"email": "abc#123.com",
"password": "12345",
"facilityNumber": "987654"
}
string filepath = "test.json";
string result = string.Empty;
using (StreamReader r = new StreamReader(filepath))
{
var json = r.ReadToEnd();
var jobj = JObject.Parse(json);
foreach (var item in jobj.Properties())
{
item.Value = item.Value.ToString().Replace("v1", "v2");
}
result = jobj.ToString();
Console.WriteLine(result);
}
try
{
string setupParameters;
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("https://www.test.com/abcde");
request.AllowAutoRedirect = true;
setupParameters = result;
ServicePointManager.ServerCertificateValidationCallback = (s, cert, chain, ssl) => true;
ASCIIEncoding encoding = new ASCIIEncoding();
var postData = setupParameters;
request.Method = "POST";
request.ContentType = "application/json";
byte[] data = encoding.GetBytes(postData);
//request.ContentLength = data.Length;
using (StreamWriter postStream = new StreamWriter(request.GetRequestStream()))//error if uncomment contentlength
{
postStream.Write(postData);
postStream.Flush();
postStream.Close();
}
HttpWebResponse wr = (HttpWebResponse)request.GetResponse();//error occurs
Stream receiveStream = wr.GetResponseStream();
StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);
}
catch (WebException ex)
{
if (ex.Response != null)
{
using (var errorResponse = (HttpWebResponse)ex.Response)
{
using (var reader = new StreamReader(errorResponse.GetResponseStream()))
{
string error = reader.ReadToEnd();
result = error;
}
}
}
I suggest modifiying your request to follow this format. Especially pay attention to the request.Method and request.ContentType which have caught me out multiple times.
Also, handling the response is easier this way.
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(YOURURL);
request.ContentType = "application/json; charset=utf8";
request.Headers.Add(ADD HEADER HERE IF YOU NEED ONE);
request.Method = WebRequestMethods.Http.Post; // IMPORTANT
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(JsonConvert.SerializeObject(JSONBODYSTRING));
// I USUALLY YOU JSONCONVERT HERE TO SIMPLY SERIALIZE A STRING CONTAINING THE JSON INFO.
//BUT I GUESS YOUR METHOD WOULD ALSO WORK
streamWriter.Flush();
streamWriter.Close();
}
WebResponse response = request.GetResponse();
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
string result = streamReader.ReadToEnd();
// DO WHATEVER YOU'D LIKE HERE
}
} catch (Exception ex)
{
// HANDLE YOUR EXCEPTIONS
}

HTTPWebRequest Response Error when sending SOAP

I am using XDocument to manually build a SOAP request and send it using HTTPWebRequest. The final output of the XDocument object is valid and when I capture and send it to the end point using SOAPUI it works fine, however; I have been unable to get this to work using HTTPWebRequest. I receive internal server server errors, but nothing really specific that I can work from. I am excluding the XDocument object for brevity. Any guidance would be appreciated.
var _url = "http://xxx.xx.x.xx:9191/aa/bb/cc/dd";
var _action = "http://xxx.xx.x.xx:9191/aa/bb/cc/dd?op=submit";
HttpWebRequest webRequest = (HttpWebRequest) WebRequest.Create(_url);
webRequest.Headers.Add(#"SOAPAction", _action);
webRequest.Credentials = new NetworkCredential("xxxxx", "xxxxxx");
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
using (Stream stream = webRequest.GetRequestStream())
{
xd.Save(stream);
}
// get the response from the completed web request.
string soapResult;
try
{
using (WebResponse webResponse = webRequest.GetResponse())
{
using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))
{
soapResult = rd.ReadToEnd();
}
Response.Write(soapResult);
}
}
catch (WebException ex)
{
if (ex.Status == WebExceptionStatus.ProtocolError)
{
Response.Write("Status Code : " + ((HttpWebResponse) ex.Response).StatusCode);
Response.Write("Status Description : " + ((HttpWebResponse) ex.Response).StatusDescription);
}
}
UPDATE (included small sample of SOAP):
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<enrollment xmlns="xxxxxxxxxxx">
<asOfDate xmlns="">2018-01-01</asOfDate>
<activate xmlns="">false</activate>
<subscription xmlns="">
<receiptDate>2018-06-01</receiptDate>
<accountMatchData>
<accountHccIdentifier>
<accountHccIdentificationNumber>xxxxxxxxxx</accountHccIdentificationNumber>
</accountHccIdentifier>
<asOfDate>2018-01-01</asOfDate>
</accountMatchData>
<informationSourceCode>
<codeEntry>3</codeEntry>
</informationSourceCode>
</subscription>
</enrollment>
</s:Body>
</s:Envelope>
UPDATE (Solved):
I cannot believe it was something as stupid as how it was sending the credentials. I used the below code to generate the credentials and add them to the HTTPWebRequest and it worked.
string credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes("xxxx" + ":" + "xxxxxxx"));
HttpWebRequest webRequest = (HttpWebRequest) WebRequest.Create(_url);
webRequest.Headers[HttpRequestHeader.Authorization] = string.Format(
"Basic {0}", credentials);

Sending xml using Apache HttpComponents

I am attempting to replicate the following C# code in Java. This code is a helper class that sends a request containing xml, and reads a response.
internal static String Send(String url, String body)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
try
{
// create the new httpwebrequest with the uri
request.ContentLength = 0;
// set the method to POST
request.Method = "POST";
if (!String.IsNullOrEmpty(body))
{
request.ContentType = "application/xml; charset=utf-8";
byte[] postData = Encoding.Default.GetBytes(body);
request.ContentLength = postData.Length;
using (Stream s = request.GetRequestStream())
{
s.Write(postData, 0, postData.Length);
}
}
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
String responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
if (response.StatusCode != HttpStatusCode.OK)
{
throw new ResponseException(((int)response.StatusCode),
response.StatusCode.ToString(), request.RequestUri.ToString(),
responseString);
}
return responseString;
}
}
catch (WebException e)
{
using (WebResponse response = e.Response)
{
HttpWebResponse httpResponse = response as HttpWebResponse;
if (httpResponse != null)
{
using (Stream data = response.GetResponseStream())
{
data.Position = 0;
throw new ResponseException(((int)httpResponse.StatusCode),
httpResponse.StatusCode.ToString(), request.RequestUri.ToString(),
new StreamReader(data).ReadToEnd()
);
}
}
else
{
throw;
}
After reading other threads I determined that the Apache HttpComponents library would be my best bet to get the same functionality. After reading the documentation and following the example here:
http://hc.apache.org/httpcomponents-client-ga/quickstart.html
I am unable to figure out how to send the body string as xml. When I attempt to set the entity for the request it requires that I declare a BasicNameValuePair, and I do not understand what this is, or how I would format the body string to meet this specification.
Below is what I have currently done.
protected static String Send(String url, String body)
{
HttpPost request = new HttpPost(url);
try
{
request.setHeader("ContentType", "application/xml; charset=utf=8");
// Encode the body if needed
request.setEntity(new UrlEncodedFormEntity());
//get the response
// if the response code is not valid throw a ResponseException
// else return the response string.
} finally {
request.releaseConnection();
}
return null;
}
EDIT : or should I use a StringEntity and do the following
protected static String SendToJetstream(String url, String body)
{
HttpPost request = new HttpPost(url);
try
{
StringEntity myEntity = new StringEntity(body,
ContentType.create("application/xml", "UTF-8"));
// Encode the body if needed
request.setEntity(myEntity);
//get the response
// if the response code is not valid throw a ResponseException
// else return the response string.
} finally {
request.releaseConnection();
}
return null;
}
Use a FileEntity
File file = new File("somefile.xml");
FileEntity entity = new FileEntity(file, ContentType.create("application/xml", "UTF-8"));
Lots of good examples here: http://hc.apache.org/httpcomponents-client-ga/tutorial/html/fundamentals.html#d5e165

Internal Server Error (500) when doing SOAP request

I am trying to do a SOAP request but the server is returning an 500 error.
The SOAP request returns correctly the XML message via jmeter for example, so it must be something in my code, but i fail to see what. Can you help?
private void soapRequest(string regID)
{
string soapReq= #"<?xml version=""1.0"" encoding=""utf-8""?>";
soapReq= "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:mpc=\"urn://mobility-platform.de/mpcustomerdb/\">\n";
soapReq += "<soapenv:Header/>\n";
soapReq += "<soapenv:Body>\n";
soapReq += "<mpc:findRegistrationByID>\n";
soapReq += "<registrationID>" + regID + "</registrationID>\n";
soapReq += "</mpc:findRegistrationByID>\n";
soapReq += "</soapenv:Body>\n";
soapReq += "</soapenv:Envelope>";
//Builds the connection to the WebService.
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://url?wsdl");
req.Credentials = new NetworkCredential("user", "pass");
req.Headers.Add("SOAP:Action");
req.ContentType = "text/xml;charset=\"utf-8\"";
req.Accept = "text/xml";
req.Method = "POST";
//Passes the SoapRequest String to the WebService
using (Stream stm = req.GetRequestStream())
{
using (StreamWriter stmw = new StreamWriter(stm))
{
stmw.Write(soapReq.ToString());
}
}
try
{
//Gets the response
HttpWebResponse soapResponse = (HttpWebResponse)req.GetResponse();
//Writes the Response
Stream responseStream = soapResponse.GetResponseStream();
//read the stream
XmlDocument soapResponseXML = new XmlDocument();
StreamReader responseStreamRead = new StreamReader(responseStream);
soapResponse.ContentType = "text/xml";
//MessageBox.Show(responseStreamRead.ReadToEnd().ToString());
string soapURL = responseStreamRead.ReadToEnd().ToString();
soapResponseXML.LoadXml(soapURL);
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message);
}
}
Here is the soap request
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mpc="urn://mobility-platform.de/mpcustomerdb/">
<soapenv:Header/>
<soapenv:Body>
<mpc:findRegistrationByID>
<registrationID>2304580</registrationID>
</mpc:findRegistrationByID>
</soapenv:Body>
</soapenv:Envelope>
Later edit:
If i change
req.Headers.Add("SOAP:Action"); to:
req.Headers.Add("SOAPAction", ""\"http://url\"" + "findRegistrationByID");
i get an different error:
"This property is not implemented by this class"
Is not very easy to make an proper soap request with this method. I am strongly recommending to use rather the whole web service, and rather make the request like this:
WebService aa = new WebService;
registrationName = aa.findRegistrationByID("123");
This will accomplish all the above code ;)

Categories

Resources