Megosztás a következőn keresztül:


HttpContext használata az ASP.NET Core-ban

Megjegyzés:

Ez nem a cikk legújabb verziója. Az aktuális kiadásról a cikk .NET 10-es verziójában olvashat.

Figyelmeztetés

A ASP.NET Core ezen verziója már nem támogatott. További információt a .NET és a .NET Core támogatási szabályzatában talál. A jelen cikk .NET 9-es verzióját lásd az aktuális kiadásért .

HttpContext beágyazza az egyes HTTP-kérésekre és -válaszokra vonatkozó összes információt. Az HttpContext példányt inicializálják, amikor egy HTTP-kérést fogadnak. A HttpContext példány elérhető köztes szoftver- és alkalmazás-keretrendszerek, például Blazor Web Apps, Web API-vezérlők, Razor Pages, SignalR, gRPC és mások számára.

HttpRequest

HttpContext.Request hozzáférést biztosít HttpRequest számára. HttpRequest információval rendelkezik a bejövő HTTP-kérésről, és inicializálódik, amikor a kiszolgáló HTTP-kérést fogad. HttpRequest nem írásvédett, és a middleware módosíthatja a kérési értékeket a köztes szoftverfolyamat során.

Gyakran használt tagok a HttpRequest következők:

Ingatlan Description Example
HttpRequest.Path A kérelem elérési útja. /en/article/getstarted
HttpRequest.Method A kérelmi metódus. GET
HttpRequest.Headers Kérelemfejlécek gyűjteménye. user-agent=Edge
x-custom-header=MyValue
HttpRequest.RouteValues Útvonalértékek gyűjteménye. A gyűjtemény akkor van beállítva, ha a kérés egy útvonalhoz van igazítva. language=en
article=getstarted
HttpRequest.Query A QueryString-ből elemzett lekérdezési értékek gyűjteménye. filter=hello
page=1
HttpRequest.ReadFormAsync() Egy metódus, amely űrlapként olvassa be a kérelem törzsét, és egy űrlapérték-gyűjteményt ad vissza. Az űrlapadatok elérésének okairól szóló további információkért lásd: ReadFormAsync. email=user@contoso.com
HttpRequest.Body A Stream a kérelem törzsének olvasásához. UTF-8 JSON hasznos adatok

Kérelemfejlécek lekérése

HttpRequest.Headers hozzáférést biztosít a HTTP-kéréssel küldött kérelemfejlécekhez. A fejlécek kétféleképpen érhetők el a gyűjtemény használatával:

  • Adja meg a fejléc nevét a fejléccsoport indexelőjének. A fejléc neve nem érzékeny a kis- és nagybetűkre. Az indexelő bármilyen fejlécértéket elérhet.
  • A fejlécgyűjtemény rendelkezik a gyakran használt HTTP-fejlécek beolvasására és beállítására szolgáló tulajdonságokkal is. A tulajdonságok gyors, IntelliSense-alapú módot biztosítanak a fejlécek eléréséhez.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", (HttpRequest request) =>
{
    var userAgent = request.Headers.UserAgent;
    var customHeader = request.Headers["x-custom-header"];

    return Results.Ok(new { userAgent = userAgent, customHeader = customHeader });
});

app.Run();

A többször megjelenő fejlécek hatékony kezeléséről a StringValues rövid ismertetésében olvashat.

Kérelemtörzs olvasása

A HTTP-kérések tartalmazhatnak egy kérelemtörzset. A kérelem törzse a kérelemhez társított adatok, például egy HTML-űrlap tartalma, egy UTF-8 JSON adatcsomag vagy egy fájl.

HttpRequest.Body lehetővé teszi a kérelem törzsének olvasását a következővel Stream:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapPost("/uploadstream", async (IConfiguration config, HttpContext context) =>
{
    var filePath = Path.Combine(config["StoredFilesPath"], Path.GetRandomFileName());

    await using var writeStream = File.Create(filePath);
    await context.Request.Body.CopyToAsync(writeStream);
});

app.Run();

HttpRequest.Body közvetlenül olvasható, vagy más, streamet elfogadó API-kkal is használható.

Megjegyzés:

A minimális API-k támogatják a közvetlenül egy paraméterhez való kötést HttpRequest.BodyStream .

