Udostępnij za pośrednictwem


Element HttpClientFactory używa programu SocketsHttpHandler jako podstawowego programu obsługi

HttpClientFactory Umożliwia skonfigurowanie potoku HttpMessageHandler dla nazwanych HttpClient i wpisanych obiektów. Najbardziej wewnętrzna procedura obsługi lub ta, która rzeczywiście wysyła żądanie na przewodzie, jest nazywana podstawową procedurą obsługi. Jeśli nie skonfigurowano, ta procedura obsługi była wcześniej zawsze elementem HttpClientHandler. Chociaż domyślna podstawowa procedura obsługi jest szczegółem implementacji, byli użytkownicy, którzy od niego polegali. Na przykład niektórzy użytkownicy rzutować podstawowy program obsługi w celu HttpClientHandler ustawienia właściwości, takich jak ClientCertificates, UseCookiesi UseProxy.

Dzięki tej zmianie domyślna podstawowa procedura obsługi jest SocketsHttpHandler oparta na platformach, które ją obsługują. Na innych platformach, na przykład .NET Framework, HttpClientHandler nadal jest używany.

SocketsHttpHandler teraz ma również właściwość wstępnie ustawioną PooledConnectionLifetime , HandlerLifetime aby dopasować wartość. (Odzwierciedla ona najnowszą wartość, jeśli HandlerLifetime została skonfigurowana przez użytkownika).

Wprowadzona wersja

.NET 9 (wersja zapoznawcza 6)

Poprzednie zachowanie

Domyślna podstawowa procedura obsługi to HttpClientHandler. Rzutowanie jej w celu HttpClientHandler zaktualizowania właściwości stało się możliwe.

services.AddHttpClient("test")
    .ConfigurePrimaryHttpMessageHandler((h, _) =>
    {
        ((HttpClientHandler)h).UseCookies = false;
    });

// This worked.
var client = httpClientFactory.CreateClient("test");

Nowe zachowanie

Na platformach, na których SocketsHttpHandler jest obsługiwana, domyślna podstawowa procedura obsługi jest teraz SocketsHttpHandler ustawiona PooledConnectionLifetime HandlerLifetime na wartość . Rzutowanie go w celu HttpClientHandler zaktualizowania właściwości zgłasza błąd InvalidCastException.

Na przykład ten sam kod z poprzedniej sekcji zachowania zgłasza teraz wyjątek InvalidCastException:

System.InvalidCastException: Nie można rzutować obiektu typu "System.Net.Http.SocketsHttpHandler", aby wpisać "System.Net.Http.HttpClientHandler".

Typ zmiany powodującej niezgodność

Ta zmiana jest zmianą behawioralną.

Przyczyna wprowadzenia zmiany

Jednym z najczęstszych problemów HttpClientFactory , które użytkownicy napotkali, jest to, że klient Named lub Typed błędnie zostaje przechwycony w pojedynczej usłudze lub, ogólnie, przechowywane gdzieś przez pewien czas dłuższy niż określony HandlerLifetime. Ponieważ HttpClientFactory nie można obracać takich procedur obsługi, mogą one nie uwzględniać zmian DNS.

Ten problem można rozwiązać za pomocą polecenia SocketsHttpHandler, który ma opcję kontrolowania PooledConnectionLifetime. Podobnie jak HandlerLifetimew przypadku programu okres istnienia połączenia w puli umożliwia regularne ponowne tworzenie połączeń w celu pobierania zmian DNS, ale na niższym poziomie. Klient z PooledConnectionLifetime konfiguracją może być bezpiecznie używany jako pojedynczy klient.

Niestety jest to łatwe i pozornie "intuicyjne", aby wstrzyknąć Typed klienta do pojedynczego. Ale trudno jest mieć jakikolwiek rodzaj sprawdzania lub analizatora, aby upewnić się, że HttpClient nie jest przechwytywany, gdy nie ma być przechwytywany. Trudno jest również rozwiązać problemy wynikające z tego problemu. W związku z tym jako środek zapobiegawczy — aby zminimalizować potencjalny wpływ błędnych wzorców użycia — SocketsHttpHandler środki zaradcze są stosowane domyślnie.

Ta zmiana ma wpływ tylko na przypadki, gdy klient nie został skonfigurowany przez użytkownika końcowego do używania niestandardowego PrimaryHandler (na przykład za pośrednictwem polecenia ConfigurePrimaryHttpMessageHandler<THandler>(IHttpClientBuilder)).

Istnieją trzy opcje obejścia zmiany powodującej niezgodność:

  • Jawnie określ i skonfiguruj podstawową procedurę obsługi dla każdego klienta:

    services.AddHttpClient("test")
      .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { UseCookies = false });
    
  • Zastąp domyślną podstawową procedurę obsługi dla wszystkich klientów przy użyciu polecenia ConfigureHttpClientDefaults(IServiceCollection, Action<IHttpClientBuilder>):

    services.ConfigureHttpClientDefaults(b =>
      b.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { UseCookies = false }));
    
  • W akcji konfiguracji sprawdź wartości i HttpClientHandler SocketsHttpHandler:

    services.AddHttpClient("test")
      .ConfigurePrimaryHttpMessageHandler((h, _) =>
      {
          if (h is HttpClientHandler hch)
          {
              hch.UseCookies = false;
          }
    
          if (h is SocketsHttpHandler shh)
          {
              shh.UseCookies = false;
          }
      });
    

Dotyczy interfejsów API