Got this error today when connecting to Dynamics 365 using the XRM Tooling CrmServiceClient class. This solution to be fair was expecting to connect to a 2016 online instance so I knew it would need changes. I was trying to connect in debug mode using Visual Studio 2015 on an old Virtual Machine.

I added a watch to the Connection object and viewed the LastCRMErrorProperty and exception detail showed:

“Unable to connect to CRM: The underlying connection was closed: An unexpected error occurred on a send.\r\nMetadata contains a reference that cannot be resolved: ‘′. => The underlying connection was closed: An unexpected error occurred on a send. => Authentication failed because the remote party has closed the transport stream.Unable to Login to Dynamics CRM\r\nUnable to Login to Dynamics CRMOrganizationWebProxyClient is null\r\nOrganizationWebProxyClient is nullOrganizationWebProxyClient is null\r\nOrganizationWebProxyClient is null”

I already knew that the .NET framework had to be changed to 4.6.2 as we are targeting Dynamics 365 from the client application (which would also meet the TLS 1.2 requirement). You can read more about that is very important here and this other link was useful too.

I downloaded the latest nuget package for Dynamics 365 assemblies too as the code was last running 2016 versions. None of these logical considerations were directly relevant to my problem.

None of these things fixed the problem

As noted in the Microsoft link above this issue can occur if using Visual Studio 2015 and trying to connect to D365 in debug mode which was exactly what I was doing here and an extract is below from the Microsoft support page:

Microsoft Dynamics 365 Customer Engagement (online) to require TLS 1.2 for connectivity

Known Issue with Visual Studio 2015

When you are running your project/solution in VS 2015 in debug mode, there is a known issue where you may not be able to connect to Dynamics 365 (online) version 9.x or Dynamics 365 (online) version 8.2 Government. This happens regardless of whether you are using a Target Framework of 4.6.2 or higher. This can occur because the Visual Studio hosting process is compiled against .NET 4.5 which means by default it does not support TLS 1.2. You can disable the Visual Studio hosting process as a work around. Right-click on the name of your project in Visual Studio and then click Properties. On the Debug tab you can uncheck the Enable the Visual Studio hosting process option. 

Please Note: This only impacts the debug experience in VS 2015. This does not impact the binaries or executable that are built. The same issue does not occur in Visual Studio 2017.

Uncheck Enable the Visual Studio hosting process option. 

This was the recommended option and sure thing it fixed the error but only to introduce an entirely new problem! Whenever I did a rebuild of the code and ran the debugger it would ignore the breakpoints and run the application from start to finish on the first execution. Then quite bizarrely it would automatically open up a new debugging session. So long as I didn’t rebuild the code the breakpoints would work every time otherwise the application would execute without halting on the breakpoints.

To validate this was the cause of the problem. I started a completely new project and ensured the above behavior was repeatable. I tried with the option checked and unchecked. This proved that the issue was related to that option being turned off within Visual Studio 2015.

Final Solution

Ultimately I updated the Virtual Machine version of VS to the latest 2019 to avoid the entire problem and that’s what I recommend you do too. However as a temporary workaround and to demonstrate the point also managed to get this working by re-ticking the “Enable The Visual Studio Hosting Process” option and then adding the following code right before making the connection:

Console.WriteLine("We are in DEBUG mode so having to set security protocol to get around debugging issue with VS2015 as dont want to turn off Enable Visual Studio Hosting Process option");
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

This I believe provides best of both worlds as it means that we don’t need to worry about Microsoft recommendation:

This forces the TLS 1.2 security protocol at all times. This is not recommended as you run the risk of having to update this when there is a newer security protocol adopted by the industry.”

As this code only forces TLS 1.2 only when running in DEBUG mode this is unlikely to cause any issue if it was production level code. I have provided feeedback to Microsoft hopefully they will update there support page to reflect this issue and a resolution that actually works.