ASP.NET Core 'de ıhttpclientfactory kullanarak HTTP istekleri yapınMake HTTP requests using IHttpClientFactory in ASP.NET Core

Glenn CONDRON, Ryan şimdi ak, Steve Gordon, Rick Andersonve Kirk larkabağıBy Glenn Condron, Ryan Nowak, Steve Gordon, Rick Anderson, and Kirk Larkin

Bir IHttpClientFactory uygulamadaki örnekleri yapılandırmak ve oluşturmak için kayıt yapılabilir ve kullanılabilir HttpClient .An IHttpClientFactory can be registered and used to configure and create HttpClient instances in an app. IHttpClientFactoryaşağıdaki avantajları sunar:IHttpClientFactory offers the following benefits:

  • , Mantıksal örnekleri adlandırmak ve yapılandırmak için merkezi bir konum sağlar HttpClient .Provides a central location for naming and configuring logical HttpClient instances. Örneğin, GitHub adlı bir Istemci, GitHub'a erişmek için kaydedilebilir ve yapılandırılabilir.For example, a client named github could be registered and configured to access GitHub. Varsayılan istemci, genel erişim için kaydedilebilir.A default client can be registered for general access.
  • ' De işleyiciler temsilci seçme yoluyla giden ara yazılım kavramını daha da artırır HttpClient .Codifies the concept of outgoing middleware via delegating handlers in HttpClient. ' De işleyiciler temsilci atama avantajlarından faydalanmak için, Polya tabanlı bir ara yazılım için uzantılar sağlar HttpClient .Provides extensions for Polly-based middleware to take advantage of delegating handlers in HttpClient.
  • Temel örneklerin biriktirmesini ve ömrünü yönetir HttpClientMessageHandler .Manages the pooling and lifetime of underlying HttpClientMessageHandler instances. Otomatik yönetim, yaşam sürelerini el ile yönetirken oluşan ortak DNS (etki alanı adı sistemi) sorunlarını önler HttpClient .Automatic management avoids common DNS (Domain Name System) problems that occur when manually managing HttpClient lifetimes.
  • ILoggerFabrika tarafından oluşturulan istemciler aracılığıyla gönderilen tüm istekler için yapılandırılabilir bir günlüğe kaydetme deneyimi ekler (aracılığıyla).Adds a configurable logging experience (via ILogger) for all requests sent through clients created by the factory.

Örnek kodu görüntüleyin veya indirin (nasıl indirilir).View or download sample code (how to download).

Bu konu sürümündeki örnek kod, System.Text.Json http yanıtlarında döndürülen JSON içeriğinin serisini kaldırmak için kullanır.The sample code in this topic version uses System.Text.Json to deserialize JSON content returned in HTTP responses. Ve kullanan örnekler için Json.NET ReadAsAsync<T> , bu konunun 2. x sürümünü seçmek üzere sürüm seçiciyi kullanın.For samples that use Json.NET and ReadAsAsync<T>, use the version selector to select a 2.x version of this topic.

Tüketim desenleriConsumption patterns

Bir uygulamada çeşitli yollar IHttpClientFactory kullanılabilir:There are several ways IHttpClientFactory can be used in an app:

En iyi yaklaşım, uygulamanın gereksinimlerine bağlı olarak değişir.The best approach depends upon the app's requirements.

Temel kullanımBasic usage

IHttpClientFactory, çağırarak kaydedilebilir AddHttpClient :IHttpClientFactory can be registered by calling AddHttpClient:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHttpClient();
        // Remaining code deleted for brevity.

IHttpClientFactory Bağımlılık ekleme (dı)kullanılarak bir istek yapılabilir.An IHttpClientFactory can be requested using dependency injection (DI). Aşağıdaki kod IHttpClientFactory bir örnek oluşturmak için kullanır HttpClient :The following code uses IHttpClientFactory to create an HttpClient instance:

public class BasicUsageModel : PageModel
{
    private readonly IHttpClientFactory _clientFactory;

    public IEnumerable<GitHubBranch> Branches { get; private set; }

    public bool GetBranchesError { get; private set; }

    public BasicUsageModel(IHttpClientFactory clientFactory)
    {
        _clientFactory = clientFactory;
    }

    public async Task OnGet()
    {
        var request = new HttpRequestMessage(HttpMethod.Get,
            "https://api.github.com/repos/aspnet/AspNetCore.Docs/branches");
        request.Headers.Add("Accept", "application/vnd.github.v3+json");
        request.Headers.Add("User-Agent", "HttpClientFactory-Sample");

        var client = _clientFactory.CreateClient();

        var response = await client.SendAsync(request);

        if (response.IsSuccessStatusCode)
        {
            using var responseStream = await response.Content.ReadAsStreamAsync();
            Branches = await JsonSerializer.DeserializeAsync
                <IEnumerable<GitHubBranch>>(responseStream);
        }
        else
        {
            GetBranchesError = true;
            Branches = Array.Empty<GitHubBranch>();
        }
    }
}

IHttpClientFactoryYukarıdaki örnekte olduğu gibi kullanmak, mevcut bir uygulamayı yeniden düzenleme için iyi bir yoldur.Using IHttpClientFactory like in the preceding example is a good way to refactor an existing app. Kullanım hakkında hiçbir etkisi yoktur HttpClient .It has no impact on how HttpClient is used. HttpClientVar olan bir uygulamada örneklerin oluşturulduğu yerlerde, bu oluşumların ' i çağrılarıyla değiştirin CreateClient .In places where HttpClient instances are created in an existing app, replace those occurrences with calls to CreateClient.

Adlandırılmış istemcilerNamed clients

Adlandırılmış istemciler şu durumlarda iyi bir seçimdir:Named clients are a good choice when:

  • Uygulama birçok farklı kullanımı gerektirir HttpClient .The app requires many distinct uses of HttpClient.
  • Birçok HttpClient s farklı yapılandırmaya sahiptir.Many HttpClients have different configuration.

Adlandırılmış için yapılandırma HttpClient , içinde kayıt sırasında belirtilebilir Startup.ConfigureServices :Configuration for a named HttpClient can be specified during registration in Startup.ConfigureServices:

services.AddHttpClient("github", c =>
{
    c.BaseAddress = new Uri("https://api.github.com/");
    // Github API versioning
    c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
    // Github requires a user-agent
    c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
});

İstemcinin yapılandırıldığı önceki kodda:In the preceding code the client is configured with:

  • Temel adres https://api.github.com/ .The base address https://api.github.com/.
  • GitHub API 'SI ile çalışmak için iki üst bilgi gereklidir.Two headers required to work with the GitHub API.

CreateClientCreateClient

Her zaman CreateClient çağrılır:Each time CreateClient is called:

  • Yeni bir örneği HttpClient oluşturulur.A new instance of HttpClient is created.
  • Yapılandırma eylemi çağrılır.The configuration action is called.

Adlandırılmış bir istemci oluşturmak için adını içine geçirin CreateClient :To create a named client, pass its name into CreateClient:

public class NamedClientModel : PageModel
{
    private readonly IHttpClientFactory _clientFactory;

    public IEnumerable<GitHubPullRequest> PullRequests { get; private set; }

    public bool GetPullRequestsError { get; private set; }

    public bool HasPullRequests => PullRequests.Any();

    public NamedClientModel(IHttpClientFactory clientFactory)
    {
        _clientFactory = clientFactory;
    }

    public async Task OnGet()
    {
        var request = new HttpRequestMessage(HttpMethod.Get,
            "repos/aspnet/AspNetCore.Docs/pulls");

        var client = _clientFactory.CreateClient("github");

        var response = await client.SendAsync(request);

        if (response.IsSuccessStatusCode)
        {
            using var responseStream = await response.Content.ReadAsStreamAsync();
            PullRequests = await JsonSerializer.DeserializeAsync
                    <IEnumerable<GitHubPullRequest>>(responseStream);
        }
        else
        {
            GetPullRequestsError = true;
            PullRequests = Array.Empty<GitHubPullRequest>();
        }
    }
}

Yukarıdaki kodda, isteğin bir ana bilgisayar adı belirtmesi gerekmez.In the preceding code, the request doesn't need to specify a hostname. İstemci için yapılandırılan taban adresi kullanıldığından, kod yalnızca yolu geçirebilir.The code can pass just the path, since the base address configured for the client is used.

Yazılan istemcilerTyped clients

Yazılan istemciler:Typed clients:

  • Dizeleri anahtar olarak kullanma gereksinimi olmadan, adlandırılmış istemcilerle aynı özellikleri sağlayın.Provide the same capabilities as named clients without the need to use strings as keys.
  • İstemcileri tükettiren IntelliSense ve derleyici yardımı sağlar.Provides IntelliSense and compiler help when consuming clients.
  • Yapılandırmak ve belirli bir ile etkileşimde bulunmak için tek bir konum belirtin HttpClient .Provide a single location to configure and interact with a particular HttpClient. Örneğin, tek bir türü belirtilmiş istemci kullanılabilir:For example, a single typed client might be used:
    • Tek bir arka uç uç noktası için.For a single backend endpoint.
    • Uç nokta ile ilgili tüm mantığı kapsüllemek için.To encapsulate all logic dealing with the endpoint.
  • DI ile birlikte çalışın ve uygulamada gerektiğinde eklenebilir.Work with DI and can be injected where required in the app.

Türü belirtilmiş istemci HttpClient , oluşturucusunda bir parametreyi kabul eder:A typed client accepts an HttpClient parameter in its constructor:

public class GitHubService
{
    public HttpClient Client { get; }

    public GitHubService(HttpClient client)
    {
        client.BaseAddress = new Uri("https://api.github.com/");
        // GitHub API versioning
        client.DefaultRequestHeaders.Add("Accept",
            "application/vnd.github.v3+json");
        // GitHub requires a user-agent
        client.DefaultRequestHeaders.Add("User-Agent",
            "HttpClientFactory-Sample");

        Client = client;
    }

    public async Task<IEnumerable<GitHubIssue>> GetAspNetDocsIssues()
    {
        var response = await Client.GetAsync(
            "/repos/aspnet/AspNetCore.Docs/issues?state=open&sort=created&direction=desc");

        response.EnsureSuccessStatusCode();

        using var responseStream = await response.Content.ReadAsStreamAsync();
        return await JsonSerializer.DeserializeAsync
            <IEnumerable<GitHubIssue>>(responseStream);
    }
}

Ingilizce dışındaki dillere çevrilmiş kod açıklamalarını görmek isterseniz, Bu GitHub tartışma sorununubize tanıyın.If you would like to see code comments translated to languages other than English, let us know in this GitHub discussion issue.

Yukarıdaki kodda:In the preceding code:

  • Yapılandırma, yazılan istemciye taşınır.The configuration is moved into the typed client.
  • HttpClientNesne bir ortak özellik olarak sunulur.The HttpClient object is exposed as a public property.

İşlevselliği kullanıma sunan, API 'ye özgü Yöntemler oluşturulabilir HttpClient .API-specific methods can be created that expose HttpClient functionality. Örneğin, GetAspNetDocsIssues yöntemi açık sorunları almak için kodu kapsüller.For example, the GetAspNetDocsIssues method encapsulates code to retrieve open issues.

Aşağıdaki kod, AddHttpClient Startup.ConfigureServices türü belirtilmiş bir istemci sınıfını kaydetmek için ' de çağırır:The following code calls AddHttpClient in Startup.ConfigureServices to register a typed client class:

services.AddHttpClient<GitHubService>();

Yazılan istemci, DI ile geçici olarak kaydedilir.The typed client is registered as transient with DI. Yukarıdaki kodda AddHttpClient GitHubService geçici bir hizmet olarak kaydedilir.In the preceding code, AddHttpClient registers GitHubService as a transient service. Bu kayıt, için bir fabrika yöntemi kullanır:This registration uses a factory method to:

  1. HttpClient örneği oluşturun.Create an instance of HttpClient.
  2. Örneğini oluşturucusuna geçirerek bir örneğini oluşturun GitHubService HttpClient .Create an instance of GitHubService, passing in the instance of HttpClient to its constructor.

Yazılan istemci doğrudan eklenebilir ve tüketilebilir:The typed client can be injected and consumed directly:

public class TypedClientModel : PageModel
{
    private readonly GitHubService _gitHubService;

    public IEnumerable<GitHubIssue> LatestIssues { get; private set; }

    public bool HasIssue => LatestIssues.Any();

    public bool GetIssuesError { get; private set; }

    public TypedClientModel(GitHubService gitHubService)
    {
        _gitHubService = gitHubService;
    }

    public async Task OnGet()
    {
        try
        {
            LatestIssues = await _gitHubService.GetAspNetDocsIssues();
        }
        catch(HttpRequestException)
        {
            GetIssuesError = true;
            LatestIssues = Array.Empty<GitHubIssue>();
        }
    }
}

Türü belirtilmiş bir istemcinin yapılandırması Startup.ConfigureServices , türü belirlenmiş istemcinin Oluşturucusu yerine kayıt sırasında belirtilebilir:The configuration for a typed client can be specified during registration in Startup.ConfigureServices, rather than in the typed client's constructor:

services.AddHttpClient<RepoService>(c =>
{
    c.BaseAddress = new Uri("https://api.github.com/");
    c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
    c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
});

, HttpClient Türü belirlenmiş bir istemci içinde kapsüllenebilir.The HttpClient can be encapsulated within a typed client. Bunu bir özellik olarak göstermek yerine, örneği dahili olarak çağıran bir yöntem tanımlayın HttpClient :Rather than exposing it as a property, define a method which calls the HttpClient instance internally:

public class RepoService
{
    // _httpClient isn't exposed publicly
    private readonly HttpClient _httpClient;

    public RepoService(HttpClient client)
    {
        _httpClient = client;
    }

    public async Task<IEnumerable<string>> GetRepos()
    {
        var response = await _httpClient.GetAsync("aspnet/repos");

        response.EnsureSuccessStatusCode();

        using var responseStream = await response.Content.ReadAsStreamAsync();
        return await JsonSerializer.DeserializeAsync
            <IEnumerable<string>>(responseStream);
    }
}

Yukarıdaki kodda, HttpClient bir özel alanda depolanır.In the preceding code, the HttpClient is stored in a private field. Öğesine erişimi, HttpClient genel yöntemi tarafından yapılır GetRepos .Access to the HttpClient is by the public GetRepos method.

Oluşturulan istemcilerGenerated clients

IHttpClientFactory, yeniden sığdırmagibi üçüncü taraf kitaplıklarla birlikte kullanılabilir.IHttpClientFactory can be used in combination with third-party libraries such as Refit. Yeniden sığdırma, .NET için bir REST kitaplığıdır.Refit is a REST library for .NET. REST API 'Leri canlı arabirimlere dönüştürür.It converts REST APIs into live interfaces. Arabirim bir uygulama, RestService HttpClient dış http çağrıları yapmak için kullanılarak tarafından dinamik olarak oluşturulur.An implementation of the interface is generated dynamically by the RestService, using HttpClient to make the external HTTP calls.

Bir arabirim ve yanıt, dış API 'yi ve yanıtını temsil edecek şekilde tanımlanır:An interface and a reply are defined to represent the external API and its response:

public interface IHelloClient
{
    [Get("/helloworld")]
    Task<Reply> GetMessageAsync();
}

public class Reply
{
    public string Message { get; set; }
}

Türü belirlenmiş bir istemci eklenebilir, uygulamayı oluşturmak için yeniden sığdırma kullanımı kullanılabilir:A typed client can be added, using Refit to generate the implementation:

public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient("hello", c =>
    {
        c.BaseAddress = new Uri("http://localhost:5000");
    })
    .AddTypedClient(c => Refit.RestService.For<IHelloClient>(c));

    services.AddControllers();
}

Tanımlı arabirim, gereken yerde, mak ve Refit tarafından sağlanmış uygulama ile kullanılabilir.The defined interface can be consumed where necessary, with the implementation provided by DI and Refit:

[ApiController]
public class ValuesController : ControllerBase
{
    private readonly IHelloClient _client;

    public ValuesController(IHelloClient client)
    {
        _client = client;
    }