A kérés törzsének pufferelésének engedélyezése

A kérelem törzse csak egyszer olvasható az elejétől a végéig. A kérelemtörzs csak előre beolvasása elkerüli a teljes kérelemtörzs pufferelésével kapcsolatos többletterhelést, és csökkenti a memóriahasználatot. Bizonyos esetekben azonban többször is be kell olvasni a kérelem törzsét. Előfordulhat például, hogy a köztes szoftvernek be kell olvasnia a kérelem törzsét, majd vissza kell pörgetnie, hogy elérhető legyen a végpont számára.

A EnableBuffering bővítménymetódus lehetővé teszi a HTTP-kérelem törzsének pufferelését, és ez a javasolt módszer több olvasás engedélyezésére. Mivel egy kérés bármilyen méretű lehet, EnableBuffering támogatja a nagyméretű kérelemtörzsek lemezre való pufferelését vagy teljes elutasítását.

A köztes szoftver az alábbi példában:

  • Többszöri olvasás engedélyezése EnableBuffering-val. A kérés törzsének elolvasása előtt meg kell hívni.
  • Beolvassa a kérelem törzsét.
  • Visszatekeri a kérelem törzsét a kezdetre, hogy más köztes szoftver vagy a végpont elolvashassa.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.Use(async (context, next) =>
{
    context.Request.EnableBuffering();
    await ReadRequestBody(context.Request.Body);
    context.Request.Body.Position = 0;
    
    await next.Invoke();
});

app.Run();

BodyReader

A kérelem törzsét másik módon is el lehet olvasni a HttpRequest.BodyReader tulajdonság használatával. A BodyReader tulajdonság a kérelem törzsét mint egy PipeReader jeleníti meg. Ez az API I/O-folyamatokból származik, amely egy speciális, nagy teljesítményű módja a kérelem törzsének olvasásának.

Az olvasó közvetlenül hozzáfér a kérés törzséhez, és a hívó nevében kezeli a memóriát. Ellentétben HttpRequest.Bodyaz olvasó nem másolja a kérésadatokat egy pufferbe. Az olvasó használata azonban bonyolultabb, mint egy stream, ezért körültekintően kell használni.

A tartalom BodyReaderolvasásáról további információt az I/O-folyamatok PipeReader című témakörben talál.

HttpResponse

HttpContext.Response hozzáférést biztosít HttpResponse számára. HttpResponse az ügyfélnek küldött HTTP-válaszra vonatkozó információk megadására szolgál.

Gyakran használt tagok a HttpResponse következők:

Ingatlan Description Example
HttpResponse.StatusCode A válaszkód. Be kell állítani a választörzsbe való írás előtt. 200
HttpResponse.ContentType A válasz content-type fejléce. Be kell állítani a választörzsbe való írás előtt. application/json
HttpResponse.Headers Válaszfejlécek gyűjteménye. Be kell állítani a választörzsbe való írás előtt. server=Kestrel
x-custom-header=MyValue
HttpResponse.Body A Stream a válasz törzs részének megírásához. Létrehozott weblap

Válaszfejlécek beállítása

HttpResponse.Headers hozzáférést biztosít a HTTP-válaszsal küldött válaszfejlécekhez. A fejlécek kétféleképpen érhetők el a gyűjtemény használatával:

  • Adja meg a fejléc nevét a fejléccsoport indexelőjének. A fejléc neve nem érzékeny a kis- és nagybetűkre. Az indexelő bármilyen fejlécértéket elérhet.
  • A gyakran használt HTTP-fejlécek lekéréséhez és beállításához használja a fejléccsoport tulajdonságait. A tulajdonságok gyors, IntelliSense-alapú módot biztosítanak a fejlécek eléréséhez.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", (HttpResponse response) =>
{
    response.Headers.CacheControl = "no-cache";
    response.Headers["x-custom-header"] = "Custom value";

    return Results.File(File.OpenRead("helloworld.txt"));
});

app.Run();

