ASP.NET Core'da HttpContext kullanma
Uyarı
ASP.NET Core'un bu sürümü artık desteklenmiyor. Daha fazla bilgi için bkz . .NET ve .NET Core Destek İlkesi. Geçerli sürüm için bu makalenin .NET 8 sürümüne bakın.
HttpContext tek bir HTTP isteği ve yanıtı hakkındaki tüm bilgileri kapsüller. HTTP HttpContext
isteği alındığında örnek başlatılır. Örneğe HttpContext
Web API denetleyicileri, SayfalarSignalR, Razor gRPC ve daha fazlası gibi ara yazılım ve uygulama çerçeveleri tarafından erişilebilir.
öğesine erişme HttpContext
hakkında daha fazla bilgi için bkz . ASP.NET Core'da HttpContext'e erişme.
HttpRequest
HttpContext.Request öğesine erişim HttpRequestsağlar. HttpRequest
gelen HTTP isteği hakkında bilgi sahibidir ve sunucu tarafından bir HTTP isteği alındığında başlatılır. HttpRequest
salt okunur değildir ve ara yazılım, ara yazılım işlem hattındaki istek değerlerini değiştirebilir.
Üzerinde HttpRequest
yaygın olarak kullanılan üyeler şunlardır:
Özellik | Açıklama | Örnek |
---|---|---|
HttpRequest.Path | İstek yolu. | /en/article/getstarted |
HttpRequest.Method | İstek yöntemi. | GET |
HttpRequest.Headers | İstek üst bilgileri koleksiyonu. | user-agent=Edge x-custom-header=MyValue |
HttpRequest.RouteValues | Yol değerleri koleksiyonu. İstek bir yolla eşleştirildiğinde koleksiyon ayarlanır. | language=en article=getstarted |
HttpRequest.Query | 'den QueryStringayrıştırılan sorgu değerleri koleksiyonu. | filter=hello page=1 |
HttpRequest.ReadFormAsync() | İstek gövdesini form olarak okuyan ve form değerleri koleksiyonu döndüren bir yöntem. Form verilerine erişmek için neden ReadFormAsync kullanılması gerektiği hakkında bilgi için bkz . Request.Form yerine ReadFormAsync'i tercih etme. |
email=user@contoso.com |
HttpRequest.Body | İstek gövdesini okumak için A Stream . | UTF-8 JSON yükü |
İstek üst bilgilerini alma
HttpRequest.Headers HTTP isteğiyle gönderilen istek üst bilgilerine erişim sağlar. Bu koleksiyonu kullanarak üst bilgilere erişmenin iki yolu vardır:
- Üst bilgi koleksiyonundaki dizin oluşturucuya üst bilgi adını sağlayın. Üst bilgi adı büyük/küçük harfe duyarlı değildir. Dizin oluşturucu herhangi bir üst bilgi değerine erişebilir.
- Üst bilgi koleksiyonu, sık kullanılan HTTP üst bilgilerini alma ve ayarlama özelliklerine de sahiptir. Özellikler, üst bilgiye erişmek için hızlı, IntelliSense temelli bir yol sağlar.
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();
Birden çok kez görüntülenen üst bilgileri verimli bir şekilde işleme hakkında bilgi için bkz . StringValues'a kısa bir bakış.
Okuma isteği gövdesi
HTTP isteği bir istek gövdesi içerebilir. İstek gövdesi, bir HTML formunun içeriği, UTF-8 JSON yükü veya bir dosya gibi istekle ilişkili verilerdir.
HttpRequest.Body , istek gövdesinin ile Streamokunmasına izin verir:
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
doğrudan okunabilir veya akışı kabul eden diğer API'lerle birlikte kullanılabilir.
Not
Minimum API'ler doğrudan bir Stream parametreye bağlamayı HttpRequest.Body destekler.
İstek gövdesi arabelleği oluşturmayı etkinleştirme
İstek gövdesi baştan sona yalnızca bir kez okunabilir. İstek gövdesinin yalnızca ileriye doğru okunması, istek gövdesinin tamamını arabelleğe alma yükünü önler ve bellek kullanımını azaltır. Ancak bazı senaryolarda istek gövdesini birden çok kez okumanız gerekir. Örneğin ara yazılımların istek gövdesini okuması ve uç nokta için kullanılabilir olması için geri sarması gerekebilir.
EnableBuffering Uzantı yöntemi, HTTP isteği gövdesinin arabelleğe alınmasını sağlar ve birden çok okumayı etkinleştirmenin önerilen yoludur. bir istek herhangi bir boyutta olabileceği için, EnableBuffering
büyük istek gövdelerini diske arabelleğe alma veya tamamen reddetme seçeneklerini destekler.
Aşağıdaki örnekteki ara yazılım:
- ile
EnableBuffering
birden çok okumayı etkinleştirir. İstek gövdesi okunmadan önce çağrılmalıdır. - İstek gövdesini okur.
- diğer ara yazılımların veya uç noktanın okuyabilmesi için istek gövdesini başlangıç ekranına geri sarar.
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
İstek gövdesini okumanın alternatif bir yolu özelliğini kullanmaktır HttpRequest.BodyReader . BodyReader
özelliği istek gövdesini olarak PipeReaderkullanıma sunar. Bu API, istek gövdesini okumanın gelişmiş, yüksek performanslı bir yolu olan G/Ç işlem hatlarından alınmaktadır.
Okuyucu doğrudan istek gövdesine erişir ve arayan adına belleği yönetir. aksine HttpRequest.Body
, okuyucu istek verilerini arabelleğe kopyalamaz. Ancak okuyucu kullanımı bir akıştan daha karmaşıktır ve dikkatli kullanılmalıdır.
'den BodyReader
içerik okuma hakkında bilgi için bkz . G/Ç işlem hatları PipeReader.
HttpResponse
HttpContext.Response öğesine erişim HttpResponsesağlar. HttpResponse
, istemciye geri gönderilen HTTP yanıtıyla ilgili bilgileri ayarlamak için kullanılır.
Üzerinde HttpResponse
yaygın olarak kullanılan üyeler şunlardır:
Özellik | Açıklama | Örnek |
---|---|---|
HttpResponse.StatusCode | Yanıt kodu. Yanıt gövdesine yazmadan önce ayarlanmalıdır. | 200 |
HttpResponse.ContentType | Yanıt content-type üst bilgisi. Yanıt gövdesine yazmadan önce ayarlanmalıdır. |
application/json |
HttpResponse.Headers | Yanıt üst bilgileri koleksiyonu. Yanıt gövdesine yazmadan önce ayarlanmalıdır. | server=Kestrel x-custom-header=MyValue |
HttpResponse.Body | Stream Yanıt gövdesini yazmak için A. | Oluşturulan web sayfası |
Yanıt üst bilgilerini ayarlama
HttpResponse.Headers HTTP yanıtıyla gönderilen yanıt üst bilgilerine erişim sağlar. Bu koleksiyonu kullanarak üst bilgilere erişmenin iki yolu vardır:
- Üst bilgi koleksiyonundaki dizin oluşturucuya üst bilgi adını sağlayın. Üst bilgi adı büyük/küçük harfe duyarlı değildir. Dizin oluşturucu herhangi bir üst bilgi değerine erişebilir.
- Üst bilgi koleksiyonu, sık kullanılan HTTP üst bilgilerini alma ve ayarlama özelliklerine de sahiptir. Özellikler, üst bilgiye erişmek için hızlı, IntelliSense temelli bir yol sağlar.
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();
Yanıt başladıktan sonra uygulama üst bilgileri değiştiremez. Yanıt başladıktan sonra üst bilgiler istemciye gönderilir. Yanıt, yanıt gövdesi temizlenerek veya çağrılarak HttpResponse.StartAsync(CancellationToken)başlatılır. HttpResponse.HasStarted özelliği yanıtın başlatılıp başlatılmadığını gösterir. Yanıt başlatıldıktan sonra üst bilgileri değiştirmeye çalışılırken bir hata oluşur:
System.InvalidOperationException: Üst bilgiler salt okunur, yanıt zaten başlatıldı.
Not
Yanıt arabelleğe alma etkinleştirilmediği sürece, tüm yazma işlemleri (örneğin, WriteAsync) yanıt gövdesini dahili olarak temizler ve yanıtı başlatıldı olarak işaretler. Yanıt arabelleği varsayılan olarak devre dışıdır.
Yanıt gövdesi yazma
HTTP yanıtı bir yanıt gövdesi içerebilir. Yanıt gövdesi, oluşturulan web sayfası içeriği, UTF-8 JSON yükü veya bir dosya gibi yanıtla ilişkili verilerdir.
HttpResponse.Body yanıt gövdesinin ile Streamyazılmasına izin verir:
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
doğrudan yazılabilir veya bir akışa yazan diğer API'lerle birlikte kullanılabilir.
BodyWriter
Yanıt gövdesini yazmanın alternatif bir yolu özelliğini kullanmaktır HttpResponse.BodyWriter . BodyWriter
özelliği, yanıt gövdesini olarak PipeWriterkullanıma sunar. Bu API G/Ç işlem hatlarından ve yanıtı yazmanın gelişmiş, yüksek performanslı bir yoludur.
Yazıcı, yanıt gövdesine doğrudan erişim sağlar ve arayan adına belleği yönetir. 'nin aksine HttpResponse.Body
, yazma işlemi istek verilerini arabelleğe kopyalamaz. Ancak, bir yazıcının kullanımı, bir akış ve yazıcı kodunun kapsamlı bir şekilde test edilmesinden daha karmaşıktır.
öğesine içerik BodyWriter
yazma hakkında bilgi için bkz . G/Ç işlem hatları PipeWriter.
Yanıt fragmanlarını ayarlama
HTTP/2 ve HTTP/3, yanıt fragmanlarını destekler. Römorklar, yanıt gövdesi tamamlandıktan sonra yanıtla birlikte gönderilen üst bilgilerdir. Römorklar yanıt gövdesinden sonra gönderildiğinden, römorklar istediğiniz zaman yanıta eklenebilir.
Aşağıdaki kod, kullanarak AppendTrailerfragmanları ayarlar:
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
İptal HttpContext.RequestAborted belirteci, HTTP isteğinin istemci veya sunucu tarafından durdurulduğunu bildirmek için kullanılabilir. İstek durdurulduysa iptal edilebilmeleri için iptal belirteci uzun süre çalışan görevlere geçirilmelidir. Örneğin, yanıtta döndürülecek verileri almak için bir veritabanı sorgusunu veya HTTP isteğini iptal etme.
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();
İstek RequestAborted
durdurulduğunda okuma işlemleri her zaman hemen oluştuğundan iptal belirtecinin istek gövdesi okuma işlemleri için kullanılması gerekmez. RequestAborted
İstek durdurulduğunda hemen işlem yapılmadan yazdığından, yanıt gövdeleri yazılırken belirteç de genellikle gereksizdir.
Bazı durumlarda, belirteci yazma işlemlerine geçirmek RequestAborted
, bir yazma döngüsünü ile erken çıkmaya zorlamanın kullanışlı bir OperationCanceledExceptionyolu olabilir. Ancak, genellikle belirteci yanıt gövdesi içeriğini almaktan sorumlu zaman uyumsuz işlemlere geçirmek RequestAborted
daha iyidir.
Not
Minimum API'ler doğrudan bir CancellationToken parametreye bağlamayı HttpContext.RequestAborted destekler.
Abort()
yöntemi, HttpContext.Abort() sunucudan gelen bir HTTP isteğini durdurmak için kullanılabilir. HTTP isteğinin iptali hemen iptal belirtecini HttpContext.RequestAborted tetikler ve istemciye sunucunun isteği durdurduğunu belirten bir bildirim gönderir.
Aşağıdaki örnekteki ara yazılım:
- Kötü amaçlı istekler için özel bir denetim ekler.
- İstek kötü amaçlıysa HTTP isteğini durdurur.
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
HttpContext.User özelliği, istek için tarafından temsil edilen ClaimsPrincipalkullanıcıyı almak veya ayarlamak için kullanılır. ClaimsPrincipal genellikle ASP.NET Core kimlik doğrulaması tarafından ayarlanır.
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();
Not
Minimum API'ler doğrudan bir ClaimsPrincipal parametreye bağlamayı HttpContext.User destekler.
Features
özelliği, HttpContext.Features geçerli istek için özellik arabirimleri koleksiyonuna erişim sağlar. Özellik koleksiyonu bir istek bağlamında bile değişebilir olduğundan, ara yazılım koleksiyonu değiştirmek ve ek özellikler için destek eklemek için kullanılabilir. Bazı gelişmiş özellikler yalnızca özellik koleksiyonu aracılığıyla ilişkili arabirime erişilerek kullanılabilir.
Aşağıdaki örnek:
- Özellikler koleksiyonundan alır IHttpMinRequestBodyDataRateFeature .
- Null olarak ayarlanır MinDataRate . Bu, istek gövdesinin bu HTTP isteği için istemci tarafından gönderilmesi gereken en düşük veri hızını kaldırır.
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();
ve HttpContext
istek özelliklerini kullanma hakkında daha fazla bilgi için bkz . ASP.NET Core'da İstek Özellikleri.
HttpContext iş parçacığı güvenli değil
Bu makalede öncelikle Sayfalar, denetleyiciler, ara yazılım vb. istek ve yanıt akışında Razor kullanımı HttpContext
ele alınmaktadır. İstek ve yanıt akışının dışında kullanırken HttpContext
aşağıdakileri göz önünde bulundurun:
HttpContext
İş parçacığı güvenli DEĞİlDİ, birden çok iş parçacığından erişildiğinde özel durumlara, veri bozulmasına ve genel olarak öngörülemeyen sonuçlara neden olabilir.- Arabirim IHttpContextAccessor dikkatli kullanılmalıdır. Her zaman olduğu gibi,
HttpContext
istek akışının dışında yakalanmamalıdır.IHttpContextAccessor
:- Zaman uyumsuz çağrılar AsyncLocal<T> üzerinde olumsuz bir performans etkisine sahip olabilecek değerlerdir.
- Testi daha zor hale getirebilecek bir "ortam durumu" bağımlılığı oluşturur.
- IHttpContextAccessor.HttpContext , istek akışının dışından erişilirse olabilir
null
. - İstek akışının dışından
HttpContext
bilgilere erişmek için, bilgileri istek akışının içine kopyalayın. Yalnızca başvuruları değil gerçek verileri kopyalamaya dikkat edin. Örneğin, başvuruyu birIHeaderDictionary
öğesine kopyalamak yerine ilgili üst bilgi değerlerini kopyalayın veya istek akışından çıkmadan önce anahtara göre sözlük anahtarının tamamını kopyalayın. - Oluşturucuda yakalama
IHttpContextAccessor.HttpContext
.
Aşağıdaki örnek, uç noktadan istendiğinde GitHub dallarını günlüğe /branch
kaydeder:
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();
GitHub API'sinde iki üst bilgi gerekir. User-Agent
Üst bilgi, tarafından UserAgentHeaderHandler
dinamik olarak eklenir:
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();
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);
}
}
Yukarıdaki kodda, HttpContext
olduğunda null
userAgent
dize olarak "Unknown"
ayarlanır. Mümkünse, HttpContext
hizmete açıkça geçirilmelidir. Verileri açıkça geçirme HttpContext
:
- Hizmet API'sini istek akışının dışında daha kullanılabilir hale getirir.
- Performans için daha iyidir.
- Kodun anlaşılmasını ve anlaşılmasını, ortam durumuna bağlı olmaktan daha kolay hale getirir.
Hizmetin erişmesi HttpContext
gerektiğinde, istek iş parçacığından çağrılmama olasılığını HttpContext
null
hesaba eklemelidir.
Uygulama, belirtilen deponun açık GitHub dallarını 30 saniyede bir günlüğe kaydeden öğesini de içerir PeriodicBranchesLoggerService
:
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
, istek ve yanıt akışının dışında çalışan barındırılan bir hizmettir. 'den günlüğe PeriodicBranchesLoggerService
kaydetmenin null HttpContext
değeri vardır. , PeriodicBranchesLoggerService
öğesine bağlı HttpContext
değil olarak yazılmıştır.
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 =>
{
ASP.NET Core