    [HttpGet("/")]
    public async Task<ActionResult<Reply>> Index()
    {
        return await _client.GetMessageAsync();
    }
}

GÖNDERI, PUT ve DELETE isteklerini oluşturmaMake POST, PUT, and DELETE requests

Yukarıdaki örneklerde, tüm HTTP istekleri GET HTTP fiilini kullanır.In the preceding examples, all HTTP requests use the GET HTTP verb. HttpClient, aşağıdakiler de dahil olmak üzere diğer HTTP fiillerini de destekler:HttpClient also supports other HTTP verbs, including:

  • POSTPOST
  • PUTPUT
  • DELETEDELETE
  • DÜZELTMESIPATCH

Desteklenen HTTP fiillerinin tüm listesi için bkz HttpMethod ..For a complete list of supported HTTP verbs, see HttpMethod.

Aşağıdaki örnek, bir HTTP POST isteğinin nasıl yapılacağını göstermektedir:The following example shows how to make an HTTP POST request:

public async Task CreateItemAsync(TodoItem todoItem)
{
    var todoItemJson = new StringContent(
        JsonSerializer.Serialize(todoItem, _jsonSerializerOptions),
        Encoding.UTF8,
        "application/json");

    using var httpResponse =
        await _httpClient.PostAsync("/api/TodoItems", todoItemJson);

    httpResponse.EnsureSuccessStatusCode();
}

Yukarıdaki kodda, CreateItemAsync yöntemi:In the preceding code, the CreateItemAsync method:

  • TodoItemParametresini kullanarak JSON için parametreyi seri hale getirir System.Text.Json .Serializes the TodoItem parameter to JSON using System.Text.Json. Bu JsonSerializerOptions , serileştirme işlemini yapılandırmak için bir örneğini kullanır.This uses an instance of JsonSerializerOptions to configure the serialization process.
  • StringContentHttp isteğinin gövdesinde göndermek üzere seri hale GETIRILMIŞ JSON paketini paketlemek için bir örneği oluşturur.Creates an instance of StringContent to package the serialized JSON for sending in the HTTP request's body.
  • PostAsyncJSON içeriğini BELIRTILEN URL 'ye göndermek için çağrılar.Calls PostAsync to send the JSON content to the specified URL. Bu, HttpClient. BaseAddress'e eklenen GÖRELI bir URL 'dir.This is a relative URL that gets added to the HttpClient.BaseAddress.
  • EnsureSuccessStatusCodeYanıt durum kodu başarıyı belirtmezse bir özel durum oluşturmak için çağırır.Calls EnsureSuccessStatusCode to throw an exception if the response status code does not indicate success.

HttpClient, diğer içerik türlerini de destekler.HttpClient also supports other types of content. Örneğin, MultipartContent ve StreamContent.For example, MultipartContent and StreamContent. Desteklenen içeriğin tamamı listesi için bkz HttpContent ..For a complete list of supported content, see HttpContent.

Aşağıdaki örnekte bir HTTP PUT isteği gösterilmektedir:The following example shows an HTTP PUT request:

public async Task SaveItemAsync(TodoItem todoItem)
{
    var todoItemJson = new StringContent(
        JsonSerializer.Serialize(todoItem),
        Encoding.UTF8,
        "application/json");

    using var httpResponse =
        await _httpClient.PutAsync($"/api/TodoItems/{todoItem.Id}", todoItemJson);

    httpResponse.EnsureSuccessStatusCode();
}

Yukarıdaki kod, POST örneğine çok benzer.The preceding code is very similar to the POST example. SaveItemAsyncYöntemi yerine çağırır PutAsync PostAsync .The SaveItemAsync method calls PutAsync instead of PostAsync.

Aşağıdaki örnekte bir HTTP SILME isteği gösterilmektedir:The following example shows an HTTP DELETE request:

public async Task DeleteItemAsync(long itemId)
{
    using var httpResponse =
        await _httpClient.DeleteAsync($"/api/TodoItems/{itemId}");

    httpResponse.EnsureSuccessStatusCode();
}

Yukarıdaki kodda, DeleteItemAsync yöntemi çağırır DeleteAsync .In the preceding code, the DeleteItemAsync method calls DeleteAsync. HTTP DELETE istekleri genellikle gövde içermediğinden, DeleteAsync yöntemi bir örneğini kabul eden bir aşırı yükleme sağlamaz HttpContent .Because HTTP DELETE requests typically contain no body, the DeleteAsync method doesn't provide an overload that accepts an instance of HttpContent.

İle farklı HTTP fiillerini kullanma hakkında daha fazla bilgi için HttpClient bkz HttpClient ..To learn more about using different HTTP verbs with HttpClient, see HttpClient.

Giden istek ara yazılımıOutgoing request middleware

HttpClient, giden HTTP istekleri için birlikte bağlanabilen işleyicileri temsilci seçme kavramıdır.HttpClient has the concept of delegating handlers that can be linked together for outgoing HTTP requests. IHttpClientFactory:IHttpClientFactory:

  • Her bir adlandırılmış istemci için uygulanacak işleyiciler tanımlamayı basitleştirir.Simplifies defining the handlers to apply for each named client.

  • Bir giden istek ara yazılım işlem hattı oluşturmak için birden çok işleyicinin kaydedilmesini ve zincirleme kullanımını destekler.Supports registration and chaining of multiple handlers to build an outgoing request middleware pipeline. Bu işleyicilerin her biri, giden istekten önce ve sonra iş gerçekleştirebilir.Each of these handlers is able to perform work before and after the outgoing request. Bu model:This pattern:

    • ASP.NET Core gelen ara yazılım ardışık düzenine benzerdir.Is similar to the inbound middleware pipeline in ASP.NET Core.

    • , HTTP istekleri etrafında çapraz kesme sorunlarını yönetmek için bir mekanizma sağlar, örneğin:Provides a mechanism to manage cross-cutting concerns around HTTP requests, such as:

      • önbelleğicaching
      • hata işlemeerror handling
      • getirserialization
      • günlüğe kaydetmelogging

Temsilci seçme işleyicisi oluşturmak için:To create a delegating handler:

  • Türet DelegatingHandler .Derive from DelegatingHandler.
  • Geçersiz kıl SendAsync .Override SendAsync. İsteği ardışık düzen içindeki bir sonraki işleyiciye geçirmeden önce kodu yürütün:Execute code before passing the request to the next handler in the pipeline:
public class ValidateHeaderHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        if (!request.Headers.Contains("X-API-KEY"))
        {
            return new HttpResponseMessage(HttpStatusCode.BadRequest)
            {
                Content = new StringContent(
                    "You must supply an API key header called X-API-KEY")
            };
        }

        return await base.SendAsync(request, cancellationToken);
    }
}

Yukarıdaki kod, üstbilginin istekte olup olmadığını denetler X-API-KEY .The preceding code checks if the X-API-KEY header is in the request. X-API-KEYEksikse, BadRequest döndürülür.If X-API-KEY is missing, BadRequest is returned.

İçin yapılandırmasına birden fazla işleyici eklenebilir HttpClient Microsoft.Extensions.DependencyInjection.HttpClientBuilderExtensions.AddHttpMessageHandler :More than one handler can be added to the configuration for an HttpClient with Microsoft.Extensions.DependencyInjection.HttpClientBuilderExtensions.AddHttpMessageHandler:

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<ValidateHeaderHandler>();

    services.AddHttpClient("externalservice", c =>
    {
        // Assume this is an "external" service which requires an API KEY
        c.BaseAddress = new Uri("https://localhost:5001/");
    })
    .AddHttpMessageHandler<ValidateHeaderHandler>();

    // Remaining code deleted for brevity.

Yukarıdaki kodda,, ValidateHeaderHandler dı ile kaydedilir.In the preceding code, the ValidateHeaderHandler is registered with DI. IHttpClientFactoryHer işleyici için ayrı bır dı kapsamı oluşturur.The IHttpClientFactory creates a separate DI scope for each handler. İşleyiciler herhangi bir kapsamın hizmetlerine bağlı olabilir.Handlers can depend upon services of any scope. İşleyicilerin bağımlı olduğu hizmetler, işleyicinin elden çıkarılmasıyla kaldırılır.Services that handlers depend upon are disposed when the handler is disposed.

Kaydedildikten sonra, AddHttpMessageHandler işleyicinin türü geçirerek, çağrılabilir.Once registered, AddHttpMessageHandler can be called, passing in the type for the handler.

Birden çok işleyici, yürütülmesi gereken sırayla kaydedilebilir.Multiple handlers can be registered in the order that they should execute. Her işleyici, son isteği çalıştırana kadar sonraki işleyiciyi sarmalar HttpClientHandler :Each handler wraps the next handler until the final HttpClientHandler executes the request:

services.AddTransient<SecureRequestHandler>();
services.AddTransient<RequestDataHandler>();

services.AddHttpClient("clientwithhandlers")
    // This handler is on the outside and called first during the 
    // request, last during the response.
    .AddHttpMessageHandler<SecureRequestHandler>()
    // This handler is on the inside, closest to the request being 
    // sent.
    .AddHttpMessageHandler<RequestDataHandler>();

İleti işleyicileriyle istek başına durumu paylaşmak için aşağıdaki yaklaşımlardan birini kullanın:Use one of the following approaches to share per-request state with message handlers:

Polly tabanlı işleyiciler kullanınUse Polly-based handlers

IHttpClientFactoryüçüncü taraf kitaplığı Pollyile tümleşir.IHttpClientFactory integrates with the third-party library Polly. Polly, .NET için kapsamlı bir esnekliği ve geçici hata işleme kitaplığıdır.Polly is a comprehensive resilience and transient fault-handling library for .NET. Geliştiricilerin yeniden deneme, devre kesici, zaman aşımı, Bulkbaş yalıtımı, akıcı ve iş parçacığı açısından güvenli bir şekilde geri dönüş gibi ilkeler almasına olanak tanır.It allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner.

Uzantı yöntemleri, yapılandırılmış örneklerle Polly ilkelerin kullanımını etkinleştirmek için sağlanır HttpClient .Extension methods are provided to enable the use of Polly policies with configured HttpClient instances. Polly uzantıları, istemcilere Polly tabanlı işleyiciler eklemeyi destekler.The Polly extensions support adding Polly-based handlers to clients. Polly, Microsoft. Extensions. http. Polly NuGet paketini gerektirir.Polly requires the Microsoft.Extensions.Http.Polly NuGet package.

Geçici hataları işleHandle transient faults

Hatalar genellikle dış HTTP çağrıları geçici olduğunda oluşur.Faults typically occur when external HTTP calls are transient. AddTransientHttpErrorPolicygeçici hataları işlemek için bir ilkenin tanımlanmasını sağlar.AddTransientHttpErrorPolicy allows a policy to be defined to handle transient errors. AddTransientHttpErrorPolicyAşağıdaki yanıtları işleyecek şekilde yapılandırılan ilkeler:Policies configured with AddTransientHttpErrorPolicy handle the following responses:

AddTransientHttpErrorPolicy``PolicyBuilderolası bir geçici hatayı temsil eden hataları işlemek için yapılandırılmış bir nesneye erişim sağlar:AddTransientHttpErrorPolicy provides access to a PolicyBuilder object configured to handle errors representing a possible transient fault:

public void ConfigureServices(IServiceCollection services)
{           
    services.AddHttpClient<UnreliableEndpointCallerService>()
        .AddTransientHttpErrorPolicy(p => 
            p.WaitAndRetryAsync(3, _ => TimeSpan.FromMilliseconds(600)));

    // Remaining code deleted for brevity.

Yukarıdaki kodda bir WaitAndRetryAsync ilke tanımlanmıştır.In the preceding code, a WaitAndRetryAsync policy is defined. Başarısız istekler, denemeler arasındaki 600 MS gecikmeyle en fazla üç kez yeniden denenir.Failed requests are retried up to three times with a delay of 600 ms between attempts.

Dinamik olarak ilke seçmeDynamically select policies

Uzantı yöntemleri, örneğin, Polly tabanlı işleyiciler eklemek için sağlanır AddPolicyHandler .Extension methods are provided to add Polly-based handlers, for example, AddPolicyHandler. Aşağıdaki AddPolicyHandler aşırı yükleme, hangi ilkenin uygulanacağını belirlemek için isteği inceler:The following AddPolicyHandler overload inspects the request to decide which policy to apply:

var timeout = Policy.TimeoutAsync<HttpResponseMessage>(
    TimeSpan.FromSeconds(10));
var longTimeout = Policy.TimeoutAsync<HttpResponseMessage>(
    TimeSpan.FromSeconds(30));

services.AddHttpClient("conditionalpolicy")
// Run some code to select a policy based on the request
    .AddPolicyHandler(request => 
        request.Method == HttpMethod.Get ? timeout : longTimeout);

Yukarıdaki kodda, giden istek bir HTTP GET ise, 10 saniyelik bir zaman aşımı uygulanır.In the preceding code, if the outgoing request is an HTTP GET, a 10-second timeout is applied. Diğer HTTP yöntemleri için, 30 saniyelik bir zaman aşımı kullanılır.For any other HTTP method, a 30-second timeout is used.

Birden çok Polly işleyici eklemeAdd multiple Polly handlers

Polly ilkeleri iç içe almak yaygın bir şekilde yapılır:It's common to nest Polly policies:

services.AddHttpClient("multiplepolicies")
    .AddTransientHttpErrorPolicy(p => p.RetryAsync(3))
    .AddTransientHttpErrorPolicy(
        p => p.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));

Yukarıdaki örnekte:In the preceding example:

  • İki işleyici eklenir.Two handlers are added.
  • İlk işleyici, AddTransientHttpErrorPolicy yeniden deneme ilkesi eklemek için kullanır.The first handler uses AddTransientHttpErrorPolicy to add a retry policy. Başarısız istekler en fazla üç kez yeniden denenir.Failed requests are retried up to three times.
  • İkinci AddTransientHttpErrorPolicy çağrı bir devre kesici ilkesi ekler.The second AddTransientHttpErrorPolicy call adds a circuit breaker policy. 5 başarısız girişim sıralı olarak gerçekleşirse, daha fazla dış istek 30 saniye boyunca engellenir.Further external requests are blocked for 30 seconds if 5 failed attempts occur sequentially. Devre kesici ilkeleri durum bilgisi vardır.Circuit breaker policies are stateful. Bu istemci aracılığıyla yapılan tüm çağrılar aynı devre durumunu paylaşır.All calls through this client share the same circuit state.

Polly kayıt defterinden ilke eklemeAdd policies from the Polly registry

Düzenli olarak kullanılan ilkeleri yönetmeye yönelik bir yaklaşım, bunları bir kez tanımlayıp bir ile kaydetmektir PolicyRegistry .An approach to managing regularly used policies is to define them once and register them with a PolicyRegistry.

Aşağıdaki kodda:In the following code:

