Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Not
Bu, bu makalenin en son sürümü değildir. Geçerli sürüm için bu makalenin .NET 10 sürümüne bakın.
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 9 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 s, Web API denetleyicileri, SayfalarBlazor Web App, gRPC ve daha fazlası gibi Razorara yazılım ve uygulama çerçeveleri SignalR tarafından erişilebilir.
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=Edgex-custom-header=MyValue |
| HttpRequest.RouteValues | Yol değerleri koleksiyonu. İstek bir yolla eşleştirildiğinde koleksiyon ayarlanır. | language=enarticle=getstarted |
| HttpRequest.Query | 'den QueryStringayrıştırılan sorgu değerleri koleksiyonu. | filter=hellopage=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 HttpRequest.Body parametreye bağlamayı Stream 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
EnableBufferingbirden ç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 BodyReaderiç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=Kestrelx-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.
- Sık kullanılan HTTP üst bilgilerini almak ve ayarlamak için üst bilgi koleksiyonu özelliklerini kullanın. Ö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 BodyWriteryazma 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 HttpContext.RequestAborted parametreye bağlamayı CancellationToken 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 HttpContext.User parametreye bağlamayı ClaimsPrincipal 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 HttpContextistek ö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 HttpContext bileşeni, Blazor Web App Sayfaları, denetleyiciler, ara yazılımlar ve benzerlerinin istek ve yanıt akışında kullanımı Razor ele alınmaktadır. İstek ve yanıt akışının dışında kullanırken HttpContext aşağıdakileri göz önünde bulundurun:
-
HttpContexteşzamanlılık açısından güvenli değildir. Birden çok iş parçacığından erişim, özel durumlar ve veri bozulması gibi öngörülemeyen sonuçlara neden olabilir. - Arabirim IHttpContextAccessor dikkatli kullanılmalıdır. Her zaman olduğu gibi,
HttpContextistek akışının dışında yakalanmamalıdır.IHttpContextAccessor:- AsyncLocal<T> üzerinde olumsuz bir performans etkisi yaratabilecek olan zaman uyumsuz çağrılara dayanır.
- Testi daha zor hale getirebilecek bir "ortam durumu" bağımlılığı oluşturur.
-
IHttpContextAccessor.HttpContext istek akışının dışından erişilirse
nullolabilir. - İstek akışının dışından
HttpContextbilgilere 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 UserAgentHeaderHandlerdinamik 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 nulluserAgent 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 HttpContextgerektiğinde, istek iş parçacığından çağrılmama olasılığını HttpContextnull 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 HttpContextdeğeri vardır. , PeriodicBranchesLoggerService öğesine bağlı HttpContextdeğ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 =>
{
Ek kaynaklar
erişimi HttpContexthakkında daha fazla bilgi için bkz. ASP.NET Core'da HttpContext'e erişme.
ASP.NET Core