How to Make a Soap/Wsdl Client in C#

How to make a SOAP/WSDL client in C#?

The simplest way is to use VS and add a web reference. This automatically creates the stub for you

Create SOAP webservice(wsdl) client in c#

Having Drew's method in mind,

  1. Right click on the project and select "add a service reference' and click "Advanced.." in add service reference dialog box. Then click "Add web reference" in add service reference dialog box. Input your webservice address in the address bar and click go. then rename your web reference name and click add reference.

(for ws security)
2.Go to the Reference.cs and change System.Web.Services.Protocols.SoapHttpClientProtocol to Microsoft.Web.Services2.WebServicesClientProtocol (You might have to add service2 by nuget)


  1. Before calling your webservice, add this.

UsernameToken token = new UsernameToken("", "", PasswordOption.SendPlainText);
yourProxy.RequestSoapContext.Security.Tokens.Add(token);

How to create SOAP/XML client from WSDL in console cron job app C# vs2012

You are not alone in being confused. You have to realize classic SOAP (asmx/wsdl) is considered an "outdated" technology (by Microsoft), so these days it hidden away in the toolset in favor of newer technologies. The most basic approach is to add it as a Reference from the solution explorer within Visual Studio itself. Here is a step-by-step:

  1. Create a console application
  2. In the solution explorer, right-click the References node and choose Add Service ReferenceAdd Service Reference from within Visual Studio
  3. Ignore most of the dialog that comes up, and go straight for Advanced: enter image description here
  4. From the bottom of the Service Reference Setttings, choose Add Web Reference... Add Web Reference
  5. Now fill in the location of your ASMX, hit the little arrow, wait a bit for the tooling to discover the service, then hit Add Reference
    Add Web Reference - web service details
  6. This will add a Web Reference to your project that you can then use to access the methods of the webservice.Web reference within project

[Edit] (to answer your question)

If you have a .WSDL file on disk, you simply enter the file location on disk in the URL box of the Add Web Reference dialog:WSDL on Disk

In that case, the generated service has a default namespace of WebReference (unless you change it, of course), and you'll most likely want to explicitly set the URL:

var service = new WebReference.GlobalWeather {Url = "http://www.webservicex.net/globalweather.asmx"};
var weather = service.GetWeather("Amsterdam", "Netherlands");
Console.WriteLine(weather);

SOAP Client using C#

You can use a couple different system libraries to create an HttpWebRequest, create custom xml, and insert that xml into your request before you send it. (system.net, system.xml.linq, system.io)

I was able to hit your web service but got a 500 error. (Hopefully you see a log or that wasn't yours!)

Here's a simple class that can call a SOAP web service. It's almost the xml that you need but might need some tweaking. If you're having issues making custom xml this may be a possible solution.

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Xml.Linq;

namespace ConsoleApp1
{
/// <summary>
/// Random class
/// </summary>
class Class1
{
/// <summary>
/// Function that calls a SOAP web service
/// </summary>
public void CallSOAP()
{
try
{
// Construct http post request
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri("https://test-submit.health263.systems:8081/apacewebservices/AMF1_0"));
request.Method = "POST";
request.ContentType = "application/xml";
request.Accept = "application/xml";

// Setting a namespace for your xml
// I'm not sure the timezone one is set up properly
XNamespace soap = "urn:apace:member:format:1.0";
XNamespace timezone = "TimeZone=\"Africa/Johannesburg\"";

// This constructs your xml using the LINQ library. I modeled after your demo, but needs tweaking as I get 500 error from server.
XElement requestXML =
new XElement(soap + "Member",
new XElement("Request",
new XElement("Transaction",
new XElement("VersionNumber", "1.0"),
new XElement("Number", "434252 - 342234 - 6765"),
new XElement("SystemIdentifier", "SYSTEM999"),
new XElement("DestinationCode", "APACE"),
new XElement("ClientCountryCode", "ZA"),
new XElement(timezone + "Timestamp", "20160601123456"),
new XElement("TestIndicator", "Y"),
new XElement("User", "ProviderX/Jane Doe")
),
new XElement("MembershipLookup",
new XElement("Funder", "AFunder"),
new XElement("WithMembershipNumber",
new XElement("MembershipNumber", 123456789)
)
)
)
);

// Convert the xml into a stream that we write to our request
byte[] bytes = Encoding.UTF8.GetBytes(requestXML.ToString());
request.ContentLength = bytes.Length;
using (Stream putStream = request.GetRequestStream())
{
putStream.Write(bytes, 0, bytes.Length);
}

// Execute the request and get an xml response "reader". You can read all xml at once or line by line
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{

var streamData = reader.ReadToEnd();

}
}
catch (Exception ex)
{
// Write exception to console & wait for key press
Console.WriteLine(ex.Message + ex.StackTrace);
Console.ReadKey();
}
}
}
}

Client to send SOAP request and receive response

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);
}
}

SOAP client in .NET referencing existing WSDL

I found the solution to this problem by myself. After lots of trial and error modifications I came to the conclusion that the word "parameters" is not very welcome into .NET environment. So I changed it with "params" and now it is correctly imported by wsdl.exe

So part of my previous WSDL was something like:

<wsdl:message name="isServiceOnline">
<wsdl:part name="parameters" element="MyElement"></wsdl:part>
</wsdl:message>

The new version of it is:

<wsdl:message name="isServiceOnline">
<wsdl:part name="params" element="MyElement"></wsdl:part>
</wsdl:message>

SOAP service client generated with WSDL configure signing body only

I have finally managed to solve this myself. I had binding security configured in my app.config but this appears to default to symmetric security, hence the HMAC-SHA1 which uses AES, a symmetric algorithm. Instead of configuring in app.config, I built my own binding using AsymmetricSecurity (shown below). This meant that signatures used RSA, an asymmetric algorithm, instead of AES, and upon doing this the remote server finally accepted the request.

AsymmetricSecurityBindingElement asbe = new AsymmetricSecurityBindingElement
{
MessageSecurityVersion = MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10, // Or WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10 ?
InitiatorTokenParameters = new X509SecurityTokenParameters { InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient },
RecipientTokenParameters = new X509SecurityTokenParameters(),
SecurityHeaderLayout = SecurityHeaderLayout.Strict,
IncludeTimestamp = true,
DefaultAlgorithmSuite = SecurityAlgorithmSuite.Basic128Rsa15,
AllowSerializedSigningTokenOnReply = true
};
asbe.SetKeyDerivation(false); // What is it for?
asbe.EndpointSupportingTokenParameters.Signed.Add(new X509SecurityTokenParameters { InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient });

CustomBinding binding = new CustomBinding();
binding.Elements.Add(asbe);
binding.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8));
binding.Elements.Add(new HttpsTransportBindingElement
{
MaxReceivedMessageSize = 1024 * 1024
});

Client.Endpoint.Binding = binding;


Related Topics



Leave a reply



Submit