public void ConfigureServices(IServiceCollection services)
{           
    var timeout = Policy.TimeoutAsync<HttpResponseMessage>(
        TimeSpan.FromSeconds(10));
    var longTimeout = Policy.TimeoutAsync<HttpResponseMessage>(
        TimeSpan.FromSeconds(30));
    
    var registry = services.AddPolicyRegistry();

    registry.Add("regular", timeout);
    registry.Add("long", longTimeout);
    
    services.AddHttpClient("regularTimeoutHandler")
        .AddPolicyHandlerFromRegistry("regular");

    services.AddHttpClient("longTimeoutHandler")
       .AddPolicyHandlerFromRegistry("long");

    // Remaining code deleted for brevity.

Ve daha fazla tümleştirme hakkında daha fazla bilgi için IHttpClientFactory bkz. Polly wiki.For more information on IHttpClientFactory and Polly integrations, see the Polly wiki.

HttpClient ve ömür yönetimiHttpClient and lifetime management

HttpClientHer çağrıldığında yeni bir örnek döndürülür CreateClient IHttpClientFactory .A new HttpClient instance is returned each time CreateClient is called on the IHttpClientFactory. HttpMessageHandlerAdlandırılmış istemci başına oluşturulur.An HttpMessageHandler is created per named client. Fabrika, örneklerin yaşam sürelerini yönetir HttpMessageHandler .The factory manages the lifetimes of the HttpMessageHandler instances.

IHttpClientFactory``HttpMessageHandlerkaynak tüketimini azaltmak için fabrika tarafından oluşturulan örnekleri havuzlar.IHttpClientFactory pools the HttpMessageHandler instances created by the factory to reduce resource consumption. Bir HttpMessageHandler örnek, süresi dolmamışsa yeni bir örnek oluştururken havuzdan yeniden kullanılabilir HttpClient .An HttpMessageHandler instance may be reused from the pool when creating a new HttpClient instance if its lifetime hasn't expired.

Her işleyici genellikle kendi temel HTTP bağlantılarını yönettiğinden, işleyicilerin havuzlaması tercih edilir.Pooling of handlers is desirable as each handler typically manages its own underlying HTTP connections. Gerekenden daha fazla işleyici oluşturulması bağlantı gecikmeleri oluşmasına neden olabilir.Creating more handlers than necessary can result in connection delays. Ayrıca, bazı işleyiciler bağlantıları süresiz olarak açık tutar, bu da işleyicinin DNS (etki alanı adı sistemi) değişikliklerine yeniden davranmasını engelleyebilir.Some handlers also keep connections open indefinitely, which can prevent the handler from reacting to DNS (Domain Name System) changes.

Varsayılan işleyici ömrü iki dakikadır.The default handler lifetime is two minutes. Varsayılan değer, adlandırılmış istemci temelinde geçersiz kılınabilir:The default value can be overridden on a per named client basis:

public void ConfigureServices(IServiceCollection services)
{           
    services.AddHttpClient("extendedhandlerlifetime")
        .SetHandlerLifetime(TimeSpan.FromMinutes(5));

    // Remaining code deleted for brevity.

HttpClientörnekler genellikle aktiften çıkarma gerektirmeyen .NET nesneleri olarak kabul edilebilir.HttpClient instances can generally be treated as .NET objects not requiring disposal. Çıkarma giden istekleri iptal eder ve HttpClient çağırma sonrasında verilen örneğin kullanılamaz olmasını sağlar Dispose .Disposal cancels outgoing requests and guarantees the given HttpClient instance can't be used after calling Dispose. IHttpClientFactoryörnekler tarafından kullanılan kaynakları izler ve ortadan kaldırdık HttpClient .IHttpClientFactory tracks and disposes resources used by HttpClient instances.

Tek HttpClient bir örneğinin uzun süre canlı tutulması, önünde kullanılmadan önce kullanılan ortak bir modeldir IHttpClientFactory .Keeping a single HttpClient instance alive for a long duration is a common pattern used before the inception of IHttpClientFactory. Bu model, ' a geçtikten sonra gereksiz hale gelir IHttpClientFactory .This pattern becomes unnecessary after migrating to IHttpClientFactory.

Ihttpclientfactory alternatifleriAlternatives to IHttpClientFactory

IHttpClientFactoryDı etkin bir uygulamada kullanmak şunları önler:Using IHttpClientFactory in a DI-enabled app avoids:

  • Havuz örneklerine göre kaynak tükenmesi sorunları HttpMessageHandler .Resource exhaustion problems by pooling HttpMessageHandler instances.
  • Düzenli aralıklarla örnekleri geçirerek eski DNS sorunları HttpMessageHandler .Stale DNS problems by cycling HttpMessageHandler instances at regular intervals.

Uzun süreli bir örnek kullanarak önceki sorunları çözmenin alternatif yolları vardır SocketsHttpHandler .There are alternative ways to solve the preceding problems using a long-lived SocketsHttpHandler instance.

  • SocketsHttpHandlerUygulamanın başladığı zaman bir örneği oluşturun ve uygulamanın ömrü boyunca kullanın.Create an instance of SocketsHttpHandler when the app starts and use it for the life of the app.
  • PooledConnectionLifetimeDNS yenileme süreleri temelinde uygun bir değere yapılandırın.Configure PooledConnectionLifetime to an appropriate value based on DNS refresh times.
  • HttpClientGerektiğinde örnek oluşturun new HttpClient(handler, disposeHandler: false) .Create HttpClient instances using new HttpClient(handler, disposeHandler: false) as needed.

Yukarıdaki yaklaşımlar, IHttpClientFactory benzer bir şekilde çözen kaynak yönetimi sorunlarını çözer.The preceding approaches solve the resource management problems that IHttpClientFactory solves in a similar way.

  • , SocketsHttpHandler Örnekleri arasında bağlantıları paylaşır HttpClient .The SocketsHttpHandler shares connections across HttpClient instances. Bu paylaşım, yuva azalmasına engel olur.This sharing prevents socket exhaustion.
  • SocketsHttpHandlerBağlantıları, PooledConnectionLifetime eski DNS sorunlarından kaçınmak için öğesine göre döngüler.The SocketsHttpHandler cycles connections according to PooledConnectionLifetime to avoid stale DNS problems.

Tanımlama bilgileriCookies

Havuza alınmış HttpMessageHandler örnekler, CookieContainer paylaşılan nesneler ile sonuçlanır.The pooled HttpMessageHandler instances results in CookieContainer objects being shared. Beklenmeyen CookieContainer nesne paylaşımı genellikle hatalı kodla sonuçlanır.Unanticipated CookieContainer object sharing often results in incorrect code. Tanımlama bilgileri gerektiren uygulamalar için şunlardan birini göz önünde bulundurun:For apps that require cookies, consider either:

  • Otomatik tanımlama bilgisi işlemeyi devre dışı bırakmaDisabling automatic cookie handling
  • ÖnlemeninIHttpClientFactoryAvoiding IHttpClientFactory

ConfigurePrimaryHttpMessageHandlerOtomatik tanımlama bilgisi işlemesini devre dışı bırakmak için çağırın:Call ConfigurePrimaryHttpMessageHandler to disable automatic cookie handling:

services.AddHttpClient("configured-disable-automatic-cookies")
    .ConfigurePrimaryHttpMessageHandler(() =>
    {
        return new SocketsHttpHandler()
        {
            UseCookies = false,
        };
    });

Günlüğe KaydetmeLogging

IHttpClientFactoryTüm istekler için kayıt günlüğü iletileri aracılığıyla oluşturulan istemciler.Clients created via IHttpClientFactory record log messages for all requests. Varsayılan günlük iletilerini görmek için günlük yapılandırmasında uygun bilgi düzeyini etkinleştirin.Enable the appropriate information level in the logging configuration to see the default log messages. İstek üst bilgilerinin günlüğe kaydedilmesi gibi ek Günlükler yalnızca izleme düzeyinde yer alır.Additional logging, such as the logging of request headers, is only included at trace level.

Her istemci için kullanılan günlük kategorisi, istemcinin adını içerir.The log category used for each client includes the name of the client. Örneğin, Mynamedclientadlı bir istemci, "System .net. http. HttpClient" kategorisine sahip iletileri günlüğe kaydeder. Mynamedclient. LogicalHandler ".A client named MyNamedClient, for example, logs messages with a category of "System.Net.Http.HttpClient.MyNamedClient.LogicalHandler". Logicalhandler ile düzeltilen iletiler istek işleyicisi ardışık düzeni dışında oluşur.Messages suffixed with LogicalHandler occur outside the request handler pipeline. İstekte, işlem hattındaki diğer işleyiciler işlenmeden önce iletiler günlüğe kaydedilir.On the request, messages are logged before any other handlers in the pipeline have processed it. Yanıtta, tüm diğer işlem hattı işleyicileri yanıtı aldıktan sonra iletiler günlüğe kaydedilir.On the response, messages are logged after any other pipeline handlers have received the response.

Günlüğe kaydetme, istek işleyicisi ardışık düzeni içinde de gerçekleşir.Logging also occurs inside the request handler pipeline. Mynamedclient örneğinde, bu Iletiler "System .net. http. HttpClient" günlük kategorisiyle günlüğe kaydedilir. Mynamedclient. ClientHandler ".In the MyNamedClient example, those messages are logged with the log category "System.Net.Http.HttpClient.MyNamedClient.ClientHandler". İstek için bu, tüm diğer işleyiciler çalıştırıldıktan sonra ve istek gönderilmeden hemen önce gerçekleşir.For the request, this occurs after all other handlers have run and immediately before the request is sent. Yanıtta, bu günlüğe kaydetme, işleyicinin işleyici işlem hattı üzerinden geri geçirmeden önce yanıtın durumunu içerir.On the response, this logging includes the state of the response before it passes back through the handler pipeline.

İşlem hattının dışında ve içinde günlüğe kaydetmenin etkinleştirilmesi, diğer işlem hattı işleyicileri tarafından yapılan değişikliklerin incelemesini etkinleştirir.Enabling logging outside and inside the pipeline enables inspection of the changes made by the other pipeline handlers. Bu, istek üst bilgilerinde veya yanıt durum kodunda yapılan değişiklikleri içerebilir.This may include changes to request headers or to the response status code.

İstemcinin adını log kategorisinde da içermek, belirli adlandırılmış istemciler için günlük filtrelemeyi sunar.Including the name of the client in the log category enables log filtering for specific named clients.

HttpMessageHandler 'ı yapılandırmaConfigure the HttpMessageHandler

İstemci tarafından kullanılan iç yapılandırmayı denetlemek gerekli olabilir HttpMessageHandler .It may be necessary to control the configuration of the inner HttpMessageHandler used by a client.

IHttpClientBuilderAdlandırılmış veya yazılan istemciler eklenirken bir döndürülür.An IHttpClientBuilder is returned when adding named or typed clients. ConfigurePrimaryHttpMessageHandlerGenişletme yöntemi bir temsilciyi tanımlamak için kullanılabilir.The ConfigurePrimaryHttpMessageHandler extension method can be used to define a delegate. Temsilci, HttpMessageHandler Bu istemci tarafından kullanılan birincili oluşturmak ve yapılandırmak için kullanılır:The delegate is used to create and configure the primary HttpMessageHandler used by that client:

public void ConfigureServices(IServiceCollection services)
{            
    services.AddHttpClient("configured-inner-handler")
        .ConfigurePrimaryHttpMessageHandler(() =>
        {
            return new HttpClientHandler()
            {
                AllowAutoRedirect = false,
                UseDefaultCredentials = true
            };
        });

    // Remaining code deleted for brevity.

Konsol uygulamasında ıhttpclientfactory kullanmaUse IHttpClientFactory in a console app

Konsol uygulamasında, aşağıdaki paket başvurularını projeye ekleyin:In a console app, add the following package references to the project:

Aşağıdaki örnekte:In the following example:

  • IHttpClientFactory, genel konağın hizmet kapsayıcısına kaydedilir.IHttpClientFactory is registered in the Generic Host's service container.
  • MyServicehizmetinden bir istemci fabrikası örneği oluşturur HttpClient .MyService creates a client factory instance from the service, which is used to create an HttpClient. HttpClient, bir Web sayfasını almak için kullanılır.HttpClient is used to retrieve a webpage.
  • Mainhizmetin yöntemini yürütmek için bir kapsam oluşturur GetPage ve Web sayfası içeriğinin ilk 500 karakterini konsola yazar.Main creates a scope to execute the service's GetPage method and write the first 500 characters of the webpage content to the console.
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
class Program
{
    static async Task<int> Main(string[] args)
    {
        var builder = new HostBuilder()
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHttpClient();
                services.AddTransient<IMyService, MyService>();
            }).UseConsoleLifetime();

        var host = builder.Build();

        using (var serviceScope = host.Services.CreateScope())
        {
            var services = serviceScope.ServiceProvider;

            try
            {
                var myService = services.GetRequiredService<IMyService>();
                var pageContent = await myService.GetPage();

                Console.WriteLine(pageContent.Substring(0, 500));
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();

                logger.LogError(ex, "An error occurred.");
            }
        }

        return 0;
    }

    public interface IMyService
    {
        Task<string> GetPage();
    }

    public class MyService : IMyService
    {
        private readonly IHttpClientFactory _clientFactory;

        public MyService(IHttpClientFactory clientFactory)
        {
            _clientFactory = clientFactory;
        }

        public async Task<string> GetPage()
        {
            // Content from BBC One: Dr. Who website (©BBC)
            var request = new HttpRequestMessage(HttpMethod.Get,
                "https://www.bbc.co.uk/programmes/b006q2x0");
            var client = _clientFactory.CreateClient();
            var response = await client.SendAsync(request);

            if (response.IsSuccessStatusCode)
            {
                return await response.Content.ReadAsStringAsync();
            }
            else
            {
                return $"StatusCode: {response.StatusCode}";
            }
        }
    }
}

Üst bilgi yayma ara yazılımıHeader propagation middleware

Üst bilgi yayma, gelen istekten giden HTTP Istemci isteklerine HTTP üstbilgilerini yaymaya yönelik bir ASP.NET Core ara istemcindedir.Header propagation is an ASP.NET Core middleware to propagate HTTP headers from the incoming request to the outgoing HTTP Client requests. Üst bilgi yaymayı kullanmak için:To use header propagation:

  • Microsoft. AspNetCore. Headeryayma paketine başvurun.Reference the Microsoft.AspNetCore.HeaderPropagation package.

  • Ara yazılımı ve HttpClient içinde yapılandırın Startup :Configure the middleware and HttpClient in Startup:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
    
        services.AddHttpClient("MyForwardingClient").AddHeaderPropagation();
        services.AddHeaderPropagation(options =>
        {
            options.Headers.Add("X-TraceId");
        });
    }
    
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
    
        app.UseHttpsRedirection();
    
        app.UseHeaderPropagation();
    
        app.UseRouting();
    
        app.UseAuthorization();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
    
  • İstemci giden isteklerde yapılandırılan üst bilgileri içerir:The client includes the configured headers on outbound requests:

    var client = clientFactory.CreateClient("MyForwardingClient");
    var response = client.GetAsync(...);
    

Ek kaynaklarAdditional resources

, Glenn CONDRON, Ryan şimdi eve Steve GordonBy Glenn Condron, Ryan Nowak, and Steve Gordon

Bir IHttpClientFactory uygulamadaki örnekleri yapılandırmak ve oluşturmak için kayıt yapılabilir ve kullanılabilir HttpClient .An IHttpClientFactory can be registered and used to configure and create HttpClient instances in an app. Aşağıdaki avantajları sunar:It offers the following benefits:

  • , Mantıksal örnekleri adlandırmak ve yapılandırmak için merkezi bir konum sağlar HttpClient .Provides a central location for naming and configuring logical HttpClient instances. Örneğin, GitHub istemcisi kayıtlı ve GitHub'a erişebilecek şekilde yapılandırılabilir.For example, a github client can be registered and configured to access GitHub. Varsayılan istemci, diğer amaçlar için kaydedilebilir.A default client can be registered for other purposes.
  • ' De işleyiciler için temsilci atama ile giden ara yazılım kavramı HttpClient ve bundan faydalanmak için, Polly tabanlı ara yazılım için uzantılar sağlar.Codifies the concept of outgoing middleware via delegating handlers in HttpClient and provides extensions for Polly-based middleware to take advantage of that.
  • HttpClientMessageHandlerYaşam sürelerini el ile yönetirken gerçekleşen YAYGıN DNS sorunlarından kaçınmak için temeldeki örneklerin biriktirmesini ve ömrünü yönetir HttpClient .Manages the pooling and lifetime of underlying HttpClientMessageHandler instances to avoid common DNS problems that occur when manually managing HttpClient lifetimes.
  • ILoggerFabrika tarafından oluşturulan istemciler aracılığıyla gönderilen tüm istekler için yapılandırılabilir bir günlüğe kaydetme deneyimi ekler (aracılığıyla).Adds a configurable logging experience (via ILogger) for all requests sent through clients created by the factory.

Örnek kodu görüntüleme veya indirme (nasıl indirileceği)View or download sample code (how to download)

Tüketim desenleriConsumption patterns

Bir uygulamada çeşitli yollar IHttpClientFactory kullanılabilir:There are several ways IHttpClientFactory can be used in an app:

Hiçbiri diğerinden tamamen üst değildir.None of them are strictly superior to another. En iyi yaklaşım, uygulamanın kısıtlamalarına bağlıdır.The best approach depends upon the app's constraints.