Az alkalmazás nem tudja módosítani a fejléceket a válasz elindítása után. A válasz elindítása után a rendszer elküldi a fejléceket az ügyfélnek. A válasz a válasz törzsének kiürítésével vagy a hívással HttpResponse.StartAsync(CancellationToken)kezdődik. A HttpResponse.HasStarted tulajdonság azt jelzi, hogy a válasz elindult-e. Hibaüzenet jelenik meg a fejlécek módosításának megkísérlésekor a válasz elindítása után:

System.InvalidOperationException: A fejlécek írásvédettek, a válasz már megkezdődött.

Megjegyzés:

Ha nincs engedélyezve a válaszpufferelés, az összes írási művelet (például WriteAsync) belsőleg üríti a válasz törzsét, és a választ elindítottnak jelöli meg. A válaszpufferelés alapértelmezés szerint le van tiltva.

Választörzs létrehozása

A HTTP-válaszok tartalmazhatnak választörzset. Válasz törzse a válasznál használt adatok, mint például a létrehozott weblaptartalmak, az UTF-8 JSON terhelési adatai vagy egy fájl.

HttpResponse.Body lehetővé teszi, hogy a válasz törzse a következővel Streamlegyen megírva:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapPost("/downloadfile", async (IConfiguration config, HttpContext context) =>
{
    var filePath = Path.Combine(config["StoredFilesPath"], "helloworld.txt");

    await using var fileStream = File.OpenRead(filePath);
    await fileStream.CopyToAsync(context.Response.Body);
});

app.Run();

HttpResponse.Body közvetlenül vagy más, streambe író API-kkal is megírható.

BodyWriter

A válasz törzs írásának egy alternatív módja a HttpResponse.BodyWriter tulajdonság használata. A BodyWriter tulajdonság ismerteti a válasz törzsét PipeWriter formában. Ez az API I/O-folyamatokból származik, és ez egy speciális, nagy teljesítményű módszer a válasz megírására.

Az író közvetlen hozzáférést biztosít a válasz törzséhez, és a hívó nevében kezeli a memóriát. HttpResponse.Body ellentétben az írás nem másolja a kérés adatait egy pufferbe. Azonban egy író használata bonyolultabb, mint egy stream, és az írókódot alaposan tesztelni kell.

A tartalom BodyWriterírásáról további információt az I/O-folyamatok PipeWriter című témakörben talál.

Válasz utófejlécek beállítása

A HTTP/2 és a HTTP/3 támogatja a válaszelőzeteseket. A végfejlécek olyan fejlécek, amelyeket a válasz törzsének befejezése után küldünk. Mivel a rendszer a válasz törzse után küld pótkocsikat, a pótkocsik bármikor hozzáadhatók a válaszhoz.

A következő kódkészletek a következő használatával AppendTrailerállítja be a pótkocsikat:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", (HttpResponse response) =>
{
    // Write body
    response.WriteAsync("Hello world");

    if (response.SupportsTrailers())
    {
        response.AppendTrailer("trailername", "TrailerValue");
    }
});

app.Run();

RequestAborted

A törlési HttpContext.RequestAborted token jelezheti, hogy az HTTP-kérést az ügyfél vagy a szerver megszakította. A törlési tokent át kell adni hosszú ideig futó feladatoknak, hogy azok kihagyják a kérést, ha az megszakításra kerül. Például egy adatbázis-lekérdezés vagy HTTP-kérés megszakítása a válaszban való visszatéréshez szükséges adatok lekéréséhez.

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

var httpClient = new HttpClient();
app.MapPost("/books/{bookId}", async (int bookId, HttpContext context) =>
{
    var stream = await httpClient.GetStreamAsync(
        $"http://contoso/books/{bookId}.json", context.RequestAborted);

    // Proxy the response as JSON
    return Results.Stream(stream, "application/json");
});

app.Run();

A RequestAborted lemondási token-t nem kell használni a kérelemtörzs olvasási műveleteinél, mert az olvasások mindig azonnal megszakadnak, amikor a kérés megszakad. A RequestAborted token általában szükségtelen, amikor választesteket írunk, mivel a kérés megszakítása után azonnali no-op történik.

Bizonyos esetekben a RequestAborted token írási műveletekre való átadása kényelmes módszer lehet arra, hogy az írási hurkot a korai kilépéshez kényszerítse. OperationCanceledException Általában azonban jobb, ha a RequestAborted jogkivonatot olyan aszinkron műveletekbe adja át, amelyek a válasz törzsének tartalmának lekéréséért felelősek.

