Calling a SOAP service from C# REST API - c#

I have a VBA code which calls a SOAP service and receives an XML response.
I want to write a C# REST API to call this SOAP service in a similar way.
Referring to the articles here I wrote a SOAP request but it does not works and returns the below error. I am able to call this SOAP service from the VBA code and also POST MAN. Can some one please explain what's wrong with my code?
public class CallSOAPAPIController : ApiController
{
[HttpGet]
public string Extract()
{
HttpWebRequest request = CreateWebRequest();
XmlDocument soapEnvelopeXml = new XmlDocument();
soapEnvelopeXml.LoadXml(#"<?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/"" xmlns:inc=""http://www.test-xyz.com/""><soap:Body>Calendar #Year#Month#1</soap:Body></soap:Envelope>");
using (Stream stream = request.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
using (WebResponse response = request.GetResponse())
{
using (StreamReader rd = new StreamReader(response.GetResponseStream()))
{
soapResult = rd.ReadToEnd();
Console.WriteLine(soapResult);
}
}
return soapResult;
}
/// <summary>
/// Create a soap webrequest to [Url]
/// </summary>
/// <returns></returns>
public static HttpWebRequest CreateWebRequest()
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(#"http://test.production-xyz.com/listofemployees.do?getdetails=all&SOAP");
webRequest.Headers.Add(#"SOAP:Action");
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
CallSOAPAPIController obj = new CallSOAPAPIController();
string base64Credentials = obj.GetEncodedCredentials();
webRequest.Headers.Add("Authorization", "Basic " + base64Credentials);
return webRequest;
}
private string GetEncodedCredentials()
{
string m_Username = "XXXXXX";
string m_Password = "XXXXXX";
string mergedCredentials = string.Format("{0}:{1}", m_Username, m_Password);
byte[] byteCredentials = UTF8Encoding.UTF8.GetBytes(mergedCredentials);
return Convert.ToBase64String(byteCredentials);
}
}
The error I get : "The remote server returned an error:(401) Unauthorized"
Unauthorized(401)

Related

HttpWebRequest return error 500 when GetResponse()

I'm trying to get a response from SOAP webservice, but I'm falling into a webexception Error 500.
This my class to get a response:
public static string getResponse()
{
StringBuilder xml = new StringBuilder();
//xml.Append(#"<?xml version=""1.0"" encoding=""utf-8""?>");
xml.Append(#"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:br=""http://www.totvs.com.br/br/"" >").Replace(#"\", "");
xml.Append("<soap:Envelope/>");
xml.Append("<soapenv:Body>");
xml.Append("<br:RealizarConsultaSQLAuth>");
xml.Append("<br:codSentenca>GLOBAL_054</br:codSentenca>");
xml.Append("<br:codColigada>0</br:codColigada>");
xml.Append("<br:codAplicacao>V</br:codAplicacao>");
xml.Append("<br:Usuario>xxxx</br:Usuario>");
xml.Append("<br:Senha>xxxx</br:Senha>");
xml.Append("<br:parameters>codcoligada=1;codsistema=V;codusuario=mestre</br:parameters>");
xml.Append("</br:RealizarConsultaSQLAuth>");
xml.Append("</soapenv:Body>");
xml.Append("</soapenv:Envelope>");
string s = getUKMailData(xml.ToString(), "http://xxx.xxxx.com.br:99/xxxx/wsConsultaSQL.asmx");
return s;
}
public static string getUKMailData(string xml, string address)
{
string result = "";
HttpWebRequest request = CreateWebRequest(address);
XmlDocument soapEnvelopeXml = new XmlDocument();
string teste = xml.Replace(#"\", "");
soapEnvelopeXml.LoadXml(teste);
try
{
using (Stream stream = request.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
using (WebResponse response = request.GetResponse())
{
using (StreamReader rd = new StreamReader(response.GetResponseStream()))
{
string soapResult = rd.ReadToEnd();
result = soapResult;
}
}
}
catch (WebException wex)
{
var pageContent = new StreamReader(wex.Response.GetResponseStream()).ReadToEnd();
}
return result;
}
public static HttpWebRequest CreateWebRequest(string url)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Headers.Add("SOAP:Action");
webRequest.Headers.Add("username", "xxx");
webRequest.Headers.Add("password", "xxx");
// webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
webRequest.PreAuthenticate = true;
webRequest.Credentials = CredentialCache.DefaultCredentials;
return webRequest;
}
anyone can help me? I already read a series of articles that unfortunately did not help me. Thanks a lot!
Your request maybe true but server-side doesn't know how to process your data. Maybe parameters which are sent fault. Please check your server-side so end-point.

How to Authenticate Certificate via HTTPS Request

I need to call a URL via POST Method. But I am getting a certificate issue during the call. Here is my code,
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class Service1 : System.Web.Services.WebService
{
[WebMethod]
public string CurrencyConverter(string IssueId,string FromCurrency,string ToCurrency)
{
string url;
url = "http://www.webservicex.net/currencyconvertor.asmx/ConversionRate?FromCurrency=" + FromCurrency + "&ToCurrency=" + ToCurrency;
HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(string.Format(url));
webReq.Method = "GET";
HttpWebResponse webResponse = (HttpWebResponse)webReq.GetResponse();
//I don't use the response for anything right now. But I might log the response answer later on.
Stream answer = webResponse.GetResponseStream();
StreamReader _recivedAnswer = new StreamReader(answer);
string content=_recivedAnswer.ReadToEnd();
XmlDocument xd = new XmlDocument();
xd.LoadXml(content);
content=xd.LastChild.InnerText;
url = "https://jira-mysql:8443/rest/api/2/issue/CPS-306";
WebRequest myReq = WebRequest.Create(url);
string username = "nmorshedi#aversan.com";
string password = "Aversan1";
string data = "{\"fields\":{\"Description\":\"" + content + "\"}}";
//ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
// You must change the URL to point to your Web server.
X509Certificate Cert = X509Certificate.CreateFromCertFile("C:\\jira.cer");
System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();
HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(url);
CredentialCache mycache = new CredentialCache();
mycache.Add(new Uri(url), "Basic", new NetworkCredential(username, password));
Request.Credentials = mycache;
Request.ClientCertificates.Add(Cert);
Request.UserAgent = "Client Cert Sample";
Request.Method = "POST";
Request.ContentLength = data.Length;
Request.ContentType = "application/json; charset=UTF-8";
Request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(new ASCIIEncoding().GetBytes(username + "&" + password)));
HttpWebResponse Response = (HttpWebResponse)Request.GetResponse();
Stream receiveStream = Response.GetResponseStream();
StreamReader reader = new StreamReader(receiveStream, Encoding.UTF8);
content = reader.ReadToEnd();
return content;
} // callback used to validate the certificate in an SSL conversation
//Implement the ICertificatePolicy interface.
public class TrustAllCertificatePolicy : System.Net.ICertificatePolicy
{
public TrustAllCertificatePolicy()
{ }
public bool CheckValidationResult(ServicePoint sp,
System.Security.Cryptography.X509Certificates.
X509Certificate cert, WebRequest req, int problem)
{
return true;
}
}
}
It keeps on loading. Can anyone help me?

Is it possible that I can convert simple string to SOAP Message and send it?

Currently I want to know that is it possible in c# to read string and convert it into Soapmessage and send it to server for processing and again convert response into the string ?
Your code should look something like :
var document = Query(user, pass, date, regc);
var webRequest = Request(Url, Action, document);
var soapResult = Response(webRequest);
happiness = soapResult.Deserialize(out result);
Query:
internal static string Query(string user, string pass, string date, string regc)
{
var doc = string.Format(#"<?xml version='1.0' encoding='UTF-8'?>
<s:Envelope xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'>
<s:Body xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
<PersonnelInfo xmlns='http://propartner.ee/'>
<PersonnelInfoRequest xmlns=''>
<username>{0}</username>
<password>{1}</password>
<reg_code>{2}</reg_code>
<date>{3}</date>
<country>est</country>
<language>est</language>
</PersonnelInfoRequest>
</PersonnelInfo>
</s:Body>
</s:Envelope>", user, pass, regc, date);
return doc;
}
Request:
internal static HttpWebRequest Request(string url, string action, string doc)
{
var soapEnvelop = new XmlDocument();
soapEnvelop.LoadXml(doc);
var webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Headers.Add("SOAPAction", action);
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
webRequest.Host = "wsrvc1.propartner.ee";
using (var stream = webRequest.GetRequestStream())
{
soapEnvelop.Save(stream);
}
return webRequest;
}
Response:
internal static string Response(HttpWebRequest webRequest)
{
var asyncResult = webRequest.BeginGetResponse(null, null);
asyncResult.AsyncWaitHandle.WaitOne();
using (var webResponse = webRequest.EndGetResponse(asyncResult))
{
var responsesteam = webResponse.GetResponseStream();
if (responsesteam == null) return default(string);
using (var rd = new StreamReader(responsesteam))
{
var soapResult = rd.ReadToEnd();
return soapResult;
}
}
}

Sending HTTP POST Request with XML to a web service and reading response data in C# for windows 8 phone

I a newbie at windows 8 phone development. I want to send an aync HTTP POST Request to a PHP web service with some headers and XML in the request body.
Also, I want to read the response sent back by the PHP web service.
Please guide me, how can I achieve the above two stated things.
what I have tried until now i am giving below
// Main begins program execution.
public static void SendRequest()
{
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.CreateHttp("http://mytestserver.com/Test.php");
webRequest.Method = "POST";
webRequest.ContentType = "text/xml";
webRequest.Headers["SOURCE"] = "WinApp";
var response = await httpRequest(webRequest);
}
public static async Task<string> httpRequest(HttpWebRequest request)
{
string received;
using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
{
using (var responseStream = response.GetResponseStream())
{
using (var sr = new StreamReader(responseStream))
{
received = await sr.ReadToEndAsync();
MessageBox.Show(received.ToString());
}
}
}
return received;
}
I am able to send the request using the above code. I just need to know that how I can send the XML in the request body to my web service.
For Set a file, and receive a server Response, I use that for sending .csv files:
First I initialize a POST Request:
/// <summary>
/// Initialize the POST HTTP request.
/// </summary>
public void SentPostReport()
{
string url = "http://MyUrlPerso.com/";
Uri uri = new Uri(url);
// Create a boundary for HTTP request.
Boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.ContentType = "multipart/form-data; boundary=" + Boundary;
request.Method = "POST";
request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), est);
allDone.WaitOne();
}
After initialized Request, I send the differents parts of my files (headers + content + footer).
/// <summary>
/// Send a File with initialized request.
/// </summary>
private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
string contentType = "binary";
string myFileContent = "one;two;three;four;five;"; // CSV content.
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
Stream memStream = request.EndGetRequestStream(asynchronousResult);
byte[] boundarybytes = System.Text.Encoding.UTF8.GetBytes("\r\n--" + Boundary + "\r\n");
memStream.Write(boundarybytes, 0, boundarybytes.Length);
// Send headers.
string headerTemplate = "Content-Disposition: form-data; ";
headerTemplate += "name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: " + contentType + "\r\n\r\n";
string fileName = "MyFileName.csv";
string header = string.Format(headerTemplate, "file", fileName);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
memStream.Write(headerbytes, 0, headerbytes.Length);
byte[] contentbytes = System.Text.Encoding.UTF8.GetBytes(myFileContent);
// send the content of the file.
memStream.Write(contentbytes, 0, contentbytes.Length);
// Send last boudary of the file ( the footer) for specify post request is finish.
byte[] boundarybytesend = System.Text.Encoding.UTF8.GetBytes("\r\n--" + Boundary + "--\r\n");
memStream.Write(boundarybytesend, 0, boundarybytesend.Length);
memStream.Flush();
memStream.Close();
allDone.Set();
// Start the asynchronous operation to get the response
request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}
And, Finnaly, I get The response server response, indicate the file is transmetted.
/// <summary>
/// Get the Response server.
/// </summary>
private static void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
try
{
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadToEnd(); // this is a response server.
// Close the stream object
streamResponse.Close();
streamRead.Close();
// Release the HttpWebResponse
response.Close();
}
catch (Exception ex)
{
// error.
}
}
This sample works on Windows Phone 7 and Windows Phone 8.
This is for send a .csv content. You can adapt this code for send Xml content.
Replace just
string myFileContent = "one;two;three;four;five;"; // CSV content.
string fileName = "MyFileName.csv";
by your XML
string myFileContent = "<xml><xmlnode></xmlnode></xml>"; // XML content.
string fileName = "MyFileName.xml";
If all you're looking to do is take XML you've already generated and add it to your existing request as content, you'll need to be able to write to the request stream. I don't particularly care for the stock model of getting the request stream, so I'd recommend the following extension to make your life a little easier:
public static class Extensions
{
public static System.Threading.Tasks.Task<System.IO.Stream> GetRequestStreamAsync(this System.Net.HttpWebRequest wr)
{
if (wr.ContentLength < 0)
{
throw new InvalidOperationException("The ContentLength property of the HttpWebRequest must first be set to the length of the content to be written to the stream.");
}
var tcs = new System.Threading.Tasks.TaskCompletionSource<System.IO.Stream>();
wr.BeginGetRequestStream((result) =>
{
var source = (System.Net.HttpWebRequest)result.AsyncState;
tcs.TrySetResult(source.EndGetRequestStream(result));
}, wr);
return tcs.Task;
}
}
From here, augment your SendRequest method:
public static void SendRequest(string myXml)
{
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.CreateHttp("http://mytestserver.com/Test.php");
webRequest.Method = "POST";
webRequest.Headers["SOURCE"] = "WinApp";
// Might not hurt to specify encoding here
webRequest.ContentType = "text/xml; charset=utf-8";
// ContentLength must be set before a stream may be acquired
byte[] content = System.Text.Encoding.UTF8.GetBytes(myXml);
webRequest.ContentLength = content.Length;
var reqStream = await webRequest.GetRequestStreamAsync();
reqStream.Write(content, 0, content.Length);
var response = await httpRequest(webRequest);
}
If the service you're trying to reach is a SOAP service, you could simplify this a bit more by having the IDE generate a client class for you. For more information on how to do that, check out this MSDN article. However, if the service does not have a Web Service Definition Language (WSDL) document, this approach will not be able to assist you.
You can use the HTTP Client libraries in Windows Phone 8 and use the client in the same way that Windows 8.
First, get the HTTP Client Libraries from Nuget.
And now, to perform a POST call
HttpClient client = new HttpClient();
HttpContent httpContent = new StringContent("my content: xml, json or whatever");
httpContent.Headers.Add("name", "value");
HttpResponseMessage response = await client.PostAsync("uri", httpContent);
if (response.IsSuccessStatusCode)
{
// DO SOMETHING
}
i hope this helps you :)
I have solved the problem in some other way..
class HTTPReqRes
{
private static HttpWebRequest webRequest;
public static void SendRequest()
{
webRequest = (HttpWebRequest)HttpWebRequest.CreateHttp("https://www.mydomain.com");
webRequest.Method = "PUT";
webRequest.ContentType = "text/xml; charset=utf-8";
webRequest.Headers["Header1"] = "Header1Value";
String myXml = "<Roottag><info>test</info></Roottag>";
// Convert the string into a byte array.
byte[] byteArray = Encoding.UTF8.GetBytes(myXml);
webRequest.ContentLength = byteArray.Length;
// start the asynchronous operation
webRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), webRequest);
//webRequest.BeginGetResponse(new AsyncCallback(GetResponseCallback), webRequest);
}
private static void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
Stream postStream = request.EndGetRequestStream(asynchronousResult);
String myXml = <Roottag><info>test</info></Roottag>";
// Convert the string into a byte array.
byte[] byteArray = Encoding.UTF8.GetBytes(myXml);
// Write to the request stream.
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
// Start the asynchronous operation to get the response
request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}
private static void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadToEnd();
System.Diagnostics.Debug.WriteLine(responseString);
// Close the stream object
streamResponse.Close();
streamRead.Close();
// Release the HttpWebResponse
response.Close();
}
}
This perfectly solves my problem, send an XML within the HTTP Request and in Response receive the XML from the web service.
I recommend using the RestSharp library. You can find a sample request here.
This is what I used. It's really simple, add WindowsPhonePostClient.dll to your References (if you can't, try unblock the file first by properties->unblock), then use this code:
private void Post(string YourUsername, string Password)
{
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("User", YourUsername);
parameters.Add("Password", Password);
PostClient proxy = new PostClient(parameters);
proxy.DownloadStringCompleted += proxy_UploadDownloadStringCompleted;
proxy.DownloadStringAsync(new Uri("http://mytestserver.com/Test.php",UriKind.Absolute));
}
private void proxy_UploadDownloadStringCompleted(object sender,WindowsPhonePostClient.DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
MessageBox.Show(e.Result.ToString());
}
You need to create a reference to the webservice wsdl or you could try to do it manually as detailed here:
https://stackoverflow.com/a/1609427/2638872
//The below code worked for me. I receive xml response back.
private void SendDataUsingHttps()
{
WebRequest req = null;
WebResponse rsp = null;
string fileName = #"C:\Test\WPC\InvoiceXMLs\123File.xml"; string uri = "https://service.XYZ.com/service/transaction/cxml.asp";
try
{
if ((!string.IsNullOrEmpty(uri)) && (!string.IsNullOrEmpty(fileName)))
{
req = WebRequest.Create(uri);
//req.Proxy = WebProxy.GetDefaultProxy(); // Enable if using proxy
req.Method = "POST"; // Post method
req.ContentType = "text/xml"; // content type
// Wrap the request stream with a text-based writer
StreamWriter writer = new StreamWriter(req.GetRequestStream());
// Write the XML text into the stream
StreamReader reader = new StreamReader(file);
string ret = reader.ReadToEnd();
reader.Close();
writer.WriteLine(ret);
writer.Close();
// Send the data to the webserver
rsp = req.GetResponse();
HttpWebResponse hwrsp = (HttpWebResponse)rsp;
Stream streamResponse = hwrsp.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadToEnd();
rsp.Close();
}
}
catch (WebException webEx) { }
catch (Exception ex) { }
finally
{
if (req != null) req.GetRequestStream().Close();
if (rsp != null) rsp.GetResponseStream().Close();
}
}

