I used C# to create a DLL that uses a WebRequest to access a WebService. This DLL is declared as ComVisible, so I can use it with Delphi. If the WebRequest works unencrypted, everything works fine. But when I use https as protocol, I get the following error message:
The underlying connection was closed: An unexpected error occurred on a send.
Unable to read data from the transport connection: Eine vorhandene Verbindung wurde vom Remotehost geschlossen.
But the same DLL works when I use it from a .NET application.
I created a minimal sample project to see if the error is reproducible and I had the same problem.
Here is the code with the webrequest
[Guid("D0AAE68A-D2C0-4015-8DE6-471879267418"), ClassInterface(ClassInterfaceType.AutoDual), ProgId("WebRequestTest")]
[ComVisible(true)]
public class ComClient
{
public bool Authenticate(string customer)
{
var request = WebRequest.Create(@"https://server.azurewebsites.net/api/authenticate?apikey=xxxx&customer=" + customer);
request.Method = "GET";
try
{
using (var response = (HttpWebResponse)request.GetResponse())
{
using (StreamReader streamReader = new StreamReader(response.GetResponseStream()))
{
string responseString = streamReader.ReadToEnd();
Trace.WriteLine(responseString);
return true;
}
}
}
catch (Exception exc)
{
Trace.WriteLine(exc);
return false;
}
}
}
In delphi the code is also small and simple
procedure TForm1.btnTestClick(Sender: TObject);
var
client: TComClient;
begin
client := TComClient.Create(self);
if client.Authenticate('xxxxxxxx') then
Application.MessageBox('Ok', '', MB_OK + MB_ICONINFORMATION)
else
Application.MessageBox('Error', '', MB_OK + MB_ICONINFORMATION);
client.Free;
client := nil;
end;
To test this with pure .NET, I've created a small unit test, which works without error.
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
ComClient client = new ComClient();
bool result = client.Authenticate("xxxxxxxx");
Assert.IsTrue(result);
}
}
It looks to me like the .NET framework isn't completely initialized when using a .NET assembly from a COM application. As already mentioned, the call works fine if I switch to http instead of https.
I found the solution through Tav's comment. While ServicePointManager.SecurityProtocol contains the protocols TLS | TLS11 | TLS12 for .NET applications, only the protocols SSL3 and TLS are assigned as COM application. Since Azure AppServices are configured by default so that the minimum TLS version is 1.2, you must either reconfigure the AppService accordingly or explicitly add TLS1.2 in the COM assembly.
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;