Megjegyzés:

A minimális API-k támogatják a közvetlenül egy paraméterhez való kötést HttpContext.RequestAbortedCancellationToken .

Abort()

A HttpContext.Abort() metódussal megszakítható egy HTTP-kérés a kiszolgálóról. A HTTP-kérés megszakítása azonnal aktiválja a HttpContext.RequestAborted lemondási jogkivonatot, és értesítést küld az ügyfélnek arról, hogy a kiszolgáló megszakította a kérést.

A köztes szoftver az alábbi példában:

  • Egyéni ellenőrzést ad hozzá a rosszindulatú kérelmekhez.
  • Megszakítja a HTTP-kérést, ha a kérés rosszindulatú.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.Use(async (context, next) =>
{
    if (RequestAppearsMalicious(context.Request))
    {
        // Malicious requests don't even deserve an error response (e.g. 400).
        context.Abort();
        return;
    }

    await next.Invoke();
});

app.Run();

User

A HttpContext.User tulajdonság a kérelemhez tartozó ClaimsPrincipal felhasználó lekérésére vagy beállítására szolgál. Az ClaimsPrincipal-t általában az ASP.NET Core-hitelesítés állítja be.

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/user/current", [Authorize] async (HttpContext context) =>
{
    var user = await GetUserAsync(context.User.Identity.Name);
    return Results.Ok(user);
});

app.Run();

Megjegyzés:

A minimális API-k támogatják a közvetlenül egy paraméterhez való kötést HttpContext.UserClaimsPrincipal .

Features

A HttpContext.Features tulajdonság hozzáférést biztosít az aktuális kérés funkcióillesztőinek gyűjteményéhez. Mivel a szolgáltatásgyűjtemény egy kérés kontextusában is mutable, a köztes szoftver használható a gyűjtemény módosítására és további funkciók támogatásának hozzáadására. Egyes speciális funkciók csak a társított felület funkciógyűjteményen keresztüli elérésével érhetők el.

A következő példa:

  • Lekérdez IHttpMinRequestBodyDataRateFeature a funkciók gyűjteményéből.
  • Null értékre van adva MinDataRate . Ez eltávolítja azt a minimális adatmennyiséget, amelyet a kérelem törzsének az ügyfélnek el kell küldenie ehhez a HTTP-kéréshez.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/long-running-stream", async (HttpContext context) =>
{
    var feature = context.Features.Get<IHttpMinRequestBodyDataRateFeature>();
    if (feature != null)
    {
        feature.MinDataRate = null;
    }

    // await and read long-running stream from request body.
    await Task.Yield();
});

app.Run();

A kérelemfunkciók HttpContexthasználatáról további információt a ASP.NET Core Szolgáltatáskérési funkciói című témakörben talál.

HttpContext nem szálbiztos

Ez a cikk elsősorban a kérési és válaszfolyamatokban a HttpContext összetevők, Blazor Web App lapok, vezérlők, köztes szoftverek és így tovább használatával foglalkozik. A kérelem- és válaszfolyamaton kívüli használat HttpContext esetén vegye figyelembe a következőket:

  • A HttpContextNEM szál biztonságos. Ha több szálból éri el, az kiszámíthatatlan eredményeket eredményezhet, például kivételeket és adatsérüléseket.
  • A IHttpContextAccessor kezelőfelületet körültekintően kell használni. Mint mindig, a HttpContext kérési folyamaton kívül nem szabad rögzíteni. IHttpContextAccessor:
    • A AsyncLocal<T> használata, amely negatívan befolyásolhatja az aszinkron hívások teljesítményét.
    • Függőséget hoz létre a "környezeti állapottól", ami megnehezítheti a tesztelést.
  • IHttpContextAccessor.HttpContext akkor lehet null , ha a kérelemfolyamaton kívül van elérve.
  • Ha a kérelemfolyamaton kívülről HttpContext szeretne adatokat elérni, másolja az adatokat a kérelemfolyamatba. Ügyeljen arra, hogy ne csak a hivatkozásokat, hanem a tényleges adatokat is másolja. Például ahelyett, hogy egy IHeaderDictionary hivatkozást másolna, másolja a megfelelő fejlécértékeket, vagy másolja a teljes szótárt kulcsonként a kérelem feldolgozási folyamatának elhagyása előtt.
  • Ne használjon IHttpContextAccessor.HttpContext a konstruktorban.