Temel kullanımBasic usage

, IHttpClientFactory AddHttpClient Yöntemi içindeki içindeki genişletme yöntemi çağırarak kaydedilebilir IServiceCollection Startup.ConfigureServices .The IHttpClientFactory can be registered by calling the AddHttpClient extension method on the IServiceCollection, inside the Startup.ConfigureServices method.

services.AddHttpClient();

Kaydedildikten sonra kod, IHttpClientFactory bağımlılık ekleme (dı)ile her yerden bir hizmeti kabul edebilir.Once registered, code can accept an IHttpClientFactory anywhere services can be injected with dependency injection (DI). IHttpClientFactoryBir örnek oluşturmak için kullanılabilir HttpClient :The IHttpClientFactory can be used to create an HttpClient instance:

public class BasicUsageModel : PageModel
{
    private readonly IHttpClientFactory _clientFactory;

    public IEnumerable<GitHubBranch> Branches { get; private set; }

    public bool GetBranchesError { get; private set; }

    public BasicUsageModel(IHttpClientFactory clientFactory)
    {
        _clientFactory = clientFactory;
    }

    public async Task OnGet()
    {
        var request = new HttpRequestMessage(HttpMethod.Get, 
            "https://api.github.com/repos/aspnet/AspNetCore.Docs/branches");
        request.Headers.Add("Accept", "application/vnd.github.v3+json");
        request.Headers.Add("User-Agent", "HttpClientFactory-Sample");

        var client = _clientFactory.CreateClient();

        var response = await client.SendAsync(request);

        if (response.IsSuccessStatusCode)
        {
            Branches = await response.Content
                .ReadAsAsync<IEnumerable<GitHubBranch>>();
        }
        else
        {
            GetBranchesError = true;
            Branches = Array.Empty<GitHubBranch>();
        }                               
    }
}

IHttpClientFactoryBu biçimde kullanmak, mevcut bir uygulamayı yeniden düzenleme için iyi bir yoldur.Using IHttpClientFactory in this fashion is a good way to refactor an existing app. Kullanım şekli üzerinde hiçbir etkisi yoktur HttpClient .It has no impact on the way HttpClient is used. HttpClientÖrneklerin Şu anda oluşturulduğu yerlerde, bu tekrarlamaları ' a çağrı ile değiştirin CreateClient .In places where HttpClient instances are currently created, replace those occurrences with a call to CreateClient.

Adlandırılmış istemcilerNamed clients

Bir uygulama HttpClient , her biri farklı bir yapılandırmaya sahip birçok farklı kullanım gerektiriyorsa, adlandırılmış istemcilerkullanılır.If an app requires many distinct uses of HttpClient, each with a different configuration, an option is to use named clients. Adlandırılmış için yapılandırma HttpClient , içinde kayıt sırasında belirtilebilir Startup.ConfigureServices .Configuration for a named HttpClient can be specified during registration in Startup.ConfigureServices.

services.AddHttpClient("github", c =>
{
    c.BaseAddress = new Uri("https://api.github.com/");
    // Github API versioning
    c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
    // Github requires a user-agent
    c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
});

Yukarıdaki kodda, AddHttpClient GitHubadının sağlanması denir.In the preceding code, AddHttpClient is called, providing the name github. Bu istemci, — GITHUB API 'siyle birlikte çalışmak için gerekli olan temel adres ve iki üst bilgi olan bazı varsayılan yapılandırma uygulanmış.This client has some default configuration applied—namely the base address and two headers required to work with the GitHub API.

Her seferinde her CreateClient çağrıldığında yeni bir örneği HttpClient oluşturulur ve yapılandırma eylemi çağrılır.Each time CreateClient is called, a new instance of HttpClient is created and the configuration action is called.

Adlandırılmış bir istemciyi kullanmak için, bir dize parametresi iletilebilir CreateClient .To consume a named client, a string parameter can be passed to CreateClient. Oluşturulacak istemcinin adını belirtin:Specify the name of the client to be created:

public class NamedClientModel : PageModel
{
    private readonly IHttpClientFactory _clientFactory;

    public IEnumerable<GitHubPullRequest> PullRequests { get; private set; }

    public bool GetPullRequestsError { get; private set; }

    public bool HasPullRequests => PullRequests.Any();

    public NamedClientModel(IHttpClientFactory clientFactory)
    {
        _clientFactory = clientFactory;
    }

    public async Task OnGet()
    {
        var request = new HttpRequestMessage(HttpMethod.Get, 
            "repos/aspnet/AspNetCore.Docs/pulls");

        var client = _clientFactory.CreateClient("github");

        var response = await client.SendAsync(request);

        if (response.IsSuccessStatusCode)
        {
            PullRequests = await response.Content
                .ReadAsAsync<IEnumerable<GitHubPullRequest>>();
        }
        else
        {
            GetPullRequestsError = true;
            PullRequests = Array.Empty<GitHubPullRequest>();
        }
    }
}

Yukarıdaki kodda, isteğin bir ana bilgisayar adı belirtmesi gerekmez.In the preceding code, the request doesn't need to specify a hostname. İstemci için yapılandırılan taban adresi kullanıldığından, bu yalnızca yolu geçirebilir.It can pass just the path, since the base address configured for the client is used.

Yazılan istemcilerTyped clients

Yazılan istemciler:Typed clients:

  • Dizeleri anahtar olarak kullanma gereksinimi olmadan, adlandırılmış istemcilerle aynı özellikleri sağlayın.Provide the same capabilities as named clients without the need to use strings as keys.
  • İstemcileri tükettiren IntelliSense ve derleyici yardımı sağlar.Provides IntelliSense and compiler help when consuming clients.
  • Yapılandırmak ve belirli bir ile etkileşimde bulunmak için tek bir konum belirtin HttpClient .Provide a single location to configure and interact with a particular HttpClient. Örneğin, tek bir arka uç uç noktası için tek bir adet yazılmış istemci kullanılabilir ve bu uç nokta ile ilgili tüm mantığı kapsüllenebilir.For example, a single typed client might be used for a single backend endpoint and encapsulate all logic dealing with that endpoint.
  • DI ile birlikte çalışın ve uygulamanızda gerektiğinde eklenebilir.Work with DI and can be injected where required in your app.

Türü belirtilmiş istemci HttpClient , oluşturucusunda bir parametreyi kabul eder:A typed client accepts an HttpClient parameter in its constructor:

public class GitHubService
{
    public HttpClient Client { get; }

    public GitHubService(HttpClient client)
    {
        client.BaseAddress = new Uri("https://api.github.com/");
        // GitHub API versioning
        client.DefaultRequestHeaders.Add("Accept", 
            "application/vnd.github.v3+json");
        // GitHub requires a user-agent
        client.DefaultRequestHeaders.Add("User-Agent", 
            "HttpClientFactory-Sample");

        Client = client;
    }

    public async Task<IEnumerable<GitHubIssue>> GetAspNetDocsIssues()
    {
        var response = await Client.GetAsync(
            "/repos/aspnet/AspNetCore.Docs/issues?state=open&sort=created&direction=desc");

        response.EnsureSuccessStatusCode();

        var result = await response.Content
            .ReadAsAsync<IEnumerable<GitHubIssue>>();

        return result;
    }
}

Önceki kodda, yapılandırma yazılan istemciye taşınır.In the preceding code, the configuration is moved into the typed client. HttpClientNesne bir ortak özellik olarak sunulur.The HttpClient object is exposed as a public property. İşlevselliği kullanıma sunan API 'ye özel yöntemler tanımlamak mümkündür HttpClient .It's possible to define API-specific methods that expose HttpClient functionality. GetAspNetDocsIssuesYöntemi, GitHub deposundan en son açık sorunları sorgulamak ve ayrıştırmak için gereken kodu saklar.The GetAspNetDocsIssues method encapsulates the code needed to query for and parse out the latest open issues from a GitHub repository.

Türü belirtilmiş bir istemciyi kaydettirmek için, genel AddHttpClient genişletme yöntemi içinde kullanılabilir Startup.ConfigureServices istemci sınıfını belirterek kullanılabilir:To register a typed client, the generic AddHttpClient extension method can be used within Startup.ConfigureServices, specifying the typed client class:

services.AddHttpClient<GitHubService>();

Yazılan istemci, DI ile geçici olarak kaydedilir.The typed client is registered as transient with DI. Yazılan istemci doğrudan eklenebilir ve tüketilebilir:The typed client can be injected and consumed directly:

public class TypedClientModel : PageModel
{
    private readonly GitHubService _gitHubService;

    public IEnumerable<GitHubIssue> LatestIssues { get; private set; }

    public bool HasIssue => LatestIssues.Any();

    public bool GetIssuesError { get; private set; }

    public TypedClientModel(GitHubService gitHubService)
    {
        _gitHubService = gitHubService;
    }

    public async Task OnGet()
    {
        try
        {
            LatestIssues = await _gitHubService.GetAspNetDocsIssues();
        }
        catch(HttpRequestException)
        {
            GetIssuesError = true;
            LatestIssues = Array.Empty<GitHubIssue>();
        }
    }
}

Tercih edilirse, yazılan istemcinin yapılandırması, Startup.ConfigureServices türü belirlenmiş istemcinin Oluşturucusu yerine kayıt sırasında belirtilebilir:If preferred, the configuration for a typed client can be specified during registration in Startup.ConfigureServices, rather than in the typed client's constructor:

services.AddHttpClient<RepoService>(c =>
{
    c.BaseAddress = new Uri("https://api.github.com/");
    c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
    c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
});

HttpClientTürü belirtilmiş bir istemci içinde tamamen kapsüllenebilir.It's possible to entirely encapsulate the HttpClient within a typed client. Bunu bir özellik olarak göstermek yerine, örneği dahili olarak çağıran ortak Yöntemler sunulabilir HttpClient .Rather than exposing it as a property, public methods can be provided which call the HttpClient instance internally.

public class RepoService
{
    // _httpClient isn't exposed publicly
    private readonly HttpClient _httpClient;

    public RepoService(HttpClient client)
    {
        _httpClient = client;
    }

    public async Task<IEnumerable<string>> GetRepos()
    {
        var response = await _httpClient.GetAsync("aspnet/repos");

        response.EnsureSuccessStatusCode();

        var result = await response.Content
            .ReadAsAsync<IEnumerable<string>>();

        return result;
    }
}

Önceki kodda, HttpClient bir özel alan olarak depolanır.In the preceding code, the HttpClient is stored as a private field. Dış çağrıları yapmak için tüm erişim GetRepos yönteminden geçer.All access to make external calls goes through the GetRepos method.

Oluşturulan istemcilerGenerated clients

IHttpClientFactory, yeniden sığdırmagibi diğer üçüncü taraf kitaplıklarıyla birlikte kullanılabilir.IHttpClientFactory can be used in combination with other third-party libraries such as Refit. Yeniden sığdırma, .NET için bir REST kitaplığıdır.Refit is a REST library for .NET. REST API 'Leri canlı arabirimlere dönüştürür.It converts REST APIs into live interfaces. Arabirim bir uygulama, RestService HttpClient dış http çağrıları yapmak için kullanılarak tarafından dinamik olarak oluşturulur.An implementation of the interface is generated dynamically by the RestService, using HttpClient to make the external HTTP calls.

Bir arabirim ve yanıt, dış API 'yi ve yanıtını temsil edecek şekilde tanımlanır:An interface and a reply are defined to represent the external API and its response:

public interface IHelloClient
{
    [Get("/helloworld")]
    Task<Reply> GetMessageAsync();
}

public class Reply
{
    public string Message { get; set; }
}

Türü belirlenmiş bir istemci eklenebilir, uygulamayı oluşturmak için yeniden sığdırma kullanımı kullanılabilir:A typed client can be added, using Refit to generate the implementation:

public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient("hello", c =>
    {
        c.BaseAddress = new Uri("https://localhost:5001");
    })
    .AddTypedClient(c => Refit.RestService.For<IHelloClient>(c));

    services.AddMvc();
}

Tanımlı arabirim, gereken yerde, mak ve Refit tarafından sağlanmış uygulama ile kullanılabilir.The defined interface can be consumed where necessary, with the implementation provided by DI and Refit:

[ApiController]
public class ValuesController : ControllerBase
{
    private readonly IHelloClient _client;

    public ValuesController(IHelloClient client)
    {
        _client = client;
    }

    [HttpGet("/")]
    public async Task<ActionResult<Reply>> Index()
    {
        return await _client.GetMessageAsync();
    }
}

Giden istek ara yazılımıOutgoing request middleware

HttpClient, giden HTTP istekleri için birlikte bağlanabilen işleyicileri temsilci seçme kavramı zaten var.HttpClient already has the concept of delegating handlers that can be linked together for outgoing HTTP requests. , IHttpClientFactory Her bir adlandırılmış istemci için uygulanacak işleyicileri tanımlamanızı kolaylaştırır.The IHttpClientFactory makes it easy to define the handlers to apply for each named client. Bir giden istek ara yazılım işlem hattı oluşturmak için birden çok işleyicinin kaydını ve zincirlemeyi destekler.It supports registration and chaining of multiple handlers to build an outgoing request middleware pipeline. Bu işleyicilerin her biri, giden istekten önce ve sonra iş gerçekleştirebilir.Each of these handlers is able to perform work before and after the outgoing request. Bu düzen, ASP.NET Core gelen ara yazılım ardışık düzenine benzer.This pattern is similar to the inbound middleware pipeline in ASP.NET Core. Bu model, önbelleğe alma, hata işleme, serileştirme ve günlüğe kaydetme dahil olmak üzere HTTP istekleri etrafında çapraz kesme sorunlarını yönetmek için bir mekanizma sağlar.The pattern provides a mechanism to manage cross-cutting concerns around HTTP requests, including caching, error handling, serialization, and logging.

Bir işleyici oluşturmak için, öğesinden türeten bir sınıf tanımlayın DelegatingHandler .To create a handler, define a class deriving from DelegatingHandler. SendAsyncİsteği ardışık düzen içindeki bir sonraki işleyiciye geçirmeden önce kodu yürütmek için yöntemi geçersiz kılın:Override the SendAsync method to execute code before passing the request to the next handler in the pipeline:

public class ValidateHeaderHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        if (!request.Headers.Contains("X-API-KEY"))
        {
            return new HttpResponseMessage(HttpStatusCode.BadRequest)
            {
                Content = new StringContent(
                    "You must supply an API key header called X-API-KEY")
            };
        }

        return await base.SendAsync(request, cancellationToken);
    }
}

Yukarıdaki kod, temel bir işleyiciyi tanımlar.The preceding code defines a basic handler. İsteğe bağlı bir başlık olup olmadığını denetler X-API-KEY .It checks to see if an X-API-KEY header has been included on the request. Üst bilgi eksikse, HTTP çağrısından kaçınabilir ve uygun bir yanıt döndürebilir.If the header is missing, it can avoid the HTTP call and return a suitable response.

Kayıt sırasında, bir veya daha fazla işleyici bir için yapılandırmasına eklenebilir HttpClient .During registration, one or more handlers can be added to the configuration for an HttpClient. Bu görev, üzerindeki genişletme yöntemleri aracılığıyla gerçekleştirilir IHttpClientBuilder .This task is accomplished via extension methods on the IHttpClientBuilder.

services.AddTransient<ValidateHeaderHandler>();

services.AddHttpClient("externalservice", c =>
{
    // Assume this is an "external" service which requires an API KEY
    c.BaseAddress = new Uri("https://localhost:5000/");
})
.AddHttpMessageHandler<ValidateHeaderHandler>();

Yukarıdaki kodda,, ValidateHeaderHandler dı ile kaydedilir.In the preceding code, the ValidateHeaderHandler is registered with DI. IHttpClientFactoryHer işleyici için ayrı bır dı kapsamı oluşturur.The IHttpClientFactory creates a separate DI scope for each handler. İşleyiciler herhangi bir kapsamın hizmetlerine bağlı olarak ücretsizdir.Handlers are free to depend upon services of any scope. İşleyicilerin bağımlı olduğu hizmetler, işleyicinin elden çıkarılmasıyla kaldırılır.Services that handlers depend upon are disposed when the handler is disposed.

Kaydedildikten sonra, AddHttpMessageHandler işleyicinin türü geçirerek, çağrılabilir.Once registered, AddHttpMessageHandler can be called, passing in the type for the handler.

Birden çok işleyici, yürütülmesi gereken sırayla kaydedilebilir.Multiple handlers can be registered in the order that they should execute. Her işleyici, son isteği çalıştırana kadar sonraki işleyiciyi sarmalar HttpClientHandler :Each handler wraps the next handler until the final HttpClientHandler executes the request:

services.AddTransient<SecureRequestHandler>();
services.AddTransient<RequestDataHandler>();

services.AddHttpClient("clientwithhandlers")
    // This handler is on the outside and called first during the 
    // request, last during the response.
    .AddHttpMessageHandler<SecureRequestHandler>()
    // This handler is on the inside, closest to the request being 
    // sent.
    .AddHttpMessageHandler<RequestDataHandler>();

İleti işleyicileriyle istek başına durumu paylaşmak için aşağıdaki yaklaşımlardan birini kullanın:Use one of the following approaches to share per-request state with message handlers:

  • Kullanarak işleyicide veri geçirin HttpRequestMessage.Properties .Pass data into the handler using HttpRequestMessage.Properties.
  • IHttpContextAccessorGeçerli isteğe erişmek için kullanın.Use IHttpContextAccessor to access the current request.
  • AsyncLocalVerileri geçirmek için özel bir depolama nesnesi oluşturun.Create a custom AsyncLocal storage object to pass the data.

Polly tabanlı işleyiciler kullanınUse Polly-based handlers

IHttpClientFactory, Pollyadlı popüler bir üçüncü taraf kitaplığı ile tümleşir.IHttpClientFactory integrates with a popular third-party library called Polly. Polly, .NET için kapsamlı bir esnekliği ve geçici hata işleme kitaplığıdır.Polly is a comprehensive resilience and transient fault-handling library for .NET. Geliştiricilerin yeniden deneme, devre kesici, zaman aşımı, Bulkbaş yalıtımı, akıcı ve iş parçacığı açısından güvenli bir şekilde geri dönüş gibi ilkeler almasına olanak tanır.It allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner.

Uzantı yöntemleri, yapılandırılmış örneklerle Polly ilkelerin kullanımını etkinleştirmek için sağlanır HttpClient .Extension methods are provided to enable the use of Polly policies with configured HttpClient instances. Polly uzantıları:The Polly extensions:

  • İstemcilere Polly tabanlı işleyiciler eklemeyi destekler.Support adding Polly-based handlers to clients.
  • , Microsoft. Extensions. http. Polly NuGet paketini yükledikten sonra kullanılabilir.Can be used after installing the Microsoft.Extensions.Http.Polly NuGet package. Paket, ASP.NET Core paylaşılan çerçevesine dahil değildir.The package isn't included in the ASP.NET Core shared framework.

Geçici hataları işleHandle transient faults

Yaygın hatalar, dış HTTP çağrıları geçici olduğunda oluşur.Most common faults occur when external HTTP calls are transient. AddTransientHttpErrorPolicyGeçici hataları işlemek üzere bir ilkenin tanımlanmasını sağlayan, çağrılan bir uygun genişletme yöntemi eklenmiştir.A convenient extension method called AddTransientHttpErrorPolicy is included which allows a policy to be defined to handle transient errors. Bu uzantı yöntemi tanıtıcısıyla yapılandırılmış ilkeler HttpRequestException , http 5xx yanıtları ve http 408 yanıtları.Policies configured with this extension method handle HttpRequestException, HTTP 5xx responses, and HTTP 408 responses.

AddTransientHttpErrorPolicyUzantı içinde kullanılabilir Startup.ConfigureServices .The AddTransientHttpErrorPolicy extension can be used within Startup.ConfigureServices. Uzantı, PolicyBuilder olası bir geçici hatayı temsil eden hataları işlemek için yapılandırılmış bir nesneye erişim sağlar:The extension provides access to a PolicyBuilder object configured to handle errors representing a possible transient fault:

services.AddHttpClient<UnreliableEndpointCallerService>()
    .AddTransientHttpErrorPolicy(p => 
        p.WaitAndRetryAsync(3, _ => TimeSpan.FromMilliseconds(600)));

Yukarıdaki kodda bir WaitAndRetryAsync ilke tanımlanmıştır.In the preceding code, a WaitAndRetryAsync policy is defined. Başarısız istekler, denemeler arasındaki 600 MS gecikmeyle en fazla üç kez yeniden denenir.Failed requests are retried up to three times with a delay of 600 ms between attempts.

Dinamik olarak ilke seçmeDynamically select policies

Polly tabanlı işleyiciler eklemek için kullanılabilecek ek uzantı yöntemleri vardır.Additional extension methods exist which can be used to add Polly-based handlers. Bu tür bir uzantının AddPolicyHandler birden çok aşırı yüklemesi vardır.One such extension is AddPolicyHandler, which has multiple overloads. Bir aşırı yükleme, hangi ilkenin uygulanacağını tanımlarken isteğin incelenebilirliğini sağlar:One overload allows the request to be inspected when defining which policy to apply:

var timeout = Policy.TimeoutAsync<HttpResponseMessage>(
    TimeSpan.FromSeconds(10));
var longTimeout = Policy.TimeoutAsync<HttpResponseMessage>(
    TimeSpan.FromSeconds(30));

services.AddHttpClient("conditionalpolicy")
// Run some code to select a policy based on the request
    .AddPolicyHandler(request => 
        request.Method == HttpMethod.Get ? timeout : longTimeout);

Yukarıdaki kodda, giden istek bir HTTP GET ise, 10 saniyelik bir zaman aşımı uygulanır.In the preceding code, if the outgoing request is an HTTP GET, a 10-second timeout is applied. Diğer HTTP yöntemleri için, 30 saniyelik bir zaman aşımı kullanılır.For any other HTTP method, a 30-second timeout is used.

Birden çok Polly işleyici eklemeAdd multiple Polly handlers

Gelişmiş işlevsellik sağlamak için çok fazla ilke iç içe geçmiş bir yaygın hale gelir:It's common to nest Polly policies to provide enhanced functionality:

services.AddHttpClient("multiplepolicies")
    .AddTransientHttpErrorPolicy(p => p.RetryAsync(3))
    .AddTransientHttpErrorPolicy(
        p => p.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));

Yukarıdaki örnekte, iki işleyici eklenmiştir.In the preceding example, two handlers are added. İlki, AddTransientHttpErrorPolicy yeniden deneme ilkesi eklemek için uzantıyı kullanır.The first uses the AddTransientHttpErrorPolicy extension to add a retry policy. Başarısız istekler en fazla üç kez yeniden denenir.Failed requests are retried up to three times. İçin ikinci çağrı, AddTransientHttpErrorPolicy bir devre kesici ilkesi ekler.The second call to AddTransientHttpErrorPolicy adds a circuit breaker policy. Beş başarısız girişim sırayla gerçekleşiyorsa, daha fazla dış istek 30 saniye için engellenir.Further external requests are blocked for 30 seconds if five failed attempts occur sequentially. Devre kesici ilkeleri durum bilgisi vardır.Circuit breaker policies are stateful. Bu istemci aracılığıyla yapılan tüm çağrılar aynı devre durumunu paylaşır.All calls through this client share the same circuit state.

Polly kayıt defterinden ilke eklemeAdd policies from the Polly registry

Düzenli olarak kullanılan ilkeleri yönetmeye yönelik bir yaklaşım, bunları bir kez tanımlayıp bir ile kaydetmektir PolicyRegistry .An approach to managing regularly used policies is to define them once and register them with a PolicyRegistry. Kayıt defterinden bir ilke kullanılarak bir işleyicinin eklenmesine izin veren bir genişletme yöntemi sağlanır:An extension method is provided which allows a handler to be added using a policy from the registry:

var registry = services.AddPolicyRegistry();

registry.Add("regular", timeout);
registry.Add("long", longTimeout);

services.AddHttpClient("regulartimeouthandler")
    .AddPolicyHandlerFromRegistry("regular");

Yukarıdaki kodda, öğesine eklendiğinde iki ilke kaydedilir PolicyRegistry ServiceCollection .In the preceding code, two policies are registered when the PolicyRegistry is added to the ServiceCollection. Kayıt defterinden bir ilke kullanmak için AddPolicyHandlerFromRegistry yöntemi kullanılır ve uygulanacak ilke adı geçer.To use a policy from the registry, the AddPolicyHandlerFromRegistry method is used, passing the name of the policy to apply.

Ve daha fazla tümleştirme hakkında daha fazla bilgi IHttpClientFactory , Polly wiki' de bulunabilir.Further information about IHttpClientFactory and Polly integrations can be found on the Polly wiki.

HttpClient ve ömür yönetimiHttpClient and lifetime management

HttpClientHer çağrıldığında yeni bir örnek döndürülür CreateClient IHttpClientFactory .A new HttpClient instance is returned each time CreateClient is called on the IHttpClientFactory. HttpMessageHandlerAdlandırılmış istemci başına.There's an HttpMessageHandler per named client. Fabrika, örneklerin yaşam sürelerini yönetir HttpMessageHandler .The factory manages the lifetimes of the HttpMessageHandler instances.

IHttpClientFactory``HttpMessageHandlerkaynak tüketimini azaltmak için fabrika tarafından oluşturulan örnekleri havuzlar.IHttpClientFactory pools the HttpMessageHandler instances created by the factory to reduce resource consumption. Bir HttpMessageHandler örnek, süresi dolmamışsa yeni bir örnek oluştururken havuzdan yeniden kullanılabilir HttpClient .An HttpMessageHandler instance may be reused from the pool when creating a new HttpClient instance if its lifetime hasn't expired.

Her işleyici genellikle kendi temel HTTP bağlantılarını yönettiğinden, işleyicilerin havuzlaması tercih edilir.Pooling of handlers is desirable as each handler typically manages its own underlying HTTP connections. Gerekenden daha fazla işleyici oluşturulması bağlantı gecikmeleri oluşmasına neden olabilir.Creating more handlers than necessary can result in connection delays. Ayrıca, bazı işleyiciler bağlantıları süresiz olarak açık tutar, bu da işleyicinin DNS değişikliklerine yeniden davranmasını engelleyebilir.Some handlers also keep connections open indefinitely, which can prevent the handler from reacting to DNS changes.

Varsayılan işleyici ömrü iki dakikadır.The default handler lifetime is two minutes. Varsayılan değer, adlandırılmış istemci temelinde geçersiz kılınabilir.The default value can be overridden on a per named client basis. Bunu geçersiz kılmak için, SetHandlerLifetime IHttpClientBuilder istemcisini oluştururken döndürülen öğesini çağırın:To override it, call SetHandlerLifetime on the IHttpClientBuilder that is returned when creating the client:

services.AddHttpClient("extendedhandlerlifetime")
    .SetHandlerLifetime(TimeSpan.FromMinutes(5));

İstemcinin çıkarılması gerekli değildir.Disposal of the client isn't required. Çıkarma giden istekleri iptal eder ve HttpClient çağırma sonrasında verilen örneğin kullanılamaz olmasını sağlar Dispose .Disposal cancels outgoing requests and guarantees the given HttpClient instance can't be used after calling Dispose. IHttpClientFactoryörnekler tarafından kullanılan kaynakları izler ve ortadan kaldırdık HttpClient .IHttpClientFactory tracks and disposes resources used by HttpClient instances. HttpClientÖrnekler genellikle aktiften çıkarma gerektirmeyen .NET nesneleri olarak kabul edilebilir.The HttpClient instances can generally be treated as .NET objects not requiring disposal.

Tek HttpClient bir örneğinin uzun süre canlı tutulması, önünde kullanılmadan önce kullanılan ortak bir modeldir IHttpClientFactory .Keeping a single HttpClient instance alive for a long duration is a common pattern used before the inception of IHttpClientFactory. Bu model, ' a geçtikten sonra gereksiz hale gelir IHttpClientFactory .This pattern becomes unnecessary after migrating to IHttpClientFactory.

Ihttpclientfactory alternatifleriAlternatives to IHttpClientFactory

IHttpClientFactoryDı etkin bir uygulamada kullanmak şunları önler:Using IHttpClientFactory in a DI-enabled app avoids:

  • Havuz örneklerine göre kaynak tükenmesi sorunları HttpMessageHandler .Resource exhaustion problems by pooling HttpMessageHandler instances.
  • Düzenli aralıklarla örnekleri geçirerek eski DNS sorunları HttpMessageHandler .Stale DNS problems by cycling HttpMessageHandler instances at regular intervals.

Uzun süreli bir örnek kullanarak önceki sorunları çözmenin alternatif yolları vardır SocketsHttpHandler .There are alternative ways to solve the preceding problems using a long-lived SocketsHttpHandler instance.

  • SocketsHttpHandlerUygulamanın başladığı zaman bir örneği oluşturun ve uygulamanın ömrü boyunca kullanın.Create an instance of SocketsHttpHandler when the app starts and use it for the life of the app.
  • PooledConnectionLifetimeDNS yenileme süreleri temelinde uygun bir değere yapılandırın.Configure PooledConnectionLifetime to an appropriate value based on DNS refresh times.
  • HttpClientGerektiğinde örnek oluşturun new HttpClient(handler, disposeHandler: false) .Create HttpClient instances using new HttpClient(handler, disposeHandler: false) as needed.

Yukarıdaki yaklaşımlar, IHttpClientFactory benzer bir şekilde çözen kaynak yönetimi sorunlarını çözer.The preceding approaches solve the resource management problems that IHttpClientFactory solves in a similar way.

  • , SocketsHttpHandler Örnekleri arasında bağlantıları paylaşır HttpClient .The SocketsHttpHandler shares connections across HttpClient instances. Bu paylaşım, yuva azalmasına engel olur.This sharing prevents socket exhaustion.
  • SocketsHttpHandlerBağlantıları, PooledConnectionLifetime eski DNS sorunlarından kaçınmak için öğesine göre döngüler.The SocketsHttpHandler cycles connections according to PooledConnectionLifetime to avoid stale DNS problems.

Tanımlama bilgileriCookies

Havuza alınmış HttpMessageHandler örnekler, CookieContainer paylaşılan nesneler ile sonuçlanır.The pooled HttpMessageHandler instances results in CookieContainer objects being shared. Beklenmeyen CookieContainer nesne paylaşımı genellikle hatalı kodla sonuçlanır.Unanticipated CookieContainer object sharing often results in incorrect code. Tanımlama bilgileri gerektiren uygulamalar için şunlardan birini göz önünde bulundurun:For apps that require cookies, consider either:

  • Otomatik tanımlama bilgisi işlemeyi devre dışı bırakmaDisabling automatic cookie handling
  • ÖnlemeninIHttpClientFactoryAvoiding IHttpClientFactory

ConfigurePrimaryHttpMessageHandlerOtomatik tanımlama bilgisi işlemesini devre dışı bırakmak için çağırın:Call ConfigurePrimaryHttpMessageHandler to disable automatic cookie handling:

services.AddHttpClient("configured-disable-automatic-cookies")
    .ConfigurePrimaryHttpMessageHandler(() =>
    {
        return new SocketsHttpHandler()
        {
            UseCookies = false,
        };
    });

Günlüğe KaydetmeLogging

IHttpClientFactoryTüm istekler için kayıt günlüğü iletileri aracılığıyla oluşturulan istemciler.Clients created via IHttpClientFactory record log messages for all requests. Varsayılan günlük iletilerini görmek için günlük yapılandırmanızda uygun bilgi düzeyini etkinleştirin.Enable the appropriate information level in your logging configuration to see the default log messages. İstek üst bilgilerinin günlüğe kaydedilmesi gibi ek Günlükler yalnızca izleme düzeyinde yer alır.Additional logging, such as the logging of request headers, is only included at trace level.

Her istemci için kullanılan günlük kategorisi, istemcinin adını içerir.The log category used for each client includes the name of the client. Örneğin, Mynamedclientadlı bir istemci, bir kategorisine sahip iletileri günlüğe kaydeder System.Net.Http.HttpClient.MyNamedClient.LogicalHandler .A client named MyNamedClient, for example, logs messages with a category of System.Net.Http.HttpClient.MyNamedClient.LogicalHandler. Logicalhandler ile düzeltilen iletiler istek işleyicisi ardışık düzeni dışında oluşur.Messages suffixed with LogicalHandler occur outside the request handler pipeline. İstekte, işlem hattındaki diğer işleyiciler işlenmeden önce iletiler günlüğe kaydedilir.On the request, messages are logged before any other handlers in the pipeline have processed it. Yanıtta, tüm diğer işlem hattı işleyicileri yanıtı aldıktan sonra iletiler günlüğe kaydedilir.On the response, messages are logged after any other pipeline handlers have received the response.

Günlüğe kaydetme, istek işleyicisi ardışık düzeni içinde de gerçekleşir.Logging also occurs inside the request handler pipeline. Mynamedclient örneğinde, bu iletiler günlük kategorisine göre günlüğe kaydedilir System.Net.Http.HttpClient.MyNamedClient.ClientHandler .In the MyNamedClient example, those messages are logged against the log category System.Net.Http.HttpClient.MyNamedClient.ClientHandler. İstek için bu, tüm diğer işleyiciler çalıştıktan sonra ve istek ağda gönderilmeden hemen önce gerçekleşir.For the request, this occurs after all other handlers have run and immediately before the request is sent out on the network. Yanıtta, bu günlüğe kaydetme, işleyicinin işleyici işlem hattı üzerinden geri geçirmeden önce yanıtın durumunu içerir.On the response, this logging includes the state of the response before it passes back through the handler pipeline.

İşlem hattının dışında ve içinde günlüğe kaydetmenin etkinleştirilmesi, diğer işlem hattı işleyicileri tarafından yapılan değişikliklerin incelemesini etkinleştirir.Enabling logging outside and inside the pipeline enables inspection of the changes made by the other pipeline handlers. Bu, örneğin veya yanıt durum kodunda istek başlıklarındaki değişiklikleri içerebilir.This may include changes to request headers, for example, or to the response status code.

İstemci adı ' nı log kategorisinde da içermek, gerektiğinde belirli adlandırılmış istemciler için günlük filtrelemeyi sunar.Including the name of the client in the log category enables log filtering for specific named clients where necessary.

HttpMessageHandler 'ı yapılandırmaConfigure the HttpMessageHandler

İstemci tarafından kullanılan iç yapılandırmayı denetlemek gerekli olabilir HttpMessageHandler .It may be necessary to control the configuration of the inner HttpMessageHandler used by a client.

IHttpClientBuilderAdlandırılmış veya yazılan istemciler eklenirken bir döndürülür.An IHttpClientBuilder is returned when adding named or typed clients. ConfigurePrimaryHttpMessageHandlerGenişletme yöntemi bir temsilciyi tanımlamak için kullanılabilir.The ConfigurePrimaryHttpMessageHandler extension method can be used to define a delegate. Temsilci, HttpMessageHandler Bu istemci tarafından kullanılan birincili oluşturmak ve yapılandırmak için kullanılır:The delegate is used to create and configure the primary HttpMessageHandler used by that client:

services.AddHttpClient("configured-inner-handler")
    .ConfigurePrimaryHttpMessageHandler(() =>
    {
        return new HttpClientHandler()
        {
            AllowAutoRedirect = false,
            UseDefaultCredentials = true
        };
    });

Konsol uygulamasında ıhttpclientfactory kullanmaUse IHttpClientFactory in a console app

Konsol uygulamasında, aşağıdaki paket başvurularını projeye ekleyin:In a console app, add the following package references to the project:

Aşağıdaki örnekte:In the following example:

  • IHttpClientFactory, genel konağın hizmet kapsayıcısına kaydedilir.IHttpClientFactory is registered in the Generic Host's service container.
  • MyServicehizmetinden bir istemci fabrikası örneği oluşturur HttpClient .MyService creates a client factory instance from the service, which is used to create an HttpClient. HttpClient, bir Web sayfasını almak için kullanılır.HttpClient is used to retrieve a webpage.
  • Mainhizmetin yöntemini yürütmek için bir kapsam oluşturur GetPage ve Web sayfası içeriğinin ilk 500 karakterini konsola yazar.Main creates a scope to execute the service's GetPage method and write the first 500 characters of the webpage content to the console.
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
class Program
{
    static async Task<int> Main(string[] args)
    {
        var builder = new HostBuilder()
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHttpClient();
                services.AddTransient<IMyService, MyService>();
            }).UseConsoleLifetime();

        var host = builder.Build();

        using (var serviceScope = host.Services.CreateScope())
        {
            var services = serviceScope.ServiceProvider;

            try
            {
                var myService = services.GetRequiredService<IMyService>();
                var pageContent = await myService.GetPage();

                Console.WriteLine(pageContent.Substring(0, 500));
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();

                logger.LogError(ex, "An error occurred.");
            }
        }

        return 0;
    }

    public interface IMyService
    {
        Task<string> GetPage();
    }

    public class MyService : IMyService
    {
        private readonly IHttpClientFactory _clientFactory;

        public MyService(IHttpClientFactory clientFactory)
        {
            _clientFactory = clientFactory;
        }

        public async Task<string> GetPage()
        {
            // Content from BBC One: Dr. Who website (©BBC)
            var request = new HttpRequestMessage(HttpMethod.Get,
                "https://www.bbc.co.uk/programmes/b006q2x0");
            var client = _clientFactory.CreateClient();
            var response = await client.SendAsync(request);

            if (response.IsSuccessStatusCode)
            {
                return await response.Content.ReadAsStringAsync();
            }
            else
            {
                return $"StatusCode: {response.StatusCode}";
            }
        }
    }
}

Ek kaynaklarAdditional resources

, Glenn CONDRON, Ryan şimdi eve Steve GordonBy Glenn Condron, Ryan Nowak, and Steve Gordon

Bir IHttpClientFactory uygulamadaki örnekleri yapılandırmak ve oluşturmak için kayıt yapılabilir ve kullanılabilir HttpClient .An IHttpClientFactory can be registered and used to configure and create HttpClient instances in an app. Aşağıdaki avantajları sunar:It offers the following benefits:

  • , Mantıksal örnekleri adlandırmak ve yapılandırmak için merkezi bir konum sağlar HttpClient .Provides a central location for naming and configuring logical HttpClient instances. Örneğin, GitHub istemcisi kayıtlı ve GitHub'a erişebilecek şekilde yapılandırılabilir.For example, a github client can be registered and configured to access GitHub. Varsayılan istemci, diğer amaçlar için kaydedilebilir.A default client can be registered for other purposes.
  • ' De işleyiciler için temsilci atama ile giden ara yazılım kavramı HttpClient ve bundan faydalanmak için, Polly tabanlı ara yazılım için uzantılar sağlar.Codifies the concept of outgoing middleware via delegating handlers in HttpClient and provides extensions for Polly-based middleware to take advantage of that.
  • HttpClientMessageHandlerYaşam sürelerini el ile yönetirken gerçekleşen YAYGıN DNS sorunlarından kaçınmak için temeldeki örneklerin biriktirmesini ve ömrünü yönetir HttpClient .Manages the pooling and lifetime of underlying HttpClientMessageHandler instances to avoid common DNS problems that occur when manually managing HttpClient lifetimes.
  • ILoggerFabrika tarafından oluşturulan istemciler aracılığıyla gönderilen tüm istekler için yapılandırılabilir bir günlüğe kaydetme deneyimi ekler (aracılığıyla).Adds a configurable logging experience (via ILogger) for all requests sent through clients created by the factory.

Örnek kodu görüntüleme veya indirme (nasıl indirileceği)View or download sample code (how to download)

ÖnkoşullarPrerequisites

.NET Framework hedefleyen projeler Microsoft. Extensions. http NuGet paketinin yüklenmesini gerektirir.Projects targeting .NET Framework require installation of the Microsoft.Extensions.Http NuGet package. .NET Core ile hedeflenen ve Microsoft. AspNetCore. app metapackage 'e başvuran projeler zaten paketi içeriyor Microsoft.Extensions.Http .Projects that target .NET Core and reference the Microsoft.AspNetCore.App metapackage already include the Microsoft.Extensions.Http package.

Tüketim desenleriConsumption patterns

Bir uygulamada çeşitli yollar IHttpClientFactory kullanılabilir:There are several ways IHttpClientFactory can be used in an app:

Hiçbiri diğerinden tamamen üst değildir.None of them are strictly superior to another. En iyi yaklaşım, uygulamanın kısıtlamalarına bağlıdır.The best approach depends upon the app's constraints.

Temel kullanımBasic usage

, IHttpClientFactory AddHttpClient Yöntemi içindeki içindeki genişletme yöntemi çağırarak kaydedilebilir IServiceCollection Startup.ConfigureServices .The IHttpClientFactory can be registered by calling the AddHttpClient extension method on the IServiceCollection, inside the Startup.ConfigureServices method.

services.AddHttpClient();

Kaydedildikten sonra kod, IHttpClientFactory bağımlılık ekleme (dı)ile her yerden bir hizmeti kabul edebilir.Once registered, code can accept an IHttpClientFactory anywhere services can be injected with dependency injection (DI). IHttpClientFactoryBir örnek oluşturmak için kullanılabilir HttpClient :The IHttpClientFactory can be used to create an HttpClient instance:

public class BasicUsageModel : PageModel
{
    private readonly IHttpClientFactory _clientFactory;

    public IEnumerable<GitHubBranch> Branches { get; private set; }

    public bool GetBranchesError { get; private set; }

    public BasicUsageModel(IHttpClientFactory clientFactory)
    {
        _clientFactory = clientFactory;
    }

    public async Task OnGet()
    {
        var request = new HttpRequestMessage(HttpMethod.Get, 
            "https://api.github.com/repos/aspnet/AspNetCore.Docs/branches");
        request.Headers.Add("Accept", "application/vnd.github.v3+json");
        request.Headers.Add("User-Agent", "HttpClientFactory-Sample");

        var client = _clientFactory.CreateClient();

        var response = await client.SendAsync(request);

        if (response.IsSuccessStatusCode)
        {
            Branches = await response.Content
                .ReadAsAsync<IEnumerable<GitHubBranch>>();
        }
        else
        {
            GetBranchesError = true;
            Branches = Array.Empty<GitHubBranch>();
        }                               
    }
}

IHttpClientFactoryBu biçimde kullanmak, mevcut bir uygulamayı yeniden düzenleme için iyi bir yoldur.Using IHttpClientFactory in this fashion is a good way to refactor an existing app. Kullanım şekli üzerinde hiçbir etkisi yoktur HttpClient .It has no impact on the way HttpClient is used. HttpClientÖrneklerin Şu anda oluşturulduğu yerlerde, bu tekrarlamaları ' a çağrı ile değiştirin CreateClient .In places where HttpClient instances are currently created, replace those occurrences with a call to CreateClient.

Adlandırılmış istemcilerNamed clients

Bir uygulama HttpClient , her biri farklı bir yapılandırmaya sahip birçok farklı kullanım gerektiriyorsa, adlandırılmış istemcilerkullanılır.If an app requires many distinct uses of HttpClient, each with a different configuration, an option is to use named clients. Adlandırılmış için yapılandırma HttpClient , içinde kayıt sırasında belirtilebilir Startup.ConfigureServices .Configuration for a named HttpClient can be specified during registration in Startup.ConfigureServices.

services.AddHttpClient("github", c =>
{
    c.BaseAddress = new Uri("https://api.github.com/");
    // Github API versioning
    c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
    // Github requires a user-agent
    c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
});

Yukarıdaki kodda, AddHttpClient GitHubadının sağlanması denir.In the preceding code, AddHttpClient is called, providing the name github. Bu istemci, — GITHUB API 'siyle birlikte çalışmak için gerekli olan temel adres ve iki üst bilgi olan bazı varsayılan yapılandırma uygulanmış.This client has some default configuration applied—namely the base address and two headers required to work with the GitHub API.

Her seferinde her CreateClient çağrıldığında yeni bir örneği HttpClient oluşturulur ve yapılandırma eylemi çağrılır.Each time CreateClient is called, a new instance of HttpClient is created and the configuration action is called.

Adlandırılmış bir istemciyi kullanmak için, bir dize parametresi iletilebilir CreateClient .To consume a named client, a string parameter can be passed to CreateClient. Oluşturulacak istemcinin adını belirtin:Specify the name of the client to be created:

public class NamedClientModel : PageModel
{
    private readonly IHttpClientFactory _clientFactory;

    public IEnumerable<GitHubPullRequest> PullRequests { get; private set; }

    public bool GetPullRequestsError { get; private set; }

    public bool HasPullRequests => PullRequests.Any();

    public NamedClientModel(IHttpClientFactory clientFactory)
    {
        _clientFactory = clientFactory;
    }

    public async Task OnGet()
    {
        var request = new HttpRequestMessage(HttpMethod.Get, 
            "repos/aspnet/AspNetCore.Docs/pulls");

        var client = _clientFactory.CreateClient("github");

        var response = await client.SendAsync(request);

        if (response.IsSuccessStatusCode)
        {
            PullRequests = await response.Content
                .ReadAsAsync<IEnumerable<GitHubPullRequest>>();
        }
        else
        {
            GetPullRequestsError = true;
            PullRequests = Array.Empty<GitHubPullRequest>();
        }
    }
}

Yukarıdaki kodda, isteğin bir ana bilgisayar adı belirtmesi gerekmez.In the preceding code, the request doesn't need to specify a hostname. İstemci için yapılandırılan taban adresi kullanıldığından, bu yalnızca yolu geçirebilir.It can pass just the path, since the base address configured for the client is used.

Yazılan istemcilerTyped clients

Yazılan istemciler:Typed clients:

  • Dizeleri anahtar olarak kullanma gereksinimi olmadan, adlandırılmış istemcilerle aynı özellikleri sağlayın.Provide the same capabilities as named clients without the need to use strings as keys.
  • İstemcileri tükettiren IntelliSense ve derleyici yardımı sağlar.Provides IntelliSense and compiler help when consuming clients.
  • Yapılandırmak ve belirli bir ile etkileşimde bulunmak için tek bir konum belirtin HttpClient .Provide a single location to configure and interact with a particular HttpClient. Örneğin, tek bir arka uç uç noktası için tek bir adet yazılmış istemci kullanılabilir ve bu uç nokta ile ilgili tüm mantığı kapsüllenebilir.For example, a single typed client might be used for a single backend endpoint and encapsulate all logic dealing with that endpoint.
  • DI ile birlikte çalışın ve uygulamanızda gerektiğinde eklenebilir.Work with DI and can be injected where required in your app.

Türü belirtilmiş istemci HttpClient , oluşturucusunda bir parametreyi kabul eder:A typed client accepts an HttpClient parameter in its constructor:

public class GitHubService
{
    public HttpClient Client { get; }

    public GitHubService(HttpClient client)
    {
        client.BaseAddress = new Uri("https://api.github.com/");
        // GitHub API versioning
        client.DefaultRequestHeaders.Add("Accept", 
            "application/vnd.github.v3+json");
        // GitHub requires a user-agent
        client.DefaultRequestHeaders.Add("User-Agent", 
            "HttpClientFactory-Sample");

        Client = client;
    }

    public async Task<IEnumerable<GitHubIssue>> GetAspNetDocsIssues()
    {
        var response = await Client.GetAsync(
            "/repos/aspnet/AspNetCore.Docs/issues?state=open&sort=created&direction=desc");

        response.EnsureSuccessStatusCode();

        var result = await response.Content
            .ReadAsAsync<IEnumerable<GitHubIssue>>();

        return result;
    }
}

Önceki kodda, yapılandırma yazılan istemciye taşınır.In the preceding code, the configuration is moved into the typed client. HttpClientNesne bir ortak özellik olarak sunulur.The HttpClient object is exposed as a public property. İşlevselliği kullanıma sunan API 'ye özel yöntemler tanımlamak mümkündür HttpClient .It's possible to define API-specific methods that expose HttpClient functionality. GetAspNetDocsIssuesYöntemi, GitHub deposundan en son açık sorunları sorgulamak ve ayrıştırmak için gereken kodu saklar.The GetAspNetDocsIssues method encapsulates the code needed to query for and parse out the latest open issues from a GitHub repository.

Türü belirtilmiş bir istemciyi kaydettirmek için, genel AddHttpClient genişletme yöntemi içinde kullanılabilir Startup.ConfigureServices istemci sınıfını belirterek kullanılabilir:To register a typed client, the generic AddHttpClient extension method can be used within Startup.ConfigureServices, specifying the typed client class:

services.AddHttpClient<GitHubService>();

Yazılan istemci, DI ile geçici olarak kaydedilir.The typed client is registered as transient with DI. Yazılan istemci doğrudan eklenebilir ve tüketilebilir:The typed client can be injected and consumed directly:

public class TypedClientModel : PageModel
{
    private readonly GitHubService _gitHubService;

    public IEnumerable<GitHubIssue> LatestIssues { get; private set; }

    public bool HasIssue => LatestIssues.Any();

    public bool GetIssuesError { get; private set; }

    public TypedClientModel(GitHubService gitHubService)
    {
        _gitHubService = gitHubService;
    }

    public async Task OnGet()
    {
        try
        {
            LatestIssues = await _gitHubService.GetAspNetDocsIssues();
        }
        catch(HttpRequestException)
        {
            GetIssuesError = true;
            LatestIssues = Array.Empty<GitHubIssue>();
        }
    }
}

Tercih edilirse, yazılan istemcinin yapılandırması, Startup.ConfigureServices türü belirlenmiş istemcinin Oluşturucusu yerine kayıt sırasında belirtilebilir:If preferred, the configuration for a typed client can be specified during registration in Startup.ConfigureServices, rather than in the typed client's constructor:

services.AddHttpClient<RepoService>(c =>
{
    c.BaseAddress = new Uri("https://api.github.com/");
    c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
    c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
});

HttpClientTürü belirtilmiş bir istemci içinde tamamen kapsüllenebilir.It's possible to entirely encapsulate the HttpClient within a typed client. Bunu bir özellik olarak göstermek yerine, örneği dahili olarak çağıran ortak Yöntemler sunulabilir HttpClient .Rather than exposing it as a property, public methods can be provided which call the HttpClient instance internally.

public class RepoService
{
    // _httpClient isn't exposed publicly
    private readonly HttpClient _httpClient;

    public RepoService(HttpClient client)
    {
        _httpClient = client;
    }

    public async Task<IEnumerable<string>> GetRepos()
    {
        var response = await _httpClient.GetAsync("aspnet/repos");

        response.EnsureSuccessStatusCode();

        var result = await response.Content
            .ReadAsAsync<IEnumerable<string>>();

        return result;
    }
}

Önceki kodda, HttpClient bir özel alan olarak depolanır.In the preceding code, the HttpClient is stored as a private field. Dış çağrıları yapmak için tüm erişim GetRepos yönteminden geçer.All access to make external calls goes through the GetRepos method.

Oluşturulan istemcilerGenerated clients

IHttpClientFactory, yeniden sığdırmagibi diğer üçüncü taraf kitaplıklarıyla birlikte kullanılabilir.IHttpClientFactory can be used in combination with other third-party libraries such as Refit. Yeniden sığdırma, .NET için bir REST kitaplığıdır.Refit is a REST library for .NET. REST API 'Leri canlı arabirimlere dönüştürür.It converts REST APIs into live interfaces. Arabirim bir uygulama, RestService HttpClient dış http çağrıları yapmak için kullanılarak tarafından dinamik olarak oluşturulur.An implementation of the interface is generated dynamically by the RestService, using HttpClient to make the external HTTP calls.

Bir arabirim ve yanıt, dış API 'yi ve yanıtını temsil edecek şekilde tanımlanır:An interface and a reply are defined to represent the external API and its response:

public interface IHelloClient
{
    [Get("/helloworld")]
    Task<Reply> GetMessageAsync();
}

public class Reply
{
    public string Message { get; set; }
}

Türü belirlenmiş bir istemci eklenebilir, uygulamayı oluşturmak için yeniden sığdırma kullanımı kullanılabilir:A typed client can be added, using Refit to generate the implementation:

public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient("hello", c =>
    {
        c.BaseAddress = new Uri("http://localhost:5000");
    })
    .AddTypedClient(c => Refit.RestService.For<IHelloClient>(c));

    services.AddMvc();
}

Tanımlı arabirim, gereken yerde, mak ve Refit tarafından sağlanmış uygulama ile kullanılabilir.The defined interface can be consumed where necessary, with the implementation provided by DI and Refit:

[ApiController]
public class ValuesController : ControllerBase
{
    private readonly IHelloClient _client;

    public ValuesController(IHelloClient client)
    {
        _client = client;
    }

    [HttpGet("/")]
    public async Task<ActionResult<Reply>> Index()
    {
        return await _client.GetMessageAsync();
    }
}

Giden istek ara yazılımıOutgoing request middleware

HttpClient, giden HTTP istekleri için birlikte bağlanabilen işleyicileri temsilci seçme kavramı zaten var.HttpClient already has the concept of delegating handlers that can be linked together for outgoing HTTP requests. , IHttpClientFactory Her bir adlandırılmış istemci için uygulanacak işleyicileri tanımlamanızı kolaylaştırır.The IHttpClientFactory makes it easy to define the handlers to apply for each named client. Bir giden istek ara yazılım işlem hattı oluşturmak için birden çok işleyicinin kaydını ve zincirlemeyi destekler.It supports registration and chaining of multiple handlers to build an outgoing request middleware pipeline. Bu işleyicilerin her biri, giden istekten önce ve sonra iş gerçekleştirebilir.Each of these handlers is able to perform work before and after the outgoing request. Bu düzen, ASP.NET Core gelen ara yazılım ardışık düzenine benzer.This pattern is similar to the inbound middleware pipeline in ASP.NET Core. Bu model, önbelleğe alma, hata işleme, serileştirme ve günlüğe kaydetme dahil olmak üzere HTTP istekleri etrafında çapraz kesme sorunlarını yönetmek için bir mekanizma sağlar.The pattern provides a mechanism to manage cross-cutting concerns around HTTP requests, including caching, error handling, serialization, and logging.

Bir işleyici oluşturmak için, öğesinden türeten bir sınıf tanımlayın DelegatingHandler .To create a handler, define a class deriving from DelegatingHandler. SendAsyncİsteği ardışık düzen içindeki bir sonraki işleyiciye geçirmeden önce kodu yürütmek için yöntemi geçersiz kılın:Override the SendAsync method to execute code before passing the request to the next handler in the pipeline:

public class ValidateHeaderHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        if (!request.Headers.Contains("X-API-KEY"))
        {
            return new HttpResponseMessage(HttpStatusCode.BadRequest)
            {
                Content = new StringContent(
                    "You must supply an API key header called X-API-KEY")
            };
        }

        return await base.SendAsync(request, cancellationToken);
    }
}

Yukarıdaki kod, temel bir işleyiciyi tanımlar.The preceding code defines a basic handler. İsteğe bağlı bir başlık olup olmadığını denetler X-API-KEY .It checks to see if an X-API-KEY header has been included on the request. Üst bilgi eksikse, HTTP çağrısından kaçınabilir ve uygun bir yanıt döndürebilir.If the header is missing, it can avoid the HTTP call and return a suitable response.

Kayıt sırasında, bir veya daha fazla işleyici bir için yapılandırmasına eklenebilir HttpClient .During registration, one or more handlers can be added to the configuration for an HttpClient. Bu görev, üzerindeki genişletme yöntemleri aracılığıyla gerçekleştirilir IHttpClientBuilder .This task is accomplished via extension methods on the IHttpClientBuilder.

services.AddTransient<ValidateHeaderHandler>();

services.AddHttpClient("externalservice", c =>
{
    // Assume this is an "external" service which requires an API KEY
    c.BaseAddress = new Uri("https://localhost:5000/");
})
.AddHttpMessageHandler<ValidateHeaderHandler>();

Yukarıdaki kodda,, ValidateHeaderHandler dı ile kaydedilir.In the preceding code, the ValidateHeaderHandler is registered with DI. İşleyicinin, bir geçici hizmet olarak dı 'ye kayıtlı olması gerekir , hiçbir koşulda kapsamı yoktur.The handler must be registered in DI as a transient service, never scoped. İşleyici kapsamlı bir hizmet olarak kayıtlıysa ve işleyicinin bağımlı olduğu tüm hizmetler atılabilir olur:If the handler is registered as a scoped service and any services that the handler depends upon are disposable:

  • İşleyici kapsam dışına geçmeden önce işleyicinin Hizmetleri atılamaz.The handler's services could be disposed before the handler goes out of scope.
  • Atılmış işleyici Hizmetleri işleyicinin başarısız olmasına neden olur.The disposed handler services causes the handler to fail.

Kaydedildikten sonra, AddHttpMessageHandler işleyici türünü geçirerek çağrılabilir.Once registered, AddHttpMessageHandler can be called, passing in the handler type.

Birden çok işleyici, yürütülmesi gereken sırayla kaydedilebilir.Multiple handlers can be registered in the order that they should execute. Her işleyici, son isteği çalıştırana kadar sonraki işleyiciyi sarmalar HttpClientHandler :Each handler wraps the next handler until the final HttpClientHandler executes the request:

services.AddTransient<SecureRequestHandler>();
services.AddTransient<RequestDataHandler>();

services.AddHttpClient("clientwithhandlers")
    // This handler is on the outside and called first during the 
    // request, last during the response.
    .AddHttpMessageHandler<SecureRequestHandler>()
    // This handler is on the inside, closest to the request being 
    // sent.
    .AddHttpMessageHandler<RequestDataHandler>();

İleti işleyicileriyle istek başına durumu paylaşmak için aşağıdaki yaklaşımlardan birini kullanın:Use one of the following approaches to share per-request state with message handlers:

  • Kullanarak işleyicide veri geçirin HttpRequestMessage.Properties .Pass data into the handler using HttpRequestMessage.Properties.
  • IHttpContextAccessorGeçerli isteğe erişmek için kullanın.Use IHttpContextAccessor to access the current request.
  • AsyncLocalVerileri geçirmek için özel bir depolama nesnesi oluşturun.Create a custom AsyncLocal storage object to pass the data.

Polly tabanlı işleyiciler kullanınUse Polly-based handlers

IHttpClientFactory, Pollyadlı popüler bir üçüncü taraf kitaplığı ile tümleşir.IHttpClientFactory integrates with a popular third-party library called Polly. Polly, .NET için kapsamlı bir esnekliği ve geçici hata işleme kitaplığıdır.Polly is a comprehensive resilience and transient fault-handling library for .NET. Geliştiricilerin yeniden deneme, devre kesici, zaman aşımı, Bulkbaş yalıtımı, akıcı ve iş parçacığı açısından güvenli bir şekilde geri dönüş gibi ilkeler almasına olanak tanır.It allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner.

Uzantı yöntemleri, yapılandırılmış örneklerle Polly ilkelerin kullanımını etkinleştirmek için sağlanır HttpClient .Extension methods are provided to enable the use of Polly policies with configured HttpClient instances. Polly uzantıları:The Polly extensions:

  • İstemcilere Polly tabanlı işleyiciler eklemeyi destekler.Support adding Polly-based handlers to clients.
  • , Microsoft. Extensions. http. Polly NuGet paketini yükledikten sonra kullanılabilir.Can be used after installing the Microsoft.Extensions.Http.Polly NuGet package. Paket, ASP.NET Core paylaşılan çerçevesine dahil değildir.The package isn't included in the ASP.NET Core shared framework.

Geçici hataları işleHandle transient faults

Yaygın hatalar, dış HTTP çağrıları geçici olduğunda oluşur.Most common faults occur when external HTTP calls are transient. AddTransientHttpErrorPolicyGeçici hataları işlemek üzere bir ilkenin tanımlanmasını sağlayan, çağrılan bir uygun genişletme yöntemi eklenmiştir.A convenient extension method called AddTransientHttpErrorPolicy is included which allows a policy to be defined to handle transient errors. Bu uzantı yöntemi tanıtıcısıyla yapılandırılmış ilkeler HttpRequestException , http 5xx yanıtları ve http 408 yanıtları.Policies configured with this extension method handle HttpRequestException, HTTP 5xx responses, and HTTP 408 responses.

AddTransientHttpErrorPolicyUzantı içinde kullanılabilir Startup.ConfigureServices .The AddTransientHttpErrorPolicy extension can be used within Startup.ConfigureServices. Uzantı, PolicyBuilder olası bir geçici hatayı temsil eden hataları işlemek için yapılandırılmış bir nesneye erişim sağlar:The extension provides access to a PolicyBuilder object configured to handle errors representing a possible transient fault:

services.AddHttpClient<UnreliableEndpointCallerService>()
    .AddTransientHttpErrorPolicy(p => 
        p.WaitAndRetryAsync(3, _ => TimeSpan.FromMilliseconds(600)));

Yukarıdaki kodda bir WaitAndRetryAsync ilke tanımlanmıştır.In the preceding code, a WaitAndRetryAsync policy is defined. Başarısız istekler, denemeler arasındaki 600 MS gecikmeyle en fazla üç kez yeniden denenir.Failed requests are retried up to three times with a delay of 600 ms between attempts.

Dinamik olarak ilke seçmeDynamically select policies

Polly tabanlı işleyiciler eklemek için kullanılabilecek ek uzantı yöntemleri vardır.Additional extension methods exist which can be used to add Polly-based handlers. Bu tür bir uzantının AddPolicyHandler birden çok aşırı yüklemesi vardır.One such extension is AddPolicyHandler, which has multiple overloads. Bir aşırı yükleme, hangi ilkenin uygulanacağını tanımlarken isteğin incelenebilirliğini sağlar:One overload allows the request to be inspected when defining which policy to apply:

var timeout = Policy.TimeoutAsync<HttpResponseMessage>(
    TimeSpan.FromSeconds(10));
var longTimeout = Policy.TimeoutAsync<HttpResponseMessage>(
    TimeSpan.FromSeconds(30));

services.AddHttpClient("conditionalpolicy")
// Run some code to select a policy based on the request
    .AddPolicyHandler(request => 
        request.Method == HttpMethod.Get ? timeout : longTimeout);

Yukarıdaki kodda, giden istek bir HTTP GET ise, 10 saniyelik bir zaman aşımı uygulanır.In the preceding code, if the outgoing request is an HTTP GET, a 10-second timeout is applied. Diğer HTTP yöntemleri için, 30 saniyelik bir zaman aşımı kullanılır.For any other HTTP method, a 30-second timeout is used.

Birden çok Polly işleyici eklemeAdd multiple Polly handlers

Gelişmiş işlevsellik sağlamak için çok fazla ilke iç içe geçmiş bir yaygın hale gelir:It's common to nest Polly policies to provide enhanced functionality:

services.AddHttpClient("multiplepolicies")
    .AddTransientHttpErrorPolicy(p => p.RetryAsync(3))
    .AddTransientHttpErrorPolicy(
        p => p.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));

Yukarıdaki örnekte, iki işleyici eklenmiştir.In the preceding example, two handlers are added. İlki, AddTransientHttpErrorPolicy yeniden deneme ilkesi eklemek için uzantıyı kullanır.The first uses the AddTransientHttpErrorPolicy extension to add a retry policy. Başarısız istekler en fazla üç kez yeniden denenir.Failed requests are retried up to three times. İçin ikinci çağrı, AddTransientHttpErrorPolicy bir devre kesici ilkesi ekler.The second call to AddTransientHttpErrorPolicy adds a circuit breaker policy. Beş başarısız girişim sırayla gerçekleşiyorsa, daha fazla dış istek 30 saniye için engellenir.Further external requests are blocked for 30 seconds if five failed attempts occur sequentially. Devre kesici ilkeleri durum bilgisi vardır.Circuit breaker policies are stateful. Bu istemci aracılığıyla yapılan tüm çağrılar aynı devre durumunu paylaşır.All calls through this client share the same circuit state.

Polly kayıt defterinden ilke eklemeAdd policies from the Polly registry

Düzenli olarak kullanılan ilkeleri yönetmeye yönelik bir yaklaşım, bunları bir kez tanımlayıp bir ile kaydetmektir PolicyRegistry .An approach to managing regularly used policies is to define them once and register them with a PolicyRegistry. Kayıt defterinden bir ilke kullanılarak bir işleyicinin eklenmesine izin veren bir genişletme yöntemi sağlanır:An extension method is provided which allows a handler to be added using a policy from the registry:

var registry = services.AddPolicyRegistry();

registry.Add("regular", timeout);
registry.Add("long", longTimeout);

services.AddHttpClient("regulartimeouthandler")
    .AddPolicyHandlerFromRegistry("regular");

Yukarıdaki kodda, öğesine eklendiğinde iki ilke kaydedilir PolicyRegistry ServiceCollection .In the preceding code, two policies are registered when the PolicyRegistry is added to the ServiceCollection. Kayıt defterinden bir ilke kullanmak için AddPolicyHandlerFromRegistry yöntemi kullanılır ve uygulanacak ilke adı geçer.To use a policy from the registry, the AddPolicyHandlerFromRegistry method is used, passing the name of the policy to apply.

Ve daha fazla tümleştirme hakkında daha fazla bilgi IHttpClientFactory , Polly wiki' de bulunabilir.Further information about IHttpClientFactory and Polly integrations can be found on the Polly wiki.

HttpClient ve ömür yönetimiHttpClient and lifetime management

HttpClientHer çağrıldığında yeni bir örnek döndürülür CreateClient IHttpClientFactory .A new HttpClient instance is returned each time CreateClient is called on the IHttpClientFactory. HttpMessageHandlerAdlandırılmış istemci başına.There's an HttpMessageHandler per named client. Fabrika, örneklerin yaşam sürelerini yönetir HttpMessageHandler .The factory manages the lifetimes of the HttpMessageHandler instances.

IHttpClientFactory``HttpMessageHandlerkaynak tüketimini azaltmak için fabrika tarafından oluşturulan örnekleri havuzlar.IHttpClientFactory pools the HttpMessageHandler instances created by the factory to reduce resource consumption. Bir HttpMessageHandler örnek, süresi dolmamışsa yeni bir örnek oluştururken havuzdan yeniden kullanılabilir HttpClient .An HttpMessageHandler instance may be reused from the pool when creating a new HttpClient instance if its lifetime hasn't expired.

Her işleyici genellikle kendi temel HTTP bağlantılarını yönettiğinden, işleyicilerin havuzlaması tercih edilir.Pooling of handlers is desirable as each handler typically manages its own underlying HTTP connections. Gerekenden daha fazla işleyici oluşturulması bağlantı gecikmeleri oluşmasına neden olabilir.Creating more handlers than necessary can result in connection delays. Ayrıca, bazı işleyiciler bağlantıları süresiz olarak açık tutar, bu da işleyicinin DNS değişikliklerine yeniden davranmasını engelleyebilir.Some handlers also keep connections open indefinitely, which can prevent the handler from reacting to DNS changes.

Varsayılan işleyici ömrü iki dakikadır.The default handler lifetime is two minutes. Varsayılan değer, adlandırılmış istemci temelinde geçersiz kılınabilir.The default value can be overridden on a per named client basis. Bunu geçersiz kılmak için, SetHandlerLifetime IHttpClientBuilder istemcisini oluştururken döndürülen öğesini çağırın:To override it, call SetHandlerLifetime on the IHttpClientBuilder that is returned when creating the client:

services.AddHttpClient("extendedhandlerlifetime")
    .SetHandlerLifetime(TimeSpan.FromMinutes(5));

İstemcinin çıkarılması gerekli değildir.Disposal of the client isn't required. Çıkarma giden istekleri iptal eder ve HttpClient çağırma sonrasında verilen örneğin kullanılamaz olmasını sağlar Dispose .Disposal cancels outgoing requests and guarantees the given HttpClient instance can't be used after calling Dispose. IHttpClientFactoryörnekler tarafından kullanılan kaynakları izler ve ortadan kaldırdık HttpClient .IHttpClientFactory tracks and disposes resources used by HttpClient instances. HttpClientÖrnekler genellikle aktiften çıkarma gerektirmeyen .NET nesneleri olarak kabul edilebilir.The HttpClient instances can generally be treated as .NET objects not requiring disposal.

Tek HttpClient bir örneğinin uzun süre canlı tutulması, önünde kullanılmadan önce kullanılan ortak bir modeldir IHttpClientFactory .Keeping a single HttpClient instance alive for a long duration is a common pattern used before the inception of IHttpClientFactory. Bu model, ' a geçtikten sonra gereksiz hale gelir IHttpClientFactory .This pattern becomes unnecessary after migrating to IHttpClientFactory.

Ihttpclientfactory alternatifleriAlternatives to IHttpClientFactory

IHttpClientFactoryDı etkin bir uygulamada kullanmak şunları önler:Using IHttpClientFactory in a DI-enabled app avoids:

  • Havuz örneklerine göre kaynak tükenmesi sorunları HttpMessageHandler .Resource exhaustion problems by pooling HttpMessageHandler instances.
  • Düzenli aralıklarla örnekleri geçirerek eski DNS sorunları HttpMessageHandler .Stale DNS problems by cycling HttpMessageHandler instances at regular intervals.

Uzun süreli bir örnek kullanarak önceki sorunları çözmenin alternatif yolları vardır SocketsHttpHandler .There are alternative ways to solve the preceding problems using a long-lived SocketsHttpHandler instance.

  • SocketsHttpHandlerUygulamanın başladığı zaman bir örneği oluşturun ve uygulamanın ömrü boyunca kullanın.Create an instance of SocketsHttpHandler when the app starts and use it for the life of the app.
  • PooledConnectionLifetimeDNS yenileme süreleri temelinde uygun bir değere yapılandırın.Configure PooledConnectionLifetime to an appropriate value based on DNS refresh times.
  • HttpClientGerektiğinde örnek oluşturun new HttpClient(handler, disposeHandler: false) .Create HttpClient instances using new HttpClient(handler, disposeHandler: false) as needed.

Yukarıdaki yaklaşımlar, IHttpClientFactory benzer bir şekilde çözen kaynak yönetimi sorunlarını çözer.The preceding approaches solve the resource management problems that IHttpClientFactory solves in a similar way.

  • , SocketsHttpHandler Örnekleri arasında bağlantıları paylaşır HttpClient .The SocketsHttpHandler shares connections across HttpClient instances. Bu paylaşım, yuva azalmasına engel olur.This sharing prevents socket exhaustion.
  • SocketsHttpHandlerBağlantıları, PooledConnectionLifetime eski DNS sorunlarından kaçınmak için öğesine göre döngüler.The SocketsHttpHandler cycles connections according to PooledConnectionLifetime to avoid stale DNS problems.

Tanımlama bilgileriCookies

Havuza alınmış HttpMessageHandler örnekler, CookieContainer paylaşılan nesneler ile sonuçlanır.The pooled HttpMessageHandler instances results in CookieContainer objects being shared. Beklenmeyen CookieContainer nesne paylaşımı genellikle hatalı kodla sonuçlanır.Unanticipated CookieContainer object sharing often results in incorrect code. Tanımlama bilgileri gerektiren uygulamalar için şunlardan birini göz önünde bulundurun:For apps that require cookies, consider either:

  • Otomatik tanımlama bilgisi işlemeyi devre dışı bırakmaDisabling automatic cookie handling
  • ÖnlemeninIHttpClientFactoryAvoiding IHttpClientFactory

ConfigurePrimaryHttpMessageHandlerOtomatik tanımlama bilgisi işlemesini devre dışı bırakmak için çağırın:Call ConfigurePrimaryHttpMessageHandler to disable automatic cookie handling:

services.AddHttpClient("configured-disable-automatic-cookies")
    .ConfigurePrimaryHttpMessageHandler(() =>
    {
        return new SocketsHttpHandler()
        {
            UseCookies = false,
        };
    });

Günlüğe KaydetmeLogging

IHttpClientFactoryTüm istekler için kayıt günlüğü iletileri aracılığıyla oluşturulan istemciler.Clients created via IHttpClientFactory record log messages for all requests. Varsayılan günlük iletilerini görmek için günlük yapılandırmanızda uygun bilgi düzeyini etkinleştirin.Enable the appropriate information level in your logging configuration to see the default log messages. İstek üst bilgilerinin günlüğe kaydedilmesi gibi ek Günlükler yalnızca izleme düzeyinde yer alır.Additional logging, such as the logging of request headers, is only included at trace level.

Her istemci için kullanılan günlük kategorisi, istemcinin adını içerir.The log category used for each client includes the name of the client. Örneğin, Mynamedclientadlı bir istemci, bir kategorisine sahip iletileri günlüğe kaydeder System.Net.Http.HttpClient.MyNamedClient.LogicalHandler .A client named MyNamedClient, for example, logs messages with a category of System.Net.Http.HttpClient.MyNamedClient.LogicalHandler. Logicalhandler ile düzeltilen iletiler istek işleyicisi ardışık düzeni dışında oluşur.Messages suffixed with LogicalHandler occur outside the request handler pipeline. İstekte, işlem hattındaki diğer işleyiciler işlenmeden önce iletiler günlüğe kaydedilir.On the request, messages are logged before any other handlers in the pipeline have processed it. Yanıtta, tüm diğer işlem hattı işleyicileri yanıtı aldıktan sonra iletiler günlüğe kaydedilir.On the response, messages are logged after any other pipeline handlers have received the response.

Günlüğe kaydetme, istek işleyicisi ardışık düzeni içinde de gerçekleşir.Logging also occurs inside the request handler pipeline. Mynamedclient örneğinde, bu iletiler günlük kategorisine göre günlüğe kaydedilir System.Net.Http.HttpClient.MyNamedClient.ClientHandler .In the MyNamedClient example, those messages are logged against the log category System.Net.Http.HttpClient.MyNamedClient.ClientHandler. İstek için bu, tüm diğer işleyiciler çalıştıktan sonra ve istek ağda gönderilmeden hemen önce gerçekleşir.For the request, this occurs after all other handlers have run and immediately before the request is sent out on the network. Yanıtta, bu günlüğe kaydetme, işleyicinin işleyici işlem hattı üzerinden geri geçirmeden önce yanıtın durumunu içerir.On the response, this logging includes the state of the response before it passes back through the handler pipeline.

İşlem hattının dışında ve içinde günlüğe kaydetmenin etkinleştirilmesi, diğer işlem hattı işleyicileri tarafından yapılan değişikliklerin incelemesini etkinleştirir.Enabling logging outside and inside the pipeline enables inspection of the changes made by the other pipeline handlers. Bu, örneğin veya yanıt durum kodunda istek başlıklarındaki değişiklikleri içerebilir.This may include changes to request headers, for example, or to the response status code.

İstemci adı ' nı log kategorisinde da içermek, gerektiğinde belirli adlandırılmış istemciler için günlük filtrelemeyi sunar.Including the name of the client in the log category enables log filtering for specific named clients where necessary.

HttpMessageHandler 'ı yapılandırmaConfigure the HttpMessageHandler

İstemci tarafından kullanılan iç yapılandırmayı denetlemek gerekli olabilir HttpMessageHandler .It may be necessary to control the configuration of the inner HttpMessageHandler used by a client.

IHttpClientBuilderAdlandırılmış veya yazılan istemciler eklenirken bir döndürülür.An IHttpClientBuilder is returned when adding named or typed clients. ConfigurePrimaryHttpMessageHandlerGenişletme yöntemi bir temsilciyi tanımlamak için kullanılabilir.The ConfigurePrimaryHttpMessageHandler extension method can be used to define a delegate. Temsilci, HttpMessageHandler Bu istemci tarafından kullanılan birincili oluşturmak ve yapılandırmak için kullanılır:The delegate is used to create and configure the primary HttpMessageHandler used by that client:

services.AddHttpClient("configured-inner-handler")
    .ConfigurePrimaryHttpMessageHandler(() =>
    {
        return new HttpClientHandler()
        {
            AllowAutoRedirect = false,
            UseDefaultCredentials = true
        };
    });

Konsol uygulamasında ıhttpclientfactory kullanmaUse IHttpClientFactory in a console app

Konsol uygulamasında, aşağıdaki paket başvurularını projeye ekleyin:In a console app, add the following package references to the project:

Aşağıdaki örnekte:In the following example:

  • IHttpClientFactory, genel konağın hizmet kapsayıcısına kaydedilir.IHttpClientFactory is registered in the Generic Host's service container.
  • MyServicehizmetinden bir istemci fabrikası örneği oluşturur HttpClient .MyService creates a client factory instance from the service, which is used to create an HttpClient. HttpClient, bir Web sayfasını almak için kullanılır.HttpClient is used to retrieve a webpage.
  • Mainhizmetin yöntemini yürütmek için bir kapsam oluşturur GetPage ve Web sayfası içeriğinin ilk 500 karakterini konsola yazar.Main creates a scope to execute the service's GetPage method and write the first 500 characters of the webpage content to the console.
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
class Program
{
    static async Task<int> Main(string[] args)
    {
        var builder = new HostBuilder()
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHttpClient();
                services.AddTransient<IMyService, MyService>();
            }).UseConsoleLifetime();

        var host = builder.Build();

        using (var serviceScope = host.Services.CreateScope())
        {
            var services = serviceScope.ServiceProvider;

            try
            {
                var myService = services.GetRequiredService<IMyService>();
                var pageContent = await myService.GetPage();

                Console.WriteLine(pageContent.Substring(0, 500));
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();

                logger.LogError(ex, "An error occurred.");
            }
        }

        return 0;
    }

    public interface IMyService
    {
        Task<string> GetPage();
    }

    public class MyService : IMyService
    {
        private readonly IHttpClientFactory _clientFactory;

        public MyService(IHttpClientFactory clientFactory)
        {
            _clientFactory = clientFactory;
        }

        public async Task<string> GetPage()
        {
            // Content from BBC One: Dr. Who website (©BBC)
            var request = new HttpRequestMessage(HttpMethod.Get,
                "https://www.bbc.co.uk/programmes/b006q2x0");
            var client = _clientFactory.CreateClient();
            var response = await client.SendAsync(request);

            if (response.IsSuccessStatusCode)
            {
                return await response.Content.ReadAsStringAsync();
            }
            else
            {
                return $"StatusCode: {response.StatusCode}";
            }
        }
    }
}

Üst bilgi yayma ara yazılımıHeader propagation middleware

Üst bilgi yayma, gelen istekten giden HTTP Istemci isteklerine HTTP üstbilgilerini yaymak için bir topluluk tarafından desteklenen bir ara yazılımlar.Header propagation is a community supported middleware to propagate HTTP headers from the incoming request to the outgoing HTTP Client requests. Üst bilgi yaymayı kullanmak için:To use header propagation:

  • Topluluğun, paket Headeryayılmasınındesteklediği bağlantı noktasına başvurun.Reference the community supported port of the package HeaderPropagation. ASP.NET Core 3,1 ve üzeri, Microsoft. AspNetCore. Headeryayılmayıdestekler.ASP.NET Core 3.1 and later supports Microsoft.AspNetCore.HeaderPropagation.

  • Ara yazılımı ve HttpClient içinde yapılandırın Startup :Configure the middleware and HttpClient in Startup:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    
        services.AddHttpClient("MyForwardingClient").AddHeaderPropagation();
        services.AddHeaderPropagation(options =>
        {
            options.Headers.Add("X-TraceId");
        });
    }
    
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
    
        app.UseHeaderPropagation();
    
        app.UseMvc();
    }
    
  • İstemci giden isteklerde yapılandırılan üst bilgileri içerir:The client includes the configured headers on outbound requests:

    var client = clientFactory.CreateClient("MyForwardingClient");
    var response = client.GetAsync(...);
    

Ek kaynaklarAdditional resources