I have created a Windows service using the Worker template and everything works fine, until I try to send a request with HttpClient.Send(). Once I mark this out, everything works again.
It works when I start this in Visual Studio and debug it there, but if I publish it and register it as a Windows service, it fails with this exception:
Category: CorewsWorkerService.WindowsBackgroundService EventId: 0
A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. (SECRET:443)
Exception: System.Net.Http.HttpRequestException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. (SECRET:443) ---> System.Net.Sockets.SocketException (10060): A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken) at ......
I don't know why it works when run manually and the connected party doesn't "properly respond after a period of time" when run in Windows services.
I have removed secrets and attached the code that is called from the WindowsBackgroundService class.
public class TotalArchiveService
{
public string CallService()
{
//SendRequest().GetAwaiter().GetResult();
SendRequest();
return "OK - " + DateTime.Now.ToString();
}
//static async Task SendRequest()
private void SendRequest()
{
try
{
using (var client = new HttpClient {})
{
var endpointUrlCustomer = "https://SECRET";
// Create HTTP request.
var customerBuilder = new UriBuilder(new Uri($"{endpointUrlCustomer}"));
var customerRequest = new HttpRequestMessage(HttpMethod.Post, customerBuilder.Uri);
// set SOAP action
customerRequest.Headers.Add("SOAPAction", "");
// set SOAP body content
string xmlSOAP = GetXmlSOAP();
customerRequest.Content = new StringContent(xmlSOAP, Encoding.UTF8, "text/xml");
// Add signature headers to request object
SignHttpRequestMessage(customerRequest);
// Perform request
var customerResponse = client.Send(customerRequest);
}
}
catch (HttpRequestException e)
{
throw e;
}
}
//static async Task SignHttpRequestMessage(HttpRequestMessage request)
private void SignHttpRequestMessage(HttpRequestMessage request)
{
// externalize configuration of these
string certPath = "";
string keyStorePassword = "";
string keyId = "";
certPath = Path.GetFullPath(@"c:\cert2\cert.pfx"); // path to keystorefile
keyStorePassword = "SECRET";
keyId = "SECRET";
X509Certificate2Collection certs = new X509Certificate2Collection();
X509Certificate2 cert = new X509Certificate2(certPath, keyStorePassword, X509KeyStorageFlags.DefaultKeySet | X509KeyStorageFlags.Exportable);
var services = new ServiceCollection()
.AddHttpMessageSigning()
.UseKeyId(keyId)
.UseSignatureAlgorithm(SignatureAlgorithm.CreateForSigning(cert, HashAlgorithmName.SHA256))
.UseDigestAlgorithm(HashAlgorithmName.SHA256)
.UseUseDeprecatedAlgorithmParameter()
.UseNonce(false)
.UseHeaders()
.Services;
using (var serviceProvider = services.BuildServiceProvider())
{
using (var signerFactory = serviceProvider.GetRequiredService<IRequestSignerFactory>())
{
var requestSigner = signerFactory.CreateFor(keyId);
//await requestSigner.Sign(request);
requestSigner.Sign(request);
}
}
request.Headers.Add("Signature", request.Headers.Authorization.ToString());
request.Headers.Authorization = null;
}
static string GetXmlSOAP()
{
string xmlSOAP = "";
xmlSOAP = @"<?xml version=""1.0"" encoding=""utf-8""?>
<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/""
xmlns:wsc=""http://edb.com/ws/WSCommon_v22""
xmlns:urn=""urn:srv.cus.corews.enterprise.fs.evry.com:ws:customer:v20_1""
xmlns:urn1=""urn:srv.cus.corews.enterprise.fs.evry.com:domain:customer:v20_1""
xmlns:urn2=""urn:corews.enterprise.fs.evry.com:domain:common:v8"">
<soapenv:Header>
<wsc:AutHeader>
<wsc:SourceApplication>SECRET</wsc:SourceApplication>
<wsc:DestinationApplication>SECRET</wsc:DestinationApplication>
<wsc:Function>SECRET</wsc:Function>
<wsc:Version>20_1</wsc:Version>
<wsc:ClientContext>
<wsc:userid>SECRET</wsc:userid>
<wsc:credentials/>
<wsc:channel>BRA</wsc:channel>
<wsc:orgid>9057</wsc:orgid>
<!--Optional:-->
<wsc:orgunit>36000</wsc:orgunit>
<!--Optional:-->
<wsc:customerid>SECRET</wsc:customerid>
<!--Optional:-->
<wsc:locale>no_NO</wsc:locale>
<wsc:ip>127.0.0.1</wsc:ip>
</wsc:ClientContext>
</wsc:AutHeader>
</soapenv:Header>
<soapenv:Body>
<urn:customerReadRequest>
<urn:readQualification>
<urn1:internationalCustomerKey>
<urn2:internationalCustomerNumber>SECRET</urn2:internationalCustomerNumber>
</urn1:internationalCustomerKey>
</urn:readQualification>
</urn:customerReadRequest>
</soapenv:Body>
</soapenv:Envelope>";
return xmlSOAP;
}
}
I have also tried async method, that's why there's marked out lines with async methods, "endRequest().GetAwaiter().GetResult();", "await requestSigner.Sign(request)" etc.
Why can't I call the web service after I register the app as a Windows service, when I active this line?
var customerResponse = client.Send(customerRequest);
When I start it in Visual Studio (result being a cmd prompt with the execution details), the request and response are captured by Fiddler as you would expect. When registering it as a service and starting that, even the request isn't captured in Fiddler. After a while, the above exception is present in the Event Viewer.