Laden...

WebRequest in .NET Framework 3.5 an REST-API

Erstellt von TomSchmitz vor 20 Tagen Letzter Beitrag vor 20 Tagen 125 Views
TomSchmitz Themenstarter:in
20 Beiträge seit 2022
vor 20 Tagen
WebRequest in .NET Framework 3.5 an REST-API

Moin Moin,

ich habe folgenden Code:

public static void HandleRequest(HttpListenerContext context)
{
   ServiceResponse response = new ServiceResponse();
   try
   {
       OpenProfileArticleDto openProfileArticleDto = JsonHelper.DeserializeFromStream<OpenProfileArticleDto>(context.Request.InputStream);
       if (openProfileArticleDto == null || string.IsNullOrEmpty(openProfileArticleDto.ArticleId))
       {
           throw new Exception("Invalid request data");
       }
       string baseUrl = "https://localhost:8099/api/profile";
       string url = $"{baseUrl}/get-partid-from-articleId?articleId={openProfileArticleDto.ArticleId}";                                
       HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
       request.Method = "GET";
       request.AllowWriteStreamBuffering = true;
       request.Timeout = 10000;
       request.AllowAutoRedirect = true;
       ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
       using (HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse())
       {
           if (webResponse.StatusCode == HttpStatusCode.OK)
           {
               using (StreamReader reader = new StreamReader(webResponse.GetResponseStream()))
               {
                   string result = reader.ReadToEnd();
                   Console.WriteLine("Part ID received: " + result);
                   var partId = int.Parse(result);
                   if (partId > 0)
                   {
                       new Thread(() =>
                       {
                           try
                           {
                               System.Diagnostics.Process.Start($"....");
                           }
                           catch (Exception ex)
                           {
                               Logger.Log($"Error opening link: {ex.Message}", Logger.LogPriority.Error);
                           }
                       })
                       { IsBackground = true }.Start();
                       response = new ServiceResponse<int> { StatusCode = 200, Message = "Wird gestartet..." };
                   }
               }
           }
           else
           {
               throw new Exception("Error getting part ID");
           }
       }
   }
   catch (Exception ex)
   {
       Logger.Log(ex.Message, Logger.LogPriority.Error);
       response = ErrorHandler.ThrowErrorAsync(500);
   }
   finally
   {
       SendResponse(context, response);
   }
}

Ich bekomme die Fehlermeldung: ex = {"Die zugrunde liegende Verbindung wurde geschlossen: Unerwarteter Fehler beim Senden.."}
Er fliegt bei "using (StreamReader reader = new StreamReader(webResponse.GetResponseStream()))"

In der Inner-Exception habe ich folgenden Stack-Trace:

bei System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
bei System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 count)
bei System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
bei System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
bei System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
bei System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
bei System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
bei System.Net.TlsStream.CallProcessAuthentication(Object state)
bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
bei System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result)
bei System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size)
bei System.Net.PooledStream.Write(Byte[] buffer, Int32 offset, Int32 size)
bei System.Net.ConnectStream.WriteHeaders(Boolean async)

Das Zertifikat funktioniert so weit. Mit Postman habe ich diesen Endpunkt auch soweit richtig getestet. Er funktioniert also.

Der REST-API-Endpunkt in .NET 7 sieht so aus:


       [HttpGet("get-partid-from-articleId")]
       public async Task<ActionResult<ServiceResponse<int>>> GetPartIdFromArticleId(string articleId)
       {
           return await ServiceResponseProcessor.ProcessServiceResponse(this, await _profileService.GetPartId(articleId));
       }

Ich habe mal testweise google.com über meinen oben dargestellten Code angefragt. Ich habe ganz normal einen 200er bekommen.

Woran könnte das liegen, dass der Request in Postman, aber nicht hier oben im Code funktioniert?

Kann es eventuell daran liegen, dass die TLS-Version von dem HttpClient aus dem .NET Framework 3.5 nicht mehr mit den aktuellen kompatibel ist? Ich habe nämlich nur die Wahl zwischen Tls und Ssl3

LG

Wenn man etwas nicht einfach erklären kann, hat man es nicht verstanden.

-Albert Einstein

TomSchmitz Themenstarter:in
20 Beiträge seit 2022
vor 20 Tagen

Ich habe die Lösung.

Ich konnte manuell das Enum erweitern.

ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072; // TLS 1.2

jetzt funktioniert es.

Wenn man etwas nicht einfach erklären kann, hat man es nicht verstanden.

-Albert Einstein

16.864 Beiträge seit 2008
vor 20 Tagen

Feedback zu Deinem Code (nur die wichtigsten Punkte):

  • Seit >10 Jahren ist die Empfehlung nur noch den HttpClient zu verwenden für Anfragen, das gilt auch für .NET 3.5, wobei es da auch noch den WebClient gab
  • Dein Exceptionhandling ist genau das, was man es nicht in .NET tun sollte - das galt schon immer 😃
  • Dein Thread-Handling so ist nicht robust und kostet sehr viele Ressourcen

Aber ja, .NET 3.5 hat solangsam das Problem, dass ein paar Sicherheitsthemen nicht mehr gut in der Runtime gelöst sind und man das selbst machen muss, was es mit späteren Versionen dann eingebaut gab.