Я знаю, что этот вопрос старый, но проблема сохраняется даже в .Net 4.7.2. В моем случае у меня есть многопоточное приложение, которое взаимодействует с двумя конечными точками. Одна конечная точка работает только с TLS 1.2, а другая конечная точка работает только с TLS 1.0 (команда, ответственная за это, работает над исправлением своей конечной точки, поэтому она также будет поддерживать TLS 1.2).
Чтобы обойти это, я переместил вызовы службы для конечной точки, которая работает только с TLS 1.0, в отдельный класс в той же сборке, а затем загрузил сборку в отдельный домен приложения. Делая это, я могу использовать эту глобальную переменную:
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
только для вызовов к сломанной конечной точке, в то же время продолжая работать и с вызовами к конечной точке TLS 1.2 (для которых не требуется устанавливать ServicePointManager.SecurityProtocol что-либо конкретное). Это также гарантирует, что когда хорошая конечная точка будет обновлена до TLS 1.3, мне не нужно будет повторно выпускать мое приложение. Мое приложение является многопоточным и имеет большую емкость, поэтому блокировка или попытка / окончание не являются адекватными решениями.
Вот код, который я использовал для загрузки сборки в отдельный домен. Обратите внимание, что я загружаю сборку из ее текущего местоположения (Aspnet Tempfiles), чтобы она не блокировала сборку в каталоге bin и не блокировала будущие развертывания.
Также обратите внимание, что прокси-класс наследует MarshalByRefObject, поэтому он используется в качестве прозрачного прокси-сервера, который сохраняет System.Net.ServicePointManager со своим собственным значением в собственном AppDomain.
Это кажется глупым ограничением со стороны .Net Framework, я хотел бы, чтобы мы могли просто указать протокол непосредственно в веб-запросе, а не прыгать через обручи, особенно после многих лет этого. (
Этот код работает, надеюсь, он вам поможет! :)
private static AppDomain _proxyDomain = null;
private static Object _syncObject = new Object();
public void MakeACallToTls10Endpoint(string tls10Endpoint, string jsonRequest)
{
if (_proxyDomain == null)
{
lock(_syncObject) // Only allow one thread to spin up the app domain.
{
if (_proxyDomain == null)
{
_proxyDomain = AppDomain.CreateDomain("CommunicationProxyDomain");
}
}
}
Type communicationProxyType = typeof(CommunicationProxy);
string assemblyPath = communicationProxyType.Assembly.Location;
// Always loading from the current assembly, sometimes this moves around in ASPNet Tempfiles causing type not found errors if you make it static.
ObjectHandle objectHandle = _proxyDomain.CreateInstanceFrom(assemblyPath, communicationProxyType.FullName.Split(',')[0]);
CommunicationProxy communicationProxy = (CommunicationProxy)objectHandle.Unwrap();
return communicationProxy.ExecuteHttpPost(tls10Endpoint, jsonRequest);
}
Затем в отдельном классе:
[Serializable]
public class CommunicationProxy : MarshalByRefObject
{
public string ExecuteHttpPost(string tls10Endpoint, string jsonRequest)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
// << Bunch of code to do the request >>
}
}