33

I'm trying to use the HttpClient class to send a SOAP message:

Doing so with REST seems easy (code from here) :

using System;
using System.Net.Http;
using System.Json;

namespace ConsoleApplication39
{
class Program
{
static void Main(string[] args)
{

HttpClient proxy = new HttpClient();
proxy.GetAsync("http://localhost:14892/api/Bloggers").ContinueWith((r) =>
{
HttpResponseMessage response = r.Result;
response.Content.ReadAsAsync<JsonArray>().ContinueWith(
(a)=>
{
foreach(var w in a.Result)
{
Console.WriteLine(w.ValueOrDefault("Name").ToString());
Console.WriteLine(w.ValueOrDefault("Intrest").ToString());
}
});

});

Console.ReadKey(true);

}

}
}

I would like to do something similar with SOAP.

I have the host (http://opensearch.addi.dk/2.2/) and the SOAP message to POST:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://oss.dbc.dk/ns/opensearch">
  <SOAP-ENV:Body>
    <ns1:searchRequest>
      <ns1:query>dc.title=zorro AND dc.type=bog</ns1:query>
      <ns1:agency>100200</ns1:agency>
      <ns1:profile>test</ns1:profile>
      <ns1:start>1</ns1:start>
      <ns1:stepValue>10</ns1:stepValue>
    </ns1:searchRequest>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

... but how to send it ?

I'll admit that this is the first SOAP Web Service I have ever used so I may have no idea what I'm doing, but in its simplest form could it be something like :

HttpClient hc = new HttpClient();
hc.BaseAddress = new Uri("http://opensearch.addi.dk/2.2/");
    
HttpContent content = *... something*
    
HttpResponseMessage rm = await hc.PostAsync("http://opensearch.addi.dk/2.2/", content);

I assume that the SOAP message should somehow be created through a HttpContent static method like HttpContent.Create(..) but I can't get that to work ...

I know this is a dumb question but I still need help :) !

tia ...

Hakan Fıstık
  • 16,800
  • 14
  • 110
  • 131
user1086115
  • 373
  • 1
  • 5
  • 7
  • This answer might be useful; http://stackoverflow.com/a/4791932/5827 – Chris McAtackney Jan 15 '13 at 11:20
  • That could be useful but I hope to use HttpClient for its greater simplicity and power ... the other code just seems too complicated and specific. I'm hope to use HttpClient for many things (not only SOAP) and would like a more generic solution ! – user1086115 Jan 15 '13 at 11:46

1 Answers1

48

I needed to do this myself and since I couldn't find any answers online, here's what I worked out. This uses a simple SOAP calculator service with an 'Add' method that takes two numbers and returns the sum.

public async Task<int> AddNumbersAsync(Uri uri, int a, int b)
{
    var soapString = this.ConstructSoapRequest(a, b);
    using (var client = new HttpClient())
    {
        client.DefaultRequestHeaders.Add("SOAPAction", "http://CalculatorService/ICalculatorService/Add");
        var content = new StringContent(soapString, Encoding.UTF8, "text/xml");
        using (var response = await client.PostAsync(uri, content))
        {
            var soapResponse = await response.Content.ReadAsStringAsync();
            return this.ParseSoapResponse(soapResponse);
        }
    }
}

private string ConstructSoapRequest(int a, int b)
{
    return String.Format(@"<?xml version=""1.0"" encoding=""utf-8""?>
    <s:Envelope xmlns:s=""http://schemas.xmlsoap.org/soap/envelope/"">
        <s:Body>
            <Add xmlns=""http://CalculatorService/"">
                <a>{0}</a>
                <b>{1}</b>
            </Add>
        </s:Body>
    </s:Envelope>", a, b);
}

private int ParseSoapResponse(string response)
{
    var soap = XDocument.Parse(response);
    XNamespace ns = "http://CalculatorService/";
    var result = soap.Descendants(ns + "AddResponse").First().Element(ns + "AddResult").Value;
    return Int32.Parse(result);
}
Nick Gotch
  • 9,167
  • 14
  • 70
  • 97
  • 9
    Great answer, please note that `HttpClient` is intended to be created once and reused for many requests with the same configuration. So I suggest that you create a static member and reuse it across multiple calls to your sample `AddNumbersAsync` – Alireza Jun 13 '17 at 13:09
  • 1
    @Alireza Valid point. I was only using my code for testing some things so it didn't really matter in my case but for a more formal service that's certainly the right decision. – Nick Gotch Jul 06 '17 at 18:32
  • Very useful answer. Had a struggle to process XML message using PostAsync. You gave me an idea to use direcly SoapString instead. Thanks. – mike Sep 22 '20 at 15:24