Client to send SOAP request and receive response

Trying to create a C# client (will be developed as a Windows service) that sends SOAP requests to a web service (and gets the results).
From this question I saw this code:
protected virtual WebRequest CreateRequest(ISoapMessage soapMessage)
{
var wr = WebRequest.Create(soapMessage.Uri);
wr.ContentType = "text/xml;charset=utf-8";
wr.ContentLength = soapMessage.ContentXml.Length;
wr.Headers.Add("SOAPAction", soapMessage.SoapAction);
wr.Credentials = soapMessage.Credentials;
wr.Method = "POST";
wr.GetRequestStream().Write(Encoding.UTF8.GetBytes(soapMessage.ContentXml), 0, soapMessage.ContentXml.Length);
return wr;
}
public interface ISoapMessage
{
string Uri { get; }
string ContentXml { get; }
string SoapAction { get; }
ICredentials Credentials { get; }
}
Looks nice, anyone knows how to use it and if it is the best practice?
I normally use another way to do the same
using System.Xml;
using System.Net;
using System.IO;
public static void CallWebService()
{
var _url = "http://xxxxxxxxx/Service1.asmx";
var _action = "http://xxxxxxxx/Service1.asmx?op=HelloWorld";
XmlDocument soapEnvelopeXml = CreateSoapEnvelope();
HttpWebRequest webRequest = CreateWebRequest(_url, _action);
InsertSoapEnvelopeIntoWebRequest(soapEnvelopeXml, webRequest);
// begin async call to web request.
IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);
// suspend this thread until call is complete. You might want to
// do something usefull here like update your UI.
asyncResult.AsyncWaitHandle.WaitOne();
// get the response from the completed web request.
string soapResult;
using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult))
{
using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))
{
soapResult = rd.ReadToEnd();
}
Console.Write(soapResult);
}
}
private static HttpWebRequest CreateWebRequest(string url, string action)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Headers.Add("SOAPAction", action);
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
return webRequest;
}
private static XmlDocument CreateSoapEnvelope()
{
XmlDocument soapEnvelopeDocument = new XmlDocument();
soapEnvelopeDocument.LoadXml(
#"<SOAP-ENV:Envelope xmlns:SOAP-ENV=""http://schemas.xmlsoap.org/soap/envelope/""
xmlns:xsi=""http://www.w3.org/1999/XMLSchema-instance""
xmlns:xsd=""http://www.w3.org/1999/XMLSchema"">
<SOAP-ENV:Body>
<HelloWorld xmlns=""http://tempuri.org/""
SOAP-ENV:encodingStyle=""http://schemas.xmlsoap.org/soap/encoding/"">
<int1 xsi:type=""xsd:integer"">12</int1>
<int2 xsi:type=""xsd:integer"">32</int2>
</HelloWorld>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>");
return soapEnvelopeDocument;
}
private static void InsertSoapEnvelopeIntoWebRequest(XmlDocument soapEnvelopeXml, HttpWebRequest webRequest)
{
using (Stream stream = webRequest.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
}
I got this simple solution here:
Sending SOAP request and receiving response in .NET 4.0 C# without using the WSDL or proxy classes:
class Program
{
/// <summary>
/// Execute a Soap WebService call
/// </summary>
public static void Execute()
{
HttpWebRequest request = CreateWebRequest();
XmlDocument soapEnvelopeXml = new XmlDocument();
soapEnvelopeXml.LoadXml(#"<?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>
<HelloWorld xmlns=""http://tempuri.org/"" />
</soap:Body>
</soap:Envelope>");
using (Stream stream = request.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
using (WebResponse response = request.GetResponse())
{
using (StreamReader rd = new StreamReader(response.GetResponseStream()))
{
string soapResult = rd.ReadToEnd();
Console.WriteLine(soapResult);
}
}
}
/// <summary>
/// Create a soap webrequest to [Url]
/// </summary>
/// <returns></returns>
public static HttpWebRequest CreateWebRequest()
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(#"http://localhost:56405/WebService1.asmx?op=HelloWorld");
webRequest.Headers.Add(#"SOAP:Action");
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
return webRequest;
}
static void Main(string[] args)
{
Execute();
}
}
I think there is a simpler way:
public async Task<string> CreateSoapEnvelope()
{
string soapString = #"<?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>
<HelloWorld xmlns=""http://tempuri.org/"" />
</soap:Body>
</soap:Envelope>";
HttpResponseMessage response = await PostXmlRequest("your_url_here", soapString);
string content = await response.Content.ReadAsStringAsync();
return content;
}
public static async Task<HttpResponseMessage> PostXmlRequest(string baseUrl, string xmlString)
{
using (var httpClient = new HttpClient())
{
var httpContent = new StringContent(xmlString, Encoding.UTF8, "text/xml");
httpContent.Headers.Add("SOAPAction", "http://tempuri.org/HelloWorld");
return await httpClient.PostAsync(baseUrl, httpContent);
}
}
The best practice is to reference the WSDL and use it like a web service reference.
It's easier and works better, but if you don't have the WSDL, the XSD definitions are a good piece of code.
I wrote a more general helper class which accepts a string-based dictionary of custom parameters, so that they can be set by the caller without having to hard-code them. It goes without saying that you should only use such method when you want (or need) to manually issue a SOAP-based web service: in most common scenarios the recommended approach would be using the Web Service WSDL together with the Add Service Reference Visual Studio feature instead.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Xml;
namespace Ryadel.Web.SOAP
{
/// <summary>
/// Helper class to send custom SOAP requests.
/// </summary>
public static class SOAPHelper
{
/// <summary>
/// Sends a custom sync SOAP request to given URL and receive a request
/// </summary>
/// <param name="url">The WebService endpoint URL</param>
/// <param name="action">The WebService action name</param>
/// <param name="parameters">A dictionary containing the parameters in a key-value fashion</param>
/// <param name="soapAction">The SOAPAction value, as specified in the Web Service's WSDL (or NULL to use the url parameter)</param>
/// <param name="useSOAP12">Set this to TRUE to use the SOAP v1.2 protocol, FALSE to use the SOAP v1.1 (default)</param>
/// <returns>A string containing the raw Web Service response</returns>
public static string SendSOAPRequest(string url, string action, Dictionary<string, string> parameters, string soapAction = null, bool useSOAP12 = false)
{
// Create the SOAP envelope
XmlDocument soapEnvelopeXml = new XmlDocument();
var xmlStr = (useSOAP12)
? #"<?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>
<{0} xmlns=""{1}"">{2}</{0}>
</soap12:Body>
</soap12:Envelope>"
: #"<?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>
<{0} xmlns=""{1}"">{2}</{0}>
</soap:Body>
</soap:Envelope>";
string parms = string.Join(string.Empty, parameters.Select(kv => String.Format("<{0}>{1}</{0}>", kv.Key, kv.Value)).ToArray());
var s = String.Format(xmlStr, action, new Uri(url).GetLeftPart(UriPartial.Authority) + "/", parms);
soapEnvelopeXml.LoadXml(s);
// Create the web request
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Headers.Add("SOAPAction", soapAction ?? url);
webRequest.ContentType = (useSOAP12) ? "application/soap+xml;charset=\"utf-8\"" : "text/xml;charset=\"utf-8\"";
webRequest.Accept = (useSOAP12) ? "application/soap+xml" : "text/xml";
webRequest.Method = "POST";
// Insert SOAP envelope
using (Stream stream = webRequest.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
// Send request and retrieve result
string result;
using (WebResponse response = webRequest.GetResponse())
{
using (StreamReader rd = new StreamReader(response.GetResponseStream()))
{
result = rd.ReadToEnd();
}
}
return result;
}
}
}
For additional info & details regarding this class you can also read this post on my blog.
So this is my final code after googling for 2 days on how to add a namespace and make soap request along with the SOAP envelope without adding proxy/Service Reference
class Request
{
public static void Execute(string XML)
{
try
{
HttpWebRequest request = CreateWebRequest();
XmlDocument soapEnvelopeXml = new XmlDocument();
soapEnvelopeXml.LoadXml(AppendEnvelope(AddNamespace(XML)));
using (Stream stream = request.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
using (WebResponse response = request.GetResponse())
{
using (StreamReader rd = new StreamReader(response.GetResponseStream()))
{
string soapResult = rd.ReadToEnd();
Console.WriteLine(soapResult);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
private static HttpWebRequest CreateWebRequest()
{
string ICMURL = System.Configuration.ConfigurationManager.AppSettings.Get("ICMUrl");
HttpWebRequest webRequest = null;
try
{
webRequest = (HttpWebRequest)WebRequest.Create(ICMURL);
webRequest.Headers.Add(#"SOAP:Action");
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return webRequest;
}
private static string AddNamespace(string XML)
{
string result = string.Empty;
try
{
XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(XML);
XmlElement temproot = xdoc.CreateElement("ws", "Request", "http://example.com/");
temproot.InnerXml = xdoc.DocumentElement.InnerXml;
result = temproot.OuterXml;
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return result;
}
private static string AppendEnvelope(string data)
{
string head= #"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" ><soapenv:Header/><soapenv:Body>";
string end = #"</soapenv:Body></soapenv:Envelope>";
return head + data + end;
}
}
As an alternative, and pretty close to debiasej approach. Since a SOAP request is just a HTTP request, you can simply perform a GET or POST using with HTTP client, but it's not mandatory to build SOAP envelope.
Something like this:
using Microsoft.Extensions.Logging;
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace HGF.Infraestructure.Communications
{
public class SOAPSample
{
private readonly IHttpClientFactory _clientFactory;
private readonly ILogger<DocumentProvider> _logger;
public SOAPSample(ILogger<DocumentProvider> logger,
IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
_logger = logger;
}
public async Task<string> UsingGet(int value1, int value2)
{
try
{
var client = _clientFactory.CreateClient();
var response = await client.GetAsync($"https://hostname.com/webservice.asmx/SampleMethod?value1={value1}&value2={value2}", HttpCompletionOption.ResponseHeadersRead);
//NULL check, HTTP Status Check....
return await response.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Oops! Something went wrong");
return ex.Message;
}
}
public async Task<string> UsingPost(int value1, int value2)
{
try
{
var content = new StringContent($"value1={value1}&value2={value2}", Encoding.UTF8, "application/x-www-form-urlencoded");
var client = _clientFactory.CreateClient();
var response = await client.PostAsync("https://hostname.com/webservice.asmx/SampleMethod", content);
//NULL check, HTTP Status Check....
return await response.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Oops! Something went wrong");
return ex.Message;
}
}
}
}
Of course, it depends on your scenario. If the payload is too complex, then this won't work
Call SOAP webservice in c#
using (var client = new UpdatedOutlookServiceReferenceAPI.OutlookServiceSoapClient("OutlookServiceSoap"))
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12;
var result = client.UploadAttachmentBase64(GUID, FinalFileName, fileURL);
if (result == true)
{
resultFlag = true;
}
else
{
resultFlag = false;
}
LogWriter.LogWrite1("resultFlag : " + resultFlag);
}

Categories