DEV Community

Make SOAP requests using IHttpClientFactory in .NET Core

Bojan Nikolić on August 03, 2020

SOAP services became second class citizen in .NET Core. REST was "the-way-to-go" and who creates SOAP services these days anyways? Well, maybe not ...
Collapse
 
nlyk profile image
nlyk

It's really helpful. Unfortunately, I have not been able to add custom HTTP Headers to the request so far. Any suggestions;

Collapse
 
nikolicbojan profile image
Bojan Nikolić

You can add them through additional DelegatingHandler which you would add to the HttpClient setup. So, create something like TraceLogHandler and append a header.
So, something like

internal class HeaderHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        request.Headers.Add("X-MyHeader", "MyValue");

        return base.SendAsync(request, cancellationToken);
    }
}
Enter fullscreen mode Exit fullscreen mode

Then in Startup.cs first register it

services.AddScoped<HeaderHandler>();
Enter fullscreen mode Exit fullscreen mode

and then add it to the HttpClient setup e.g. before AddHeaderPropagation line

.AddHttpMessageHandler<HeaderHandler>()
Enter fullscreen mode Exit fullscreen mode

Let me know if this is not what you had in mind or it doesn't work for your case.

Collapse
 
tho_shiteng_a8027f739194 profile image
Tho Shi Teng

Does this design able to cater for soap calls that require basic authentication ? i try to modify an existing soap client to enable http client factory, it always hit error :

The HTTP request is unauthorized with client authentication scheme 'Basic'.

Collapse
 
nikolicbojan profile image
Bojan Nikolić

Hi Tho,
Have you checked Caveat #2 or comment with suggestion for adding HttpHandler with Header for, in your case, basic authentication?
Basic authentication is just a Authorization header with Basic, then space, then Base64 of user:pass.

Collapse
 
datacruze profile image
datacruze

Hi Bojan, nice article. How would I add an X509 certificate to use the soap service with this approach? I currently use the WCF bindings to add the X509 certificate

Collapse
 
nikolicbojan profile image
Bojan Nikolić

Hi, I would suggest that you setup certificate in a constructor of a service, similarly how I setup timeouts here github.com/nikolic-bojan/soap-clie...
Maybe this example could help docs.microsoft.com/en-us/dotnet/fr...

Collapse
 
datacruze profile image
datacruze

Thanks, I added the cert but I still see TIME_WAIT when running netstat. Do you think I did not implement httpmessagehandler correctly? I documented my issue at the link below. Please let me know any suggestions
github.com/dotnet/wcf/issues/4838

Thread Thread
 
nikolicbojan profile image
Bojan Nikolić

Hi @datacruze
I would like to understand this better (checked Issue on GH) - you managed to add certificate and to call WCF service; you also conducted load tests and that was also a success; you load tested with 20 threads in parallel.
HttpMessageHandler has a default 2 minute lifetime, so all your connections should be closed after that period of time.
I checked your code on GH Issue and what I can see is that it is quite different then mine where I inject IHttpMessageHandlerFactory. I am also Closing the channel after success and Aborting on any issue or if it is not a success.
Were all of your calls a success? Could you try to close the Channel each time?

Thread Thread
 
ctechid profile image
Ey

Try to call channel.Abort(), then channel.Close(), channel.Dispose(), channel = null.

Collapse
 
vekzdran profile image
Vedran Mandić

Bojan, thank you so much... this works like a charm! Excellent find and effort! :-)

Collapse
 
nikolicbojan profile image
Bojan Nikolić

No problem, really glad to hear this post helped! :)