Az alábbi példa naplózza a GitHub-ágakat, amikor a végpontról kérik: /branch

using System.Text.Json;
using HttpContextInBackgroundThread;
using Microsoft.Net.Http.Headers;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpContextAccessor();
builder.Services.AddHostedService<PeriodicBranchesLoggerService>();

builder.Services.AddHttpClient("GitHub", httpClient =>
{
    httpClient.BaseAddress = new Uri("https://api.github.com/");

    // The GitHub API requires two headers. The Use-Agent header is added
    // dynamically through UserAgentHeaderHandler
    httpClient.DefaultRequestHeaders.Add(
        HeaderNames.Accept, "application/vnd.github.v3+json");
}).AddHttpMessageHandler<UserAgentHeaderHandler>();

builder.Services.AddTransient<UserAgentHeaderHandler>();

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.MapGet("/branches", async (IHttpClientFactory httpClientFactory,
                         HttpContext context, Logger<Program> logger) =>
{
    var httpClient = httpClientFactory.CreateClient("GitHub");
    var httpResponseMessage = await httpClient.GetAsync(
        "repos/dotnet/AspNetCore.Docs/branches");

    if (!httpResponseMessage.IsSuccessStatusCode) 
        return Results.BadRequest();

    await using var contentStream =
        await httpResponseMessage.Content.ReadAsStreamAsync();

    var response = await JsonSerializer.DeserializeAsync
        <IEnumerable<GitHubBranch>>(contentStream);

    app.Logger.LogInformation($"/branches request: " +
                              $"{JsonSerializer.Serialize(response)}");

    return Results.Ok(response);
});

app.Run();

A GitHub API-nak két fejlécre van szüksége. A User-Agent fejlécet dinamikusan hozzáadja a UserAgentHeaderHandlerkövetkező:

using System.Text.Json;
using HttpContextInBackgroundThread;
using Microsoft.Net.Http.Headers;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpContextAccessor();
builder.Services.AddHostedService<PeriodicBranchesLoggerService>();

builder.Services.AddHttpClient("GitHub", httpClient =>
{
    httpClient.BaseAddress = new Uri("https://api.github.com/");

    // The GitHub API requires two headers. The Use-Agent header is added
    // dynamically through UserAgentHeaderHandler
    httpClient.DefaultRequestHeaders.Add(
        HeaderNames.Accept, "application/vnd.github.v3+json");
}).AddHttpMessageHandler<UserAgentHeaderHandler>();

builder.Services.AddTransient<UserAgentHeaderHandler>();

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.MapGet("/branches", async (IHttpClientFactory httpClientFactory,
                         HttpContext context, Logger<Program> logger) =>
{
    var httpClient = httpClientFactory.CreateClient("GitHub");
    var httpResponseMessage = await httpClient.GetAsync(
        "repos/dotnet/AspNetCore.Docs/branches");

    if (!httpResponseMessage.IsSuccessStatusCode) 
        return Results.BadRequest();

    await using var contentStream =
        await httpResponseMessage.Content.ReadAsStreamAsync();

    var response = await JsonSerializer.DeserializeAsync
        <IEnumerable<GitHubBranch>>(contentStream);

    app.Logger.LogInformation($"/branches request: " +
                              $"{JsonSerializer.Serialize(response)}");

    return Results.Ok(response);
});

app.Run();

A UserAgentHeaderHandler:

using Microsoft.Net.Http.Headers;

namespace HttpContextInBackgroundThread;

public class UserAgentHeaderHandler : DelegatingHandler
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    private readonly ILogger _logger;

    public UserAgentHeaderHandler(IHttpContextAccessor httpContextAccessor,
                                  ILogger<UserAgentHeaderHandler> logger)
    {
        _httpContextAccessor = httpContextAccessor;
        _logger = logger;
    }

    protected override async Task<HttpResponseMessage> 
                                    SendAsync(HttpRequestMessage request, 
                                    CancellationToken cancellationToken)
    {
        var contextRequest = _httpContextAccessor.HttpContext?.Request;
        string? userAgentString = contextRequest?.Headers["user-agent"].ToString();
        
        if (string.IsNullOrEmpty(userAgentString))
        {
            userAgentString = "Unknown";
        }

        request.Headers.Add(HeaderNames.UserAgent, userAgentString);
        _logger.LogInformation($"User-Agent: {userAgentString}");

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

Az előző kódban, amikor a HttpContextnull, a userAgent sztring a "Unknown" értékre van állítva. Ha lehetséges, HttpContext kifejezetten át kell adni a szolgáltatásnak. Adatok explicit átadása HttpContext :

  • A szolgáltatás API-t a kérelemfolyamaton kívül is használhatóbbá teszi.
  • Jobb a teljesítmény szempontjából.
  • A kód érthetőbbé és átláthatóbbá válik, mint a környezeti állapotra való támaszkodás.

Amikor a szolgáltatásnak hozzá kell férnie HttpContext, figyelembe kell vennie annak lehetőségét, hogy HttpContextnull legyen, amikor nem a kérésszálból hívják meg.

Az alkalmazás tartalmazza PeriodicBranchesLoggerServiceazt is, amely 30 másodpercenként naplózza a megadott adattár megnyitott GitHub-ágait:

using System.Text.Json;

namespace HttpContextInBackgroundThread;

public class PeriodicBranchesLoggerService : BackgroundService
{
    private readonly IHttpClientFactory _httpClientFactory;
    private readonly ILogger _logger;
    private readonly PeriodicTimer _timer;

    public PeriodicBranchesLoggerService(IHttpClientFactory httpClientFactory,
                                         ILogger<PeriodicBranchesLoggerService> logger)
    {
        _httpClientFactory = httpClientFactory;
        _logger = logger;
        _timer = new PeriodicTimer(TimeSpan.FromSeconds(30));
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (await _timer.WaitForNextTickAsync(stoppingToken))
        {
            try
            {
                // Cancel sending the request to sync branches if it takes too long
                // rather than miss sending the next request scheduled 30 seconds from now.
                // Having a single loop prevents this service from sending an unbounded
                // number of requests simultaneously.
                using var syncTokenSource = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken);
                syncTokenSource.CancelAfter(TimeSpan.FromSeconds(30));
                
                var httpClient = _httpClientFactory.CreateClient("GitHub");
                var httpResponseMessage = await httpClient.GetAsync("repos/dotnet/AspNetCore.Docs/branches",
                                                                    stoppingToken);

                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    await using var contentStream =
                        await httpResponseMessage.Content.ReadAsStreamAsync(stoppingToken);

                    // Sync the response with preferred datastore.
                    var response = await JsonSerializer.DeserializeAsync<
                        IEnumerable<GitHubBranch>>(contentStream, cancellationToken: stoppingToken);

                    _logger.LogInformation(
                        $"Branch sync successful! Response: {JsonSerializer.Serialize(response)}");
                }
                else
                {
                    _logger.LogError(1, $"Branch sync failed! HTTP status code: {httpResponseMessage.StatusCode}");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(1, ex, "Branch sync failed!");
            }
        }
    }

    public override Task StopAsync(CancellationToken stoppingToken)
    {
        // This will cause any active call to WaitForNextTickAsync() to return false immediately.
        _timer.Dispose();
        // This will cancel the stoppingToken and await ExecuteAsync(stoppingToken).
        return base.StopAsync(stoppingToken);
    }
}

PeriodicBranchesLoggerService egy üzemeltetett szolgáltatás, amely a kérelem- és válaszfolyamaton kívül fut. A PeriodicBranchesLoggerService naplózása null HttpContext értékkel rendelkezik. Úgy lett megírva a PeriodicBranchesLoggerService, hogy nem függ a HttpContext.

using System.Text.Json;
using HttpContextInBackgroundThread;
using Microsoft.Net.Http.Headers;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpContextAccessor();
builder.Services.AddHostedService<PeriodicBranchesLoggerService>();

builder.Services.AddHttpClient("GitHub", httpClient =>
{

További erőforrások

A hozzáféréssel HttpContextkapcsolatos további információkért lásd: HttpContext elérése a ASP.NET Core-ban.