Yes, HttpClient
in C# can absolutely be used to interact with SOAP services. While HttpClient is commonly associated with RESTful APIs, it's perfectly capable of handling SOAP (Simple Object Access Protocol) requests, which are XML-based HTTP POST requests with specific formatting requirements.
How SOAP with HttpClient Works
SOAP services require:
1. XML SOAP envelope with proper namespaces
2. Specific HTTP headers (Content-Type
and SOAPAction
)
3. POST method for sending requests
4. XML response parsing to extract data
Basic SOAP Request Example
Here's a complete example showing how to call a SOAP web service:
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
public class SoapClient
{
private readonly HttpClient _httpClient;
public SoapClient()
{
_httpClient = new HttpClient();
}
public async Task<string> CallSoapServiceAsync()
{
var soapEnvelope = @"<?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>
<GetWeather xmlns=""http://www.webserviceX.NET"">
<CityName>London</CityName>
<CountryName>UK</CountryName>
</GetWeather>
</soap:Body>
</soap:Envelope>";
var url = "http://www.webservicex.net/globalweather.asmx";
var soapAction = "http://www.webserviceX.NET/GetWeather";
var request = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = new StringContent(soapEnvelope, Encoding.UTF8, "text/xml")
};
request.Headers.Add("SOAPAction", soapAction);
var response = await _httpClient.SendAsync(request);
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadAsStringAsync();
}
throw new HttpRequestException($"SOAP request failed: {response.StatusCode}");
}
}
Advanced SOAP Client with XML Processing
For better XML handling and response parsing:
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
public class AdvancedSoapClient : IDisposable
{
private readonly HttpClient _httpClient;
public AdvancedSoapClient()
{
_httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Add("User-Agent", "SOAPClient/1.0");
}
public async Task<XDocument> SendSoapRequestAsync(string endpoint, string soapAction, XDocument soapEnvelope)
{
var request = new HttpRequestMessage(HttpMethod.Post, endpoint)
{
Content = new StringContent(soapEnvelope.ToString(), Encoding.UTF8, "text/xml")
};
// Add required SOAP headers
request.Headers.Add("SOAPAction", $"\"{soapAction}\"");
var response = await _httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
var responseContent = await response.Content.ReadAsStringAsync();
return XDocument.Parse(responseContent);
}
public async Task<string> GetWeatherAsync(string city, string country)
{
var soapEnvelope = XDocument.Parse(@"
<soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
<soap:Body>
<GetWeather xmlns=""http://www.webserviceX.NET"">
<CityName>{0}</CityName>
<CountryName>{1}</CountryName>
</GetWeather>
</soap:Body>
</soap:Envelope>".Replace("{0}", city).Replace("{1}", country));
var response = await SendSoapRequestAsync(
"http://www.webservicex.net/globalweather.asmx",
"http://www.webserviceX.NET/GetWeather",
soapEnvelope);
// Extract data from SOAP response
var weatherData = response
.Descendants(XName.Get("GetWeatherResult", "http://www.webserviceX.NET"))
.FirstOrDefault()?.Value;
return weatherData ?? "No data found";
}
public void Dispose()
{
_httpClient?.Dispose();
}
}
SOAP with Authentication
Many SOAP services require authentication. Here's how to handle it:
public async Task<string> CallAuthenticatedSoapServiceAsync(string username, string password)
{
var soapEnvelope = $@"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
<soap:Header>
<AuthHeader xmlns=""http://tempuri.org/"">
<Username>{username}</Username>
<Password>{password}</Password>
</AuthHeader>
</soap:Header>
<soap:Body>
<MySecureOperation xmlns=""http://tempuri.org/"">
<Parameter>Value</Parameter>
</MySecureOperation>
</soap:Body>
</soap:Envelope>";
var request = new HttpRequestMessage(HttpMethod.Post, "https://secure-soap-service.com/service.asmx")
{
Content = new StringContent(soapEnvelope, Encoding.UTF8, "text/xml")
};
request.Headers.Add("SOAPAction", "http://tempuri.org/MySecureOperation");
// Optional: Add basic authentication
var credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{username}:{password}"));
request.Headers.Add("Authorization", $"Basic {credentials}");
var response = await _httpClient.SendAsync(request);
return await response.Content.ReadAsStringAsync();
}
Error Handling and SOAP Faults
SOAP services return faults for errors. Here's how to handle them:
public async Task<T> HandleSoapResponse<T>(HttpResponseMessage response, Func<XDocument, T> parser)
{
var content = await response.Content.ReadAsStringAsync();
var doc = XDocument.Parse(content);
// Check for SOAP faults
var fault = doc.Descendants(XName.Get("Fault", "http://schemas.xmlsoap.org/soap/envelope/")).FirstOrDefault();
if (fault != null)
{
var faultCode = fault.Element("faultcode")?.Value ?? "Unknown";
var faultString = fault.Element("faultstring")?.Value ?? "SOAP Fault occurred";
throw new SoapException($"SOAP Fault - Code: {faultCode}, Message: {faultString}");
}
return parser(doc);
}
public class SoapException : Exception
{
public SoapException(string message) : base(message) { }
}
When to Use HttpClient vs Alternatives
Use HttpClient for SOAP when: - You need fine-grained control over requests - Working with simple SOAP services - You're already familiar with the SOAP message structure - You want to avoid additional dependencies
Consider alternatives when: - Working with complex SOAP services with many operations - You need automatic proxy generation from WSDL - You require advanced WS-* features (WS-Security, WS-ReliableMessaging)
Modern alternatives: - Connected Services in Visual Studio (generates typed clients) - WCF Core (.NET Core/5+ version of WCF) - System.ServiceModel packages for .NET Core/5+
HttpClient provides excellent flexibility for SOAP integration while maintaining full control over the HTTP communication layer.