Aracılığıyla paylaş


ASP.NET Core 9.0'daki yenilikler

Bu makalede, ASP.NET Core 9.0'daki en önemli değişiklikler ilgili belgelerin bağlantıları ile vurgulanır.

Statik içerik teslimatını iyileştirme

MapStaticAssets yönlendirme uç noktası kuralları , ASP.NET Core uygulamalarında statik varlıkların teslimini en iyi duruma getiren yeni bir özelliktir.

Blazor uygulamaları için statik varlık teslimi hakkında bilgi için bkz: ASP.NET Core Blazor statik dosyalar.

Statik varlıklara hizmet vermek için üretim için en iyi yöntemlerin takip etmek için önemli miktarda iş ve teknik uzmanlık gerekir. Sıkıştırma, önbelleğe alma ve parmak izi gibi iyileştirmeler olmadan:

  • Tarayıcının her sayfa yüklemesinde ek istekler yapması gerekir.
  • Gerekenden daha fazla bayt ağ üzerinden aktarılır.
  • Bazen dosyaların eski sürümleri istemcilere sunulur.

Yüksek performanslı web uygulamaları oluşturmak için tarayıcıya varlık tesliminin iyileştirilmesi gerekir. Olası iyileştirmeler şunlardır:

  • Dosya değişene veya tarayıcı önbelleğini temizleyene kadar belirli bir varlığa bir kez hizmet verin. ETag üst bilgisini ayarlayın.
  • Bir uygulama güncelleştirildikten sonra tarayıcının eski veya eski varlıkları kullanmasını engelleyin. Son Değiştirme üst bilgisini ayarlayın.
  • Uygun önbelleğe alma üst bilgilerini ayarlayın.
  • Önbelleğe alma ara yazılımını kullanın.
  • Mümkün olduğunda varlıkların sıkıştırılmış sürümlerini sunma.
  • Varlıkları kullanıcıya daha yakın bir şekilde sunmak için CDN kullanın.
  • Tarayıcıya sunulan varlıkların boyutunu en aza indirin. Bu iyileştirme, küçültmeyi içermez.

MapStaticAssets bir uygulamadaki statik varlıkların teslimini en iyi duruma getiren yeni bir özelliktir. , Blazor Pages ve MVC dahil olmak üzere Razortüm kullanıcı arabirimi çerçeveleriyle çalışacak şekilde tasarlanmıştır. Genellikle UseStaticFiles için doğrudan bir yedektir.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseRouting();

app.UseAuthorization();

+app.MapStaticAssets();
-app.UseStaticFiles();
app.MapRazorPages();

app.Run();

MapStaticAssets bir uygulamadaki tüm statik kaynaklar hakkında bilgi toplamak için derleme ve yayımlama zamanı işlemlerini birleştirerek çalışır. Bu bilgiler daha sonra çalışma zamanı kitaplığı tarafından bu dosyaları tarayıcıya verimli bir şekilde sunmak için kullanılır.

MapStaticAssets çoğu durumda yerini UseStaticFiles alabilir, ancak uygulamanın derleme ve yayımlama zamanında bilgi sahibi olduğu varlıklara hizmet etmek için iyileştirilmiştir. Uygulama, disk veya gömülü kaynaklar gibi farklı konumlardan varlıklar sağlıyorsa, UseStaticFiles kullanılmalıdır.

MapStaticAssets ile UseStaticFilesbulunmayan aşağıdaki avantajları sağlar:

  • Uygulamadaki tüm kayıtların derleme süresi sıkıştırması:
    • gzip geliştirme sırasında ve gzip + brotli yayımlama sırasında.
    • Tüm varlıklar, varlıkların boyutunu en aza indirme hedefiyle sıkıştırılır.
  • İçerik tabanlı ETags: Her kaynağın Etags içeriğinin SHA-256 karmasının Base64 ile kodlanmış dizgesidir. Bu, tarayıcının yalnızca içeriği değiştirilmişse dosyayı yeniden indirmesini sağlar.

Aşağıdaki tabloda, varsayılan JS Sayfalar şablonundaki CSS ve dosyaların özgün ve Razor sıkıştırılmış boyutları gösterilmektedir:

Dosya Özgün Sıkıştırılmış Azaltma Yüzdesi
bootstrap.min.css 163 17.5 89.26%
jquery.js 89.6 28 68.75%
bootstrap.min.js 78,5 20 74.52%
Toplam 331.1 65.5 80.20%

Aşağıdaki tabloda Fluent UI Blazor bileşenleri kitaplığı kullanılarak özgün ve sıkıştırılmış boyutlar gösterilmektedir:

Dosya Özgün Sıkıştırılmış Azaltma Yüzdesi
fluent.js 384 73 80.99%
fluent.css 94 11 88.30%
Toplam 478 84 82.43%

Toplam 478 KB sıkıştırılmamış ve 84 KB sıkıştırılmış için.

Aşağıdaki tabloda MudBlazor bileşen kütüphanesini kullanarak orijinal ve sıkıştırılmış boyutlar gösterilmektedir:

Dosya Özgün Sıkıştırılmış Azaltma
MudBlazor.min.css 541 37,5 93.07%
MudBlazor.min.js 47.4 9.2 80.59%
Toplam 588,4 46,7 92.07%

İyileştirme, kullanılırken MapStaticAssetsotomatik olarak gerçekleşir. Yeni JavaScript veya CSS gibi bir kitaplık eklendiğinde veya güncelleştirildiğinde, kaynaklar derlemenin bir parçası olarak optimize edilir. İyileştirme, daha düşük bant genişliğine veya güvenilir olmayan bağlantılara sahip olabilecek mobil ortamlar için özellikle yararlıdır.

Yeni dosya teslim özellikleri hakkında daha fazla bilgi için aşağıdaki kaynaklara bakın:

Sunucuda dinamik sıkıştırmayı etkinleştirme ile kullanma karşılaştırması

MapStaticAssets , sunucuda dinamik sıkıştırmaya göre aşağıdaki avantajlara sahiptir:

  • Sunucuya özgü bir yapılandırma olmadığından daha basittir.
  • Kaynaklar derleme zamanında sıkıştırıldığı için daha fazla performans gösterir.
  • Geliştiricilerin, varlıkların minimum boyuta sahip olduğundan emin olmak için derleme işlemi sırasında fazladan zaman harcamasına olanak tanır.

MudBlazor sıkıştırmasını IIS dinamik sıkıştırma ve MapStaticAssetsile karşılaştıran aşağıdaki tabloyu göz önünde bulundurun:

IIS gzip MapStaticAssets MapStaticAssets azaltma
≅ 90 37,5 59%

Blazor

Bu bölümde için Blazoryeni özellikler açıklanmaktadır.

.NET MAUI Blazor Hybrid ve Web App çözüm şablonu

Yeni bir çözüm şablonu, aynı kullanıcı arabirimini paylaşan yerel ve .NET MAUI web istemcisi uygulamaları oluşturmayı Blazor kolaylaştırır. Bu şablonda kodun yeniden kullanılmasını en üst düzeye çıkaran ve Android, iOS, Mac, Windows ve Web'i hedefleyen istemci uygulamalarının nasıl oluşturulacağı gösterilmektedir.

Bu şablonun temel özellikleri şunlardır:

  • Web uygulaması için etkileşimli bir Blazor işleme modu seçme özelliği.
  • Uygun projelerin otomatik oluşturulması, Blazor Web App (genel Etkileşimli Otomatik işleme) ve bir .NET MAUIBlazor Hybrid uygulaması dahil olmak üzere.
  • Oluşturulan projeler, kullanıcı arabiriminin Razor bileşenlerini korumak için paylaşılan Razor bir sınıf kitaplığı (RCL) kullanır.
  • Blazor Hybrid uygulaması ve Blazor Web App için farklı arabirim uygulamaları sağlamak amacıyla bağımlılık enjeksiyonu nasıl kullanılır gösteren örnek kod eklenmiştir.

Başlamak için .NET 9 SDK'sını .NET MAUI yükleyin ve şablonu içeren iş yükünü yükleyin:

dotnet workload install maui

Aşağıdaki komutu kullanarak komut kabuğunda proje şablonundan bir çözüm oluşturun:

dotnet new maui-blazor-web

Şablon Visual Studio'da da kullanılabilir.

Not

Şu anda, işleme modları sayfa başına/bileşen düzeyinde tanımlanmışsa Blazor bir özel durum oluşur. Daha fazla bilgi için bkz . BlazorWebView, ResolveComponentForRenderMode (dotnet/aspnetcore #51235) geçersiz kılmayı etkinleştirmek için bir yönteme ihtiyaç duyar.

Daha fazla bilgi için bkz: .NET MAUIBlazor Hybrid uygulama oluşturma Blazor Web App ile.

Çalışma zamanında işleme konumunu, etkileşimini ve atanan işleme modunu algılama

Çalışma zamanında bileşen durumlarını sorgulama işlemini basitleştirmek için tasarlanmış yeni bir API kullanıma sunulmuştur. Bu API aşağıdaki özellikleri sağlar:

  • Bileşenin geçerli yürütme konumunu belirleyin: Bu, hata ayıklama ve bileşen performansını iyileştirme için yararlı olabilir.
  • Bileşenin etkileşimli bir ortamda çalışıp çalışmadığını denetleyin: Bu, ortamlarının etkileşimi temelinde farklı davranışlara sahip bileşenler için yararlı olabilir.
  • Bileşen için atanan işleme modunu alma: İşleme modunu anlamak, işleme işlemini iyileştirmeye ve bir bileşenin genel performansını iyileştirmeye yardımcı olabilir.

Daha fazla bilgi için bkz . ASP.NET Core Blazor işleme modları.

Geliştirilmiş sunucu tarafı yeniden bağlantı deneyimi:

Varsayılan sunucu tarafı yeniden bağlantı deneyiminde aşağıdaki geliştirmeler yapılmıştır:

  • Kullanıcı bağlantısı kesilmiş bir uygulamaya geri döndüğünde, bir sonraki yeniden bağlantı aralığının süresini beklemek yerine hemen yeniden bağlanma denenir. Bu, uyku moduna geçmiş bir tarayıcı sekmesindeki bir uygulamaya gidildiğinde kullanıcı deneyimini geliştirir.

  • Yeniden bağlanma girişimi sunucuya ulaştığında ancak sunucu devreyi zaten serbest bıraktığında, otomatik olarak bir sayfa yenilemesi gerçekleşir. Bu, büyük olasılıkla yeniden bağlantının başarılı olmasına neden olacaksa kullanıcının sayfayı el ile yenilemesini önler.

  • Yeniden bağlanma zamanlaması hesaplanan geri alma stratejisini kullanır. Varsayılan olarak, ilk birkaç yeniden bağlantı girişimi, denemeler arasında hesaplanan gecikmeler ortaya çıkmadan önce yeniden deneme aralığı olmadan hızlı bir şekilde gerçekleşir. Aşağıdaki üstel geri alma örneğinde gösterildiği gibi yeniden deneme aralığını hesaplamak için bir işlev belirterek yeniden deneme aralığı davranışını özelleştirebilirsiniz:

    Blazor.start({
      circuit: {
        reconnectionOptions: {
          retryIntervalMilliseconds: (previousAttempts, maxRetries) => 
            previousAttempts >= maxRetries ? null : previousAttempts * 1000
        },
      },
    });
    
  • Varsayılan yeniden bağlantı kullanıcı arabiriminin stili modernleştirildi.

Daha fazla bilgi için bkz . ASP.NET Temel BlazorSignalR kılavuzu.

Blazor Web App'ler için basitleştirilmiş kimlik doğrulama durumu serileştirmesi

Yeni API'ler, mevcut Blazor Web Appbir öğesine kimlik doğrulaması eklemeyi kolaylaştırır. Bireysel Hesaplar ile kimlik doğrulaması kullanarak yeni bir oluşturduğunuzda ve WebAssembly tabanlı etkileşimi etkinleştirdiğinizde, proje hem sunucu hem de istemci projelerinde özel bir içerir.

Bu sağlayıcılar kullanıcının kimlik doğrulama durumunu tarayıcıya akıtıyor. İstemci yerine sunucuda kimlik doğrulaması, uygulamanın ön kayıt sırasında ve .NET WebAssembly çalışma zamanı başlatılmadan önce kimlik doğrulama durumuna erişmesine olanak tanır.

Özel AuthenticationStateProvider uygulamalar, kimlik doğrulama durumunu HTML yorumlarına dönüştürmek ve WebAssembly'den geri okuyarak yeni bir AuthenticationState örneği oluşturmak için Kalıcı Bileşen Durumu hizmetini kullanır (PersistentComponentState).

Bu, Blazor Web App proje şablonundan başlayıp Bireysel Hesaplar seçeneğini belirlediyseniz iyi çalışır, ancak mevcut bir projeye kimlik doğrulaması eklemeye çalışırken kendiniz uygulamak veya kopyalamak için çok fazla kod vardır. Artık proje şablonunun parçası Blazor Web App olan ve bu işlevselliği eklemek için sunucu ve istemci projelerinde çağrılabilen API'ler vardır:

Varsayılan olarak, API yalnızca tarayıcıdaki erişim için sunucu tarafı adını ve rol taleplerini serileştirir. Tüm talepleri dahil etmek için bir seçenek (AddAuthenticationStateSerialization) geçirilebilir.

Daha fazla bilgi için ASP.NET Core Blazor kimlik doğrulaması ve yetkilendirmesinin aşağıdaki bölümlerine bakın:

Genel olarak etkileşimli bir sayfaya statik sunucu tarafı işleme (SSR) sayfaları ekleme Blazor Web App

.NET 9 sürümüyle, genel etkileşimi benimseyen uygulamalara statik SSR sayfaları eklemek artık daha kolay.

Bu yaklaşım, uygulamanın etkileşimli Sunucu veya WebAssembly işleme ile çalışamayan belirli sayfaları olduğunda faydalıdır. Örneğin, HTTP tanımlama bilgilerini okuma/yazmaya bağlı olan ve etkileşimli işleme yerine yalnızca istek/yanıt döngüsünde çalışabilen sayfalar için bu yaklaşımı benimseyin. Etkileşimli işleme ile çalışan sayfalar için, son kullanıcı için daha az verimli ve daha az yanıt veren olduğundan, bunları statik SSR işleme kullanmaya zorlamamalısınız.

Yeni [ExcludeFromInteractiveRouting] özniteliğiyle@attributeRazor yönergesi atanmış herhangi bir Razor bileşen sayfasını işaretleyin.

@attribute [ExcludeFromInteractiveRouting]

Bu özniteliğin uygulanması, sayfa navigasyonunun etkileşimli yönlendirmeden çıkmasına neden olur. Gelen gezinti, etkileşimli yönlendirme yoluyla sayfayı çözümlemek yerine tam sayfa yeniden yükleme gerçekleştirmeye zorlanır. Tam sayfa yeniden yükleme, genellikle App bileşeni ()App.razor olan üst düzey kök bileşeni sunucudan yeniden yüklemeye zorlayarak uygulamanın farklı bir üst düzey işleme moduna geçmesini sağlar.

RazorComponentsEndpointHttpContextExtensions.AcceptsInteractiveRouting uzantı yöntemi, bileşenin özniteliğin [ExcludeFromInteractiveRouting] geçerli sayfaya uygulanıp uygulanmadığını algılamasına olanak tanır.

Bileşeninde App , aşağıdaki örnekteki deseni kullanın:

  • [ExcludeFromInteractiveRouting] özniteliği ile ek açıklama eklenmemiş sayfalar, varsayılan olarak InteractiveServer genel etkileşimli işleme modunda çalışır. InteractiveServer öğesini InteractiveWebAssembly veya InteractiveAuto ile değiştirerek farklı bir varsayılan genel işleme modu belirtebilirsiniz.
  • [ExcludeFromInteractiveRouting] özniteliğiyle etiketlenmiş sayfalar, statik SSR'yi benimser (PageRenderModenull olarak atanır).
<!DOCTYPE html>
<html>
<head>
    ...
    <HeadOutlet @rendermode="@PageRenderMode" />
</head>
<body>
    <Routes @rendermode="@PageRenderMode" />
    ...
</body>
</html>

@code {
    [CascadingParameter]
    private HttpContext HttpContext { get; set; } = default!;

    private IComponentRenderMode? PageRenderMode
        => HttpContext.AcceptsInteractiveRouting() ? InteractiveServer : null;
}

RazorComponentsEndpointHttpContextExtensions.AcceptsInteractiveRouting uzantı yöntemini kullanmanın bir alternatifi, HttpContext.GetEndpoint()?.Metadata kullanarak uç nokta meta verilerini el ile okumaktır.

Bu özellik, ASP.NET Core Blazor işleme modlarındaki başvuru belgeleri kapsamındadır.

Yapıcı enjeksiyonu

Razor bileşenler oluşturucu enjeksiyonunu destekler.

Aşağıdaki örnekte, kısmi (kod arkası) sınıfı birincil oluşturucu kullanarak NavigationManager hizmeti enjekte ediyor.

public partial class ConstructorInjection(NavigationManager navigation)
{
    private void HandleClick()
    {
        navigation.NavigateTo("/counter");
    }
}

Daha fazla bilgi için bkz . ASP.NET Core Blazor bağımlılık ekleme.

Etkileşimli Sunucu bileşenleri için Websocket sıkıştırması

Varsayılan olarak, Etkileşimli Sunucu bileşenleri WebSocket bağlantıları için sıkıştırmayı etkinleştirir ve İçerik Güvenliği Politikası (CSP) talimatlarını 'self' olarak ayarlar. Sıkıştırma etkinleştirildiğinde veya WebSocket bağlamı için bir yapılandırma sağlandığında, uygulamanın sadece sunulduğu kaynağın bir <iframe> içine yerleştirilmesine izin verir.

Sıkıştırma, ConfigureWebSocketOptions olarak null ayarlandığında devre dışı bırakılabilir, bu da uygulamanın saldırıya karşı güvenlik açığını azaltır ancak performansı düşürebilir.

.AddInteractiveServerRenderMode(o => o.ConfigureWebSocketOptions = null)

WebSocket sıkıştırmasına izin veren, ancak tarayıcıların uygulamayı herhangi bir frame-ancestors içine eklemesini engelleyen daha katı bir <iframe> CSP'yi, (tek tırnak gereklidir) 'none' değeriyle yapılandırın:

.AddInteractiveServerRenderMode(o => o.ContentSecurityFrameAncestorsPolicy = "'none'")

Daha fazla bilgi edinmek için aşağıdaki kaynaklara bakın:

Blazor uygulamasında klavye kompozisyonu olaylarını işleyin

Yeni KeyboardEventArgs.IsComposing özellik, klavye olayının bir oluşturma oturumunun parçası olup olmadığını gösterir. Klavye olaylarının oluşturma durumunu izlemek, uluslararası karakter giriş yöntemlerini işlemek için çok önemlidir.

OverscanCount özelliğine QuickGrid parametresi eklendi

QuickGrid Bileşen artık sanallaştırma etkinleştirildiğinde görünür bölgeden önce ve sonra kaç ek satırın işlendiğini belirten bir OverscanCount özellik kullanıma sunar.

Varsayılan OverscanCount değer 3'dür. Aşağıdaki örnek değerini 4'e OverscanCount yükseltir:

<QuickGrid ItemsProvider="itemsProvider" Virtualize="true" OverscanCount="4">
    ...
</QuickGrid>

InputNumber bileşeni özniteliğini type="range" destekler

Bileşen InputNumber<TValue> artık, genellikle metin kutusu yerine kaydırıcı veya kadran kontrolü olarak işlenen ve model bağlamayı ve form doğrulamayı destekleyen bir aralık girişi oluşturan type="range" özniteliğini destekler:

<EditForm Model="Model" OnSubmit="Submit" FormName="EngineForm">
    <div>
        <label>
            Nacelle Count (2-6): 
            <InputNumber @bind-Value="Model!.NacelleCount" max="6" min="2" 
                step="1" type="range" />
        </label>
    </div>
    <div>
        <button type="submit">Submit</button>
    </div>
</EditForm>

@code {
    [SupplyParameterFromForm]
    private EngineSpecifications? Model { get; set; }

    protected override void OnInitialized() => Model ??= new();

    private void Submit() {}

    public class EngineSpecifications
    {
        [Required, Range(minimum: 2, maximum: 6)]
        public int NacelleCount { get; set; }
    }
}

Yeni gelişmiş gezinti olayları

Yeni olay dinleyicileriyle gelişmiş gezinti öncesinde veya sonrasında JavaScript geri çağırmalarını tetikleme:

  • blazor.addEventListener("enhancednavigationstart", {CALLBACK})
  • blazor.addEventListener("enhancednavigationend", {CALLBACK})

Daha fazla bilgi için bkz. ASP.NET Core Blazor JavaScript ile statik sunucu tarafı işleme (statik SSR).

İstemci tarafında istek akışı

Blazor'de Etkileşimli WebAssembly işleme artık HttpRequestMessageüzerindeki request.SetBrowserReqeustStreamingEnabled(true) seçeneğini kullanarak istemci taraflı istek akışını destekliyor.

Daha fazla bilgi edinmek için aşağıdaki kaynaklara bakın:

SignalR

Bu bölümde için SignalRyeni özellikler açıklanmaktadır.

Hub'larda SignalR polimorfik tür desteği

Hub yöntemleri artık çok biçimli senaryoları etkinleştirmek için türetilmiş sınıf yerine bir temel sınıfı kabul edebilir. Çok biçimliliğe izin vermek için taban türüne açıklama eklenmelidir.

public class MyHub : Hub
{
    public void Method(JsonPerson person)
    {
        if (person is JsonPersonExtended)
        {
        }
        else if (person is JsonPersonExtended2)
        {
        }
        else
        {
        }
    }
}

[JsonPolymorphic]
[JsonDerivedType(typeof(JsonPersonExtended), nameof(JsonPersonExtended))]
[JsonDerivedType(typeof(JsonPersonExtended2), nameof(JsonPersonExtended2))]
private class JsonPerson
{
    public string Name { get; set; }
    public Person Child { get; set; }
    public Person Parent { get; set; }
}

private class JsonPersonExtended : JsonPerson
{
    public int Age { get; set; }
}

private class JsonPersonExtended2 : JsonPerson
{
    public string Location { get; set; }
}

SignalR için Geliştirilmiş Etkinlikler

SignalR artık hem merkez sunucusu hem de istemci için bir ActivitySource'a sahip.

.NET SignalR sunucusu ActivitySource

SignalR olarak adlandırılan Microsoft.AspNetCore.SignalR.Server ActivitySource, hub metodu çağrıları için olayları tetikler.

  • Her yöntem kendi etkinliğidir, bu nedenle hub yöntemi çağrısı sırasında bir etkinlik yayan her şey hub yöntemi etkinliğinin altındadır.
  • Hub yöntemi etkinliklerinin üst öğesi yoktur. Bu, uzun süre çalışan SignalR bağlantı altında paketlenmedikleri anlamına gelir.

Aşağıdaki örnek, .NET Aspire gösterge paneli ve OpenTelemetry paketlerini kullanır:

<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.9.0" />

Dosyaya aşağıdaki başlangıç kodunu Program.cs ekleyin:

using OpenTelemetry.Trace;
using SignalRChat.Hubs;

// Set OTEL_EXPORTER_OTLP_ENDPOINT environment variable depending on where your OTEL endpoint is.
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddSignalR();

builder.Services.AddOpenTelemetry()
    .WithTracing(tracing =>
    {
        if (builder.Environment.IsDevelopment())
        {
            // View all traces only in development environment.
            tracing.SetSampler(new AlwaysOnSampler());
        }

        tracing.AddAspNetCoreInstrumentation();
        tracing.AddSource("Microsoft.AspNetCore.SignalR.Server");
    });

builder.Services.ConfigureOpenTelemetryTracerProvider(tracing => tracing.AddOtlpExporter());

var app = builder.Build();

Aşağıda Aspire Panosu'ndan alınan örnek çıkış verilmiştir:

Hub yöntemi çağrı olayları için SignalR etkinlik listesi

.NET SignalR istemcisi ActivitySource

SignalR adlı Microsoft.AspNetCore.SignalR.Client ActivitySource, SignalR istemcisi için olayları yayar:

  • .NET SignalR istemcisinin ActivitySourceadlı bir Microsoft.AspNetCore.SignalR.Client vardır. Hub çağrıları artık bir istemci yayılma alanı oluşturur. JavaScript istemcisi gibi diğer SignalR istemcilerinin izlemeyi desteklemediğini unutmayın. Bu özellik, gelecek sürümlerde daha fazla istemciye eklenecektir.
  • İstemci ve sunucudaki hub çağrıları bağlam yaymadestekler. İzleme bağlamını yaymak, gerçek dağıtılmış izlemeyi etkinleştirir. Artık çağrıların istemciden sunucuya ve geriye doğru akışını görmek mümkündür.

İşte bu yeni etkinliklerin .NET Aspire kontrol panelinde nasıl göründüğü:

Aspire panosunda SignalR dağıtılmış izleme

SignalR kırpmayı ve Doğal AOT'yi destekler

.NET 8'de başlayan Yerel AOT yolculuğuna devam ederek, hem istemci hem de SignalR sunucu senaryoları için kırpmayı ve yerel önceden derlemeyi (AOT) destekleyecek şekilde etkinleştirdik. Artık gerçek zamanlı web iletişimleri için kullanılan uygulamalarda Yerel AOT kullanmanın SignalR performans avantajlarından yararlanabilirsiniz.

Başlangıç Adımları

En son .NET 9 SDK'sını yükleyin.

Aşağıdaki komutu kullanarak komut kabuğundaki şablondan webapiaot bir çözüm oluşturun:

dotnet new webapiaot -o SignalRChatAOTExample

Dosyanın içeriğini Program.cs aşağıdaki SignalR kodla değiştirin:

using Microsoft.AspNetCore.SignalR;
using System.Text.Json.Serialization;

var builder = WebApplication.CreateSlimBuilder(args);

builder.Services.AddSignalR();
builder.Services.Configure<JsonHubProtocolOptions>(o =>
{
    o.PayloadSerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
});

var app = builder.Build();

app.MapHub<ChatHub>("/chatHub");
app.MapGet("/", () => Results.Content("""
<!DOCTYPE html>
<html>
<head>
    <title>SignalR Chat</title>
</head>
<body>
    <input id="userInput" placeholder="Enter your name" />
    <input id="messageInput" placeholder="Type a message" />
    <button onclick="sendMessage()">Send</button>
    <ul id="messages"></ul>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/8.0.7/signalr.min.js"></script>
    <script>
        const connection = new signalR.HubConnectionBuilder()
            .withUrl("/chatHub")
            .build();

        connection.on("ReceiveMessage", (user, message) => {
            const li = document.createElement("li");
            li.textContent = `${user}: ${message}`;
            document.getElementById("messages").appendChild(li);
        });

        async function sendMessage() {
            const user = document.getElementById("userInput").value;
            const message = document.getElementById("messageInput").value;
            await connection.invoke("SendMessage", user, message);
        }

        connection.start().catch(err => console.error(err));
    </script>
</body>
</html>
""", "text/html"));

app.Run();

[JsonSerializable(typeof(string))]
internal partial class AppJsonSerializerContext : JsonSerializerContext { }

public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}

Yukarıdaki örnek, 10 MB'lık yerel bir Windows yürütülebilir dosyası ve 10,9 MB Linux yürütülebilir dosyası oluşturur.

Sınırlamalar

  • Şu anda yalnızca JSON protokolü desteklenmektedir:
    • Önceki kodda gösterildiği gibi, JSON serileştirme ve Yerel AOT kullanan uygulamaların Kaynak Oluşturucu'ya sahip System.Text.Json olması gerekir.
    • Bu, minimum API'ler ile aynı yaklaşımı izler.
  • SignalR sunucusunda, türü IAsyncEnumerable<T> ve ChannelReader<T> olan ve T bir ValueType (struct) olan Hub yöntemi parametreleri desteklenmez. Bu türlerin kullanılması, geliştirme aşamasında ve yayımlanan uygulamada başlangıçta bir çalışma zamanı özel durumuyla sonuçlanır. Daha fazla bilgi için, bkz: SignalR: Yerel AOT'de ValueTypes ile IAsyncEnumerable<T> ve ChannelReader<T> kullanımı (dotnet/aspnetcore #56179).
  • Güçlü bir şekilde yazılan hub'lar, Native AOT (PublishAot) ile desteklenmez. Yerel AOT ile kesin olarak yazılan hub'ların kullanılması derleme ve yayımlama sırasında uyarılarla ve çalışma zamanı özel durumuyla sonuçlanır. Kesin olarak belirlenmiş hub'ların kırpma (PublishedTrimmed) ile kullanılması desteklenir.
  • Yalnızca Task, Task<T>, ValueTaskveya ValueTask<T> zaman uyumsuz dönüş türleri için desteklenir.

Minimal API'ler

Bu bölümde en düşük API'lere yönelik yeni özellikler açıklanmaktadır.

InternalServerError ve InternalServerError<TValue>, TypedResults'ye eklendi

sınıfı TypedResults , minimum API'den kesin olarak türlenmiş HTTP durum kodu tabanlı yanıtlar döndürmek için yararlı bir araçtır. TypedResults artık uç noktalardan "500 İç Sunucu Hatası" yanıtı döndürmek için fabrika yöntemlerini ve türlerini içerir. Aşağıda 500 yanıt döndüren bir örnek verilmişti:

var app = WebApplication.Create();

app.MapGet("/", () => TypedResults.InternalServerError("Something went wrong!"));

app.Run();

Arama ProducesProblem ve ProducesValidationProblem rota gruplarında

ProducesProblem ve ProducesValidationProblem uzantı yöntemleri, yol gruplarında kullanımını destekleyecek şekilde güncelleştirildi. Bu yöntemler, bir yol grubundaki tüm uç noktaların, OpenAPI meta verilerinin amaçları doğrultusunda ProblemDetails veya ValidationProblemDetails yanıtları döndürebileceğini belirtir.

var app = WebApplication.Create();

var todos = app.MapGroup("/todos")
    .ProducesProblem();

todos.MapGet("/", () => new Todo(1, "Create sample app", false));
todos.MapPost("/", (Todo todo) => Results.Ok(todo));

app.Run();

record Todo(int Id, string Title, boolean IsCompleted);

Problem ve ValidationProblem sonuç türleri, IEnumerable<KeyValuePair<string, object?>> değerleri ile yapıyı destekler.

.NET 9'dan önce, minimal API'lerde Problem ve ValidationProblem sonuç türlerini oluşturmak için, errors ve extensions özelliklerinin bir IDictionary<string, object?> implementasyonu ile başlatılması gerekiyordu. Bu sürümde, inşaat API'leri IEnumerable<KeyValuePair<string, object?>> aşırı yüklemelerini destekler.

var app = WebApplication.Create();

app.MapGet("/", () =>
{
    var extensions = new List<KeyValuePair<string, object?>> { new("test", "value") };
    return TypedResults.Problem("This is an error with extensions",
                                                       extensions: extensions);
});

Bu katkı için GitHub kullanıcısı joegoldman2'ye teşekkür ederiz!

OpenAPI

Bu bölümde OpenAPI'nin yeni özellikleri açıklanmaktadır

OpenAPI belge oluşturma için yerleşik destek

OpenAPI belirtimi, HTTP API'lerini açıklamaya yönelik bir standarttır. Standart, geliştiricilerin istemci oluşturucularına, sunucu oluşturucularına, test araçlarına, belgelere ve daha fazlasına takılabilen API'lerin şeklini tanımlamasına olanak tanır. .NET 9'da ASP.NET Core, Microsoft.AspNetCore.OpenApi paketi aracılığıyla denetleyici tabanlı veya en düşük API'leri temsil eden OpenAPI belgeleri oluşturmak için yerleşik destek sağlar.

Aşağıdaki vurgulanmış kod çağrıları:

  • AddOpenApi uygulamasının DI kapsayıcısına gerekli bağımlılıkları kaydetmek için.
  • MapOpenApi uygulamasının yollarına gerekli OpenAPI uç noktalarını kaydetmek için.
var builder = WebApplication.CreateBuilder();

builder.Services.AddOpenApi();

var app = builder.Build();

app.MapOpenApi();

app.MapGet("/hello/{name}", (string name) => $"Hello {name}"!);

app.Run();

Microsoft.AspNetCore.OpenApi Aşağıdaki komutu kullanarak paketi projeye yükleyin:

dotnet add package Microsoft.AspNetCore.OpenApi

Uygulamayı çalıştırın ve oluşturulan OpenAPI belgesini görüntülemek için adresine gidin openapi/v1.json :

OpenAPI belgesi

OpenAPI belgeleri, Microsoft.Extensions.ApiDescription.Server paketi eklenerek derleme zamanında da oluşturulabilir.

dotnet add package Microsoft.Extensions.ApiDescription.Server

Yayılan OpenAPI belgelerinin konumunu değiştirmek için, uygulamanın proje dosyasındaki OpenApiDocumentsDirectory özelliğinde hedef yolu ayarlayın:

<PropertyGroup>
  <OpenApiDocumentsDirectory>$(MSBuildProjectDirectory)</OpenApiDocumentsDirectory>
</PropertyGroup>

Proje dizininde oluşturulan JSON dosyasını çalıştırın dotnet build ve inceleyin.

Derleme zamanında OpenAPI belgesi oluşturma

ASP.NET Core'un yerleşik OpenAPI belge oluşturma işlemi, çeşitli özelleştirmeler ve seçenekler için destek sağlar. Belge, işlem ve şema dönüştürücüleri sağlar ve aynı uygulama için birden çok OpenAPI belgesini yönetme özelliğine sahiptir.

ASP.NET Core'un yeni OpenAPI belge özellikleri hakkında daha fazla bilgi edinmek için yeni Microsoft.AspNetCore.OpenApi belgelerine bakın.

Microsoft.AspNetCore.OpenApi kırpmayı ve Yerel AOT'yi destekler

ASP.NET Core'da OpenAPI kırpmayı ve yerel AOT'yi destekler. Aşağıdaki adımlar, gereksiz parçaların kaldırılması ve yerel AOT ile bir OpenAPI uygulaması oluşturup yayımlar:

Yeni bir ASP.NET Core Web API (Yerel AOT) projesi oluşturun.

dotnet new webapiaot

Microsoft.AspNetCore.OpenAPI paketini ekleyin.

dotnet add package Microsoft.AspNetCore.OpenApi

OpenAPI belgeleri oluşturmayı etkinleştirmek için Program.cs güncelleştirin.

+ builder.Services.AddOpenApi();

var app = builder.Build();

+ app.MapOpenApi();

Uygulamayı yayımlayın.

dotnet publish

Kimlik doğrulaması ve yetkilendirme

Bu bölümde kimlik doğrulaması ve yetkilendirmeye yönelik yeni özellikler açıklanmaktadır.

OpenIdConnectHandler, Gönderilen Yetkilendirme İstekleri (PAR) için destek ekler

ASP.NET Core'un OpenIdConnectHandler'sine Gönderilen Yetkilendirme İsteklerini (PAR) eklediği için Duende Software'tenJoe DeCock'a teşekkür ederiz. Joe, API teklifinde PAR'yi etkinleştirmenin arka planını ve motivasyonunu şu şekilde tanımladı:

Gönderilen Yetkilendirme İstekleri (PAR), yetkilendirme parametrelerini ön kanaldan arka kanala taşıyarak OAuth ve OIDC akışlarının güvenliğini geliştiren nispeten yeni bir OAuth standardıdır . Diğer bir ifadeyle, yetkilendirme parametrelerinin tarayıcıdaki yönlendirme URL'lerinden arka uçta doğrudan makineden makineye http çağrılarına taşınması.

Bu, tarayıcıda bir siber saldırının aşağıdakileri yapmasını önler:

  • Kimlik doğrulama parametrelerinin görülmesi PII'yi sızdırabilir.
  • Bu parametrelerle oynanıyor. Örneğin siber saldırı, istenen erişim kapsamını değiştirebilir.

Yetkilendirme parametrelerinin gönderilmesi, istek URL'lerini de kısa tutar. Yetkilendirme parametreleri, Zengin Yetkilendirme İstekleri gibi daha karmaşık OAuth ve OIDC özellikleri kullanılırken çok uzun sürebilir. Uzun olan URL'ler birçok tarayıcıda ve ağ altyapısında sorunlara neden olur.

PAR kullanımı, OpenID Foundation içindeki FAPI çalışma grubu tarafından teşvik edilir. Örneğin, FAPI2.0 Güvenlik Profili PAR kullanımını gerektirir. Bu güvenlik profili, açık bankacılık (öncelikli olarak Avrupa' da), sağlık hizmetlerinde ve yüksek güvenlik gereksinimleri olan diğer sektörlerde çalışan grupların çoğu tarafından kullanılır.

PAR, dahil olmak üzere bir dizi kimlik sağlayıcısı tarafından desteklenir

.NET 9 için, kimlik sağlayıcısının bulma belgesi PAR desteğini tanıtıyorsa varsayılan olarak PAR'yi etkinleştirmeye karar verdik, çünkü bunu destekleyen sağlayıcılar için gelişmiş güvenlik sağlamalıdır. Kimlik sağlayıcısının bulma belgesi genellikle .well-known/openid-configuration konumunda bulunur. Bu sorunlara neden olursa, AŞAĞıDAKI gibi OpenIdConnectOptions.PushedAuthorizationBehavior aracılığıyla PAR'yi devre dışı bırakabilirsiniz:

builder.Services
    .AddAuthentication(options =>
    {
        options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
    })
    .AddCookie()
    .AddOpenIdConnect("oidc", oidcOptions =>
    {
        // Other provider-specific configuration goes here.

        // The default value is PushedAuthorizationBehavior.UseIfAvailable.

        // 'OpenIdConnectOptions' does not contain a definition for 'PushedAuthorizationBehavior'
        // and no accessible extension method 'PushedAuthorizationBehavior' accepting a first argument
        // of type 'OpenIdConnectOptions' could be found
        oidcOptions.PushedAuthorizationBehavior = PushedAuthorizationBehavior.Disable;
    });

Kimlik doğrulamasının yalnızca PAR kullanıldığında başarılı olmasını sağlamak için bunun yerine PushedAuthorizationBehavior.Require kullanın. Bu değişiklik, OpenIdConnectEvents'e gönderilen yetkilendirme isteğini özelleştirmek veya el ile işlemek için kullanılabilecek yeni bir OnPushAuthorization olayı da sunar. Daha fazla ayrıntı için API teklifine bakın.

OIDC ve OAuth Parametre Özelleştirmesi

OAuth ve OIDC kimlik doğrulama işleyicileri artık genellikle yeniden yönlendirme sorgu dizesinin parçası AdditionalAuthorizationParameters olarak eklenen yetkilendirme iletisi parametrelerini özelleştirmeyi kolaylaştırma seçeneğine sahiptir. .NET 8 ve önceki sürümlerinde bu, özel bir işleyicide özel bir OnRedirectToIdentityProvider geri çağırma işlevi veya geçersiz kılınmış bir BuildChallengeUrl yöntemi gerektirir. Aşağıda bir .NET 8 kodu örneği verilmişti:

builder.Services.AddAuthentication().AddOpenIdConnect(options =>
{
    options.Events.OnRedirectToIdentityProvider = context =>
    {
        context.ProtocolMessage.SetParameter("prompt", "login");
        context.ProtocolMessage.SetParameter("audience", "https://api.example.com");
        return Task.CompletedTask;
    };
});

Yukarıdaki örnek artık aşağıdaki kodla basitleştirilebilir:

builder.Services.AddAuthentication().AddOpenIdConnect(options =>
{
    options.AdditionalAuthorizationParameters.Add("prompt", "login");
    options.AdditionalAuthorizationParameters.Add("audience", "https://api.example.com");
});

genişletilmiş HTTP.sys kimlik doğrulama bayraklarını yapılandırma

Windows kimlik doğrulamasının nasıl işleneceğini optimize etmek için HTTP.sys üzerindeki yeni EnableKerberosCredentialCaching ve CaptureCredentials özelliklerini kullanarak HTTP_AUTH_EX_FLAG_ENABLE_KERBEROS_CREDENTIAL_CACHING ve HTTP_AUTH_EX_FLAG_CAPTURE_CREDENTIAL HTTP.sys AuthenticationManager bayraklarını şimdi yapılandırabilirsiniz. Örneğin:

webBuilder.UseHttpSys(options =>
{
    options.Authentication.Schemes = AuthenticationSchemes.Negotiate;
    options.Authentication.EnableKerberosCredentialCaching = true;
    options.Authentication.CaptureCredentials = true;
});

Çeşitli

Aşağıdaki bölümlerde çeşitli yeni özellikler açıklanmaktadır.

Yeni HybridCache kitaplık

Önemli

HybridCacheşu anda önizleme aşamasındadır, ancak .NET Uzantıları'nın gelecekteki küçük bir sürümünde .NET 9.0'ın ardından tamamen yayımlanacaktır.

API, HybridCache mevcut IDistributedCache ve IMemoryCache API'lerdeki bazı boşlukları kapatır. Ayrıca aşağıdakiler gibi yeni özellikler de ekler:

  • Aynı çalışmanın paralel getirilmesini önlemek için "Stampede" koruması .
  • Yapılandırılabilir serileştirme.

HybridCache, mevcut IDistributedCache ve IMemoryCache kullanımları için doğrudan bir alternatif olarak tasarlanmıştır ve yeni önbellekleme kodu eklemek için basit bir API sağlar. Hem işlem içi hem de işlem dışı önbelleğe alma için birleşik bir API sağlar.

API'nin HybridCache nasıl basitleştirildiğini görmek için api'yi kullanan IDistributedCachekodla karşılaştırın. İşte IDistributedCache kullanımının nasıl göründüğüne bir örnek:

public class SomeService(IDistributedCache cache)
{
    public async Task<SomeInformation> GetSomeInformationAsync
        (string name, int id, CancellationToken token = default)
    {
        var key = $"someinfo:{name}:{id}"; // Unique key for this combination.
        var bytes = await cache.GetAsync(key, token); // Try to get from cache.
        SomeInformation info;
        if (bytes is null)
        {
            // Cache miss; get the data from the real source.
            info = await SomeExpensiveOperationAsync(name, id, token);

            // Serialize and cache it.
            bytes = SomeSerializer.Serialize(info);
            await cache.SetAsync(key, bytes, token);
        }
        else
        {
            // Cache hit; deserialize it.
            info = SomeSerializer.Deserialize<SomeInformation>(bytes);
        }
        return info;
    }

    // This is the work we're trying to cache.
    private async Task<SomeInformation> SomeExpensiveOperationAsync(string name, int id,
        CancellationToken token = default)
    { /* ... */ }
}

Serileştirme gibi şeyler de dahil olmak üzere her seferinde doğru olanı yapmak için çok fazla çalışma gerekir. Önbellek kaçırma senaryosunda, birden çok eş zamanlı iş parçacığı olabilir, hepsi cache miss ile karşılaşabilir, hepsi temel verileri getirebilir, hepsi bunları seri hale getirebilir ve verilerin hepsini önbelleğe gönderebilir.

ile HybridCachebu kodu basitleştirmek ve geliştirmek için öncelikle yeni kitaplığını Microsoft.Extensions.Caching.Hybrideklemeliyiz:

<PackageReference Include="Microsoft.Extensions.Caching.Hybrid" Version="9.0.0" />

HybridCache Bir uygulamayı kaydeder gibi hizmeti kaydedinIDistributedCache:

builder.Services.AddHybridCache(); // Not shown: optional configuration API.

Artık çoğu önbelleğe alma sorunu HybridCache'a devredilebilir.

public class SomeService(HybridCache cache)
{
    public async Task<SomeInformation> GetSomeInformationAsync
        (string name, int id, CancellationToken token = default)
    {
        return await cache.GetOrCreateAsync(
            $"someinfo:{name}:{id}", // Unique key for this combination.
            async cancel => await SomeExpensiveOperationAsync(name, id, cancel),
            token: token
        );
    }
}

Bağımlılık ekleme yoluyla soyut sınıfın HybridCache somut bir uygulamasını sağlarız, ancak geliştiricilerin API'nin özel uygulamalarını sağlaması amaçlanmıştır. Uygulama, HybridCache eşzamanlı işlemlerin yönetimi dahil olmak üzere önbelleğe almayla ilgili her şeyi ele alır. Buradaki cancel belirteç, yalnızca görebildiğimiz çağıranın iptalini değil, tüm eşzamanlı arayanların birleştirilmiş iptalini temsil eder—yani, token çağıranın iptali de dahil.

Yüksek aktarım hızı senaryoları, TState desen kullanılarak yakalanan değişkenlerden ve her bir örnek için yapılan geri çağırmalardan kaynaklanan bazı ek yükleri önlemek amacıyla daha da optimize edilebilir.

public class SomeService(HybridCache cache)
{
    public async Task<SomeInformation> GetSomeInformationAsync(string name, int id, CancellationToken token = default)
    {
        return await cache.GetOrCreateAsync(
            $"someinfo:{name}:{id}", // unique key for this combination
            (name, id), // all of the state we need for the final call, if needed
            static async (state, token) =>
                await SomeExpensiveOperationAsync(state.name, state.id, token),
            token: token
        );
    }
}

HybridCache , örneğin Redis kullanarak ikincil işlem dışı önbelleğe alma için yapılandırılan IDistributedCache uygulamayı (varsa) kullanır. Ancak, bir IDistributedCache olmadan bile, HybridCache hizmeti işlem içi önbelleğe alma ve "sel koruması" sağlamaya devam eder.

Nesne yeniden kullanımıyla ilgili bir not

Tipik mevcut IDistributedCache kullanan kodda, önbellekten her nesne alımı, nesnenin seri durumdan çıkarılmasına neden olur. Bu davranış, her eşzamanlı çağıranın nesnenin diğer örneklerle etkileşim kuramayan ayrı bir örneğini aldığı anlamına gelir. Sonuç olarak iş parçacığı güvenliği sağlanır çünkü aynı nesne örneğinde eşzamanlı değişiklik yapılması riski yoktur.

Çok fazla HybridCache kullanım mevcut IDistributedCache koddan uyarlanacağından, HybridCache eşzamanlılık hatalarının oluşmasını önlemek için bu davranışı varsayılan olarak korur. Ancak, belirli bir kullanım örneği doğal olarak iş parçacığı açısından güvenlidir:

  • Önbelleğe alınan türler sabitse.
  • Kod bunları değiştirmezse.

Bu gibi durumlarda örneklerin yeniden kullanılmasının güvenli olduğunu şu şekilde bildirin HybridCache :

  • Türü olarak sealedişaretleme. sealed C# dilindeki anahtar sözcük, sınıfın devralınamaz olduğu anlamına gelir.
  • Özniteliği [ImmutableObject(true)] üzerine uygulamak. [ImmutableObject(true)] özniteliği, nesne oluşturulduktan sonra nesnenin durumunun değiştirilebileceğini gösterir.

Örnekleri yeniden kullanarak, HybridCache çağrı başına seri durumdan çıkarma ile ilişkili CPU ve nesne ayırma yükünü azaltabilir. Bu, önbelleğe alınan nesnelerin büyük olduğu veya sık erişildiği senaryolarda performans geliştirmelerine yol açabilir.

Diğer HybridCache özellikler

gibi IDistributedCache, HybridCache bir RemoveKeyAsync yöntemle anahtara göre kaldırmayı destekler.

HybridCache ayrıca, IDistributedCache uygulamaları için, byte[] ayırmalarını önlemek amacıyla isteğe bağlı API'ler sağlar. Bu özellik, Microsoft.Extensions.Caching.StackExchangeRedis ve Microsoft.Extensions.Caching.SqlServer paketlerinin önizleme sürümleri tarafından uygulanır.

Hizmeti kaydetmenin bir parçası olarak serileştirme yapılandırılır ve AddHybridCache çağrısından zincirlenerek WithSerializer ve .WithSerializerFactory yöntemleri aracılığıyla türe özgü ve genelleştirilmiş serileştiriciler için destek sunar. Varsayılan olarak, kitaplık string ve byte[] öğelerini dahili olarak işler ve diğer her şey için System.Text.Json kullanır, ancak protobuf, xml veya başka herhangi bir şeyi de kullanabilirsiniz.

HybridCache ,NET Framework 4.7.2 ve .NET Standard 2.0'a kadar eski .NET çalışma zamanlarını destekler.

hakkında HybridCachedaha fazla bilgi için bkz. ASP.NET Core'da HybridCache kitaplığı

Geliştirici özel durum sayfası geliştirmeleri

ASP.NET Core geliştirici özel durum sayfası , geliştirme sırasında bir uygulama işlenmeyen bir özel durum oluşturduğunda görüntülenir. Geliştirici özel durumu sayfası, özel durum ve istek hakkında ayrıntılı bilgi sağlar.

Önizleme 3, geliştirici özel durum sayfasına uç nokta meta verileri ekledi. ASP.NET Core yönlendirme, yanıt önbelleğe alma, hız sınırlama, OpenAPI oluşturma ve daha fazlası gibi uç nokta davranışlarını denetlemek için uç nokta meta verilerini kullanır. Aşağıdaki görüntüde Routing , geliştirici özel durum sayfasının bölümündeki yeni meta veri bilgileri gösterilmektedir:

Geliştirici özel durum sayfasındaki yeni meta veri bilgileri

Geliştirici özel durum sayfası test edilirken, küçük yaşam kalitesi iyileştirmeleri belirlendi. "Önizleme 4'te yayınlandı."

  • Daha iyi metin kaydırma. Uzun tanımlama bilgileri, sorgu dizesi değerleri ve yöntem adları artık yatay tarayıcı kaydırma çubukları oluşturmaz.
  • Modern tasarımlarda bulunan daha büyük metin.
  • Daha tutarlı tablo boyutları.

Aşağıdaki animasyonlu görüntüde yeni geliştirici özel durum sayfası gösterilmektedir:

Yeni geliştirici özel durum sayfası

Sözlük hata ayıklama geliştirmeleri

Sözlüklerin ve diğer anahtar-değer koleksiyonlarının hata ayıklama görüntüsü geliştirilmiş bir düzene sahiptir. Anahtar, değerle birleştirilmek yerine hata ayıklayıcının anahtar sütununda görüntülenir. Aşağıdaki görüntülerde, hata ayıklayıcıda bir sözlüğün eski ve yeni görünümü gösterilmektedir.

Önce:

Önceki hata ayıklayıcı deneyimi

Sonra:

Yeni hata ayıklayıcı deneyimi

ASP.NET Core'da birçok anahtar-değer koleksiyonu vardır. Bu geliştirilmiş hata ayıklama deneyimi şunlar için geçerlidir:

  • HTTP üst bilgileri
  • Sorgu dizeleri
  • Formlar
  • Çerezler
  • Verileri görüntüleme
  • Rota verisi
  • Özellikler

IIS'te uygulama geri dönüşümü esnasında oluşan 503 hatalarının düzeltilmesi

Varsayılan olarak, IIS'ye geri dönüşüm veya kapatma bildirimi gönderilmesi ile ANCM'nin yönetilen sunucuya kapatmayı başlatmasını bildirmesi arasında 1 saniyelik bir gecikme vardır. Gecikme, ANCM_shutdownDelay ortam değişkeni veya shutdownDelay işleyici ayarı ile yapılandırılabilir. Her iki değer de milisaniye cinsindendir. Gecikme esas olarak aşağıdaki durumlarda bir yarışın olasılığını azaltmaktır:

  • IIS, yeni uygulamaya gitmek için istekleri kuyruğa alma işlemini başlatmadı.
  • ANCM, eski uygulamaya gelen yeni istekleri reddetmeye başlar.

Daha yavaş makineler veya daha ağır CPU kullanımına sahip makineler, 503 olasılığını azaltmak için bu değeri ayarlamak isteyebilir.

ayar shutdownDelayörneği:

<aspNetCore processPath="dotnet" arguments="myapp.dll" stdoutLogEnabled="false" stdoutLogFile=".logsstdout">
  <handlerSettings>
    <!-- Milliseconds to delay shutdown by.
    this doesn't mean incoming requests will be delayed by this amount,
    but the old app instance will start shutting down after this timeout occurs -->
    <handlerSetting name="shutdownDelay" value="5000" />
  </handlerSettings>
</aspNetCore>

Düzeltme, barındırma paketinden gelen genel olarak yüklenmiş ANCM modülündedir.

ASP0026: [Authorize] özniteliğinin daha uzaktan [AllowAnonymous] ile geçersiz kılındığında uyarı veren analiz aracı

MVC eylemine, bir [AllowAnonymous] özniteliğinden "daha yakın" yerleştirilmiş bir [Authorize] özniteliğinin, [AllowAnonymous] özniteliğini geçersiz kılıp yetkilendirmeyi zorlaması sezgisel olarak mantıklı görünüyor. Ancak, bu durum mutlaka böyle değildir. Önemli olan özniteliklerin göreli sırasıdır.

Aşağıdaki kod, daha uzaktaki bir öznitelik tarafından daha yakın [Authorize] bir [AllowAnonymous] özniteliğin geçersiz kılındığı örnekleri gösterir.

[AllowAnonymous]
public class MyController
{
    [Authorize] // Overridden by the [AllowAnonymous] attribute on the class
    public IActionResult Private() => null;
}
[AllowAnonymous]
public class MyControllerAnon : ControllerBase
{
}

[Authorize] // Overridden by the [AllowAnonymous] attribute on MyControllerAnon
public class MyControllerInherited : MyControllerAnon
{
}

public class MyControllerInherited2 : MyControllerAnon
{
    [Authorize] // Overridden by the [AllowAnonymous] attribute on MyControllerAnon
    public IActionResult Private() => null;
}
[AllowAnonymous]
[Authorize] // Overridden by the preceding [AllowAnonymous]
public class MyControllerMultiple : ControllerBase
{
}

.NET 9 Preview 6'da, daha yakın olan [Authorize] özniteliğinin MVC eyleminden daha uzakta olan bir [AllowAnonymous] özniteliği tarafından geçersiz kılındığı durumları vurgulayan bir çözümleyici tanıttık. Uyarı, geçersiz kılınan [Authorize] özniteliğine şu iletiyle işaret ediyor:

ASP0026 [Authorize] overridden by [AllowAnonymous] from farther away

Bu uyarıyı görürseniz yapmanız gereken doğru eylem, özniteliklerin ardındaki amacına bağlıdır. Eğer uç nokta yanlışlıkla anonim kullanıcılara açıksa, [AllowAnonymous] uzaklık özniteliği kaldırılmalıdır. tr-TR: Eğer [AllowAnonymous] özniteliği, daha yakın [Authorize] özniteliğini geçersiz kılmayı amaçlıyorsa, amacı netleştirmek için [Authorize] özniteliğinden sonra [AllowAnonymous] özniteliğini tekrarlayabilirsiniz.

[AllowAnonymous]
public class MyController
{
    // This produces no warning because the second, "closer" [AllowAnonymous]
    // clarifies that [Authorize] is intentionally overridden.
    // Specifying AuthenticationSchemes can still be useful
    // for endpoints that allow but don't require authenticated users.
    [Authorize(AuthenticationSchemes = "Cookies")]
    [AllowAnonymous]
    public IActionResult Privacy() => null;
}

Geliştirilmiş Kestrel bağlantı ölçümleri

Bağlantının neden başarısız olduğuyla ilgili meta verileri ekleyerek 'nin bağlantı ölçümlerinde önemli bir iyileştirme Kestrelyaptık. Ölçüm artık kestrel.connection.duration özniteliğinde error.type bağlantı kapatma nedenini içerir.

Değerlerin error.type küçük bir örneği aşağıda verilmiştir:

  • tls_handshake_failed - Bağlantı TLS gerektiriyor ve TLS el sıkışması başarısız oldu.
  • connection_reset - İstekler devam ederken bağlantı istemci tarafından beklenmedik bir şekilde kapatıldı.
  • request_headers_timeout - Kestrel İstek üst bilgilerini zamanında almadığından bağlantıyı kapattı.
  • max_request_body_size_exceeded - Kestrel Karşıya yüklenen veriler boyut üst sınırını aştığından bağlantıyı kapattı.

Daha önce, bağlantı sorunlarını tanılamak Kestrel için sunucunun ayrıntılı, düşük düzeyli günlük kaydı yapması gerekiyordu. Ancak günlüklerin oluşturulması ve depolanması pahalı olabilir ve gürültü arasında doğru bilgileri bulmak zor olabilir.

Ölçümler, minimum etkiyle üretim ortamında bırakılabilen çok daha ucuz bir alternatiftir. Toplanan ölçümler panoları ve uyarıları yönlendirebilir. Yüksek seviyeli bir sorun ölçümlerle belirlendikten sonra, daha fazla araştırmaya günlüğe kaydetme ve diğer araçları kullanarak başlanabilir.

Geliştirilmiş bağlantı ölçümlerinin birçok senaryoda yararlı olmasını bekliyoruz:

  • Kısa bağlantı ömründen kaynaklanan performans sorunlarını araştırma.
  • Performansı ve kararlılığı etkileyen sürekli dış saldırıları Kestrel gözlemleme.
  • Yerleşik güvenlik sağlamlaştırması tarafından engellenen KestrelKestrel üzerindeki dış saldırı girişimlerini kaydetme.

Daha fazla bilgi için bkz . ASP.NET Çekirdek ölçümleri.

Adlandırılmış kanal uç noktalarını özelleştirme Kestrel

Kestrel'nin adlandırılmış kanal desteği gelişmiş özelleştirme seçenekleriyle geliştirildi. Adlandırılmış kanal seçeneklerindeki yeni CreateNamedPipeServerStream yöntem, kanalların uç nokta başına özelleştirilmesine olanak tanır.

Bunun yararlı olduğu bir örnek, farklı erişim güvenliğine sahip iki kanal uç noktası gerektiren bir Kestrel uygulamadır. bu CreateNamedPipeServerStream seçenek, kanal adına bağlı olarak özel güvenlik ayarlarıyla kanal oluşturmak için kullanılabilir.

var builder = WebApplication.CreateBuilder();

builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenNamedPipe("pipe1");
    options.ListenNamedPipe("pipe2");
});

builder.WebHost.UseNamedPipes(options =>
{
    options.CreateNamedPipeServerStream = (context) =>
    {
        var pipeSecurity = CreatePipeSecurity(context.NamedPipeEndpoint.PipeName);

        return NamedPipeServerStreamAcl.Create(context.NamedPipeEndPoint.PipeName, PipeDirection.InOut,
            NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Byte,
            context.PipeOptions, inBufferSize: 0, outBufferSize: 0, pipeSecurity);
    };
});

ExceptionHandlerMiddleware özel durum türüne göre durum kodunu seçme seçeneği

yapılandırırken yeni bir seçenek, uygulama geliştiricilerinin ExceptionHandlerMiddleware istek işleme sırasında bir özel durum oluştuğunda hangi durum kodunun döndürüleceğini seçmesine olanak tanır. Yeni seçenek, ProblemDetails yanıtındaki ayarlanan durum kodunu ExceptionHandlerMiddleware olarak değiştirir.

app.UseExceptionHandler(new ExceptionHandlerOptions
{
    StatusCodeSelector = ex => ex is TimeoutException
        ? StatusCodes.Status503ServiceUnavailable
        : StatusCodes.Status500InternalServerError,
});

Belirli uç noktalarda ve isteklerde HTTP ölçümlerini geri çevirme

.NET 9, belirli uç noktalar ve istekler için HTTP ölçümlerini geri çevirme özelliğini tanıtır. Kayıt ölçümlerini geri çevirmek, sistem durumu denetimleri gibi otomatik sistemler tarafından sık çağrılan uç noktalar için yararlıdır. Bu isteklerin ölçümlerini kaydetmek genellikle gereksizdir.

Bir uç noktaya yönelik HTTP istekleri meta veriler eklenerek ölçümlerden dışlanabilir. Şunlardan biri:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHealthChecks();

var app = builder.Build();
app.MapHealthChecks("/healthz").DisableHttpMetrics();
app.Run();

MetricsDisabled özelliği IHttpMetricsTagsFeature için eklendi:

  • Uç noktaya eşlenmeyen bir isteğin olduğu gelişmiş senaryolar.
  • Belirli HTTP istekleri için ölçüm koleksiyonunu dinamik olarak devre dışı bırakma.
// Middleware that conditionally opts-out HTTP requests.
app.Use(async (context, next) =>
{
    var metricsFeature = context.Features.Get<IHttpMetricsTagsFeature>();
    if (metricsFeature != null &&
        context.Request.Headers.ContainsKey("x-disable-metrics"))
    {
        metricsFeature.MetricsDisabled = true;
    }

    await next(context);
});

Anahtarları silmek için Data Protection desteği

.NET 9'un öncesinde, veri kaybını önlemek için tasarım gereği veri koruma anahtarları silinemezdi. Bir anahtarın silinmesi, korunan verileri kurtarılamaz hale getirir. Küçük boyutları göz önüne alındığında, bu anahtarların birikmesi genellikle en az etkiye neden oldu. Ancak, son derece uzun süre çalışan hizmetleri barındırmak için anahtarları silme seçeneğini kullanıma sunmuş olduk. Genel olarak, yalnızca eski anahtarların silinmesi gerekir. Anahtarları yalnızca depolama tasarrufu karşılığında veri kaybı riskini kabul ettiğinizde silin. Veri koruma anahtarlarının silinmemesi önerilir.

using Microsoft.AspNetCore.DataProtection.KeyManagement;

var services = new ServiceCollection();
services.AddDataProtection();

var serviceProvider = services.BuildServiceProvider();

var keyManager = serviceProvider.GetService<IKeyManager>();

if (keyManager is IDeletableKeyManager deletableKeyManager)
{
    var utcNow = DateTimeOffset.UtcNow;
    var yearAgo = utcNow.AddYears(-1);

    if (!deletableKeyManager.DeleteKeys(key => key.ExpirationDate < yearAgo))
    {
        Console.WriteLine("Failed to delete keys.");
    }
    else
    {
        Console.WriteLine("Old keys deleted successfully.");
    }
}
else
{
    Console.WriteLine("Key manager does not support deletion.");
}

Ara yazılım Keyed DI'i destekler

Ara yazılım artık hem oluşturucuda hem de InvokeAsync yönteminde Keyed DI desteğini destekliyorInvoke/InvokeAsync

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddKeyedSingleton<MySingletonClass>("test");
builder.Services.AddKeyedScoped<MyScopedClass>("test2");

var app = builder.Build();
app.UseMiddleware<MyMiddleware>();
app.Run();

internal class MyMiddleware
{
    private readonly RequestDelegate _next;

    public MyMiddleware(RequestDelegate next,
        [FromKeyedServices("test")] MySingletonClass service)
    {
        _next = next;
    }

    public Task Invoke(HttpContext context,
        [FromKeyedServices("test2")]
            MyScopedClass scopedService) => _next(context);
}

Linux'ta ASP.NET Core HTTPS geliştirme sertifikasına güvenme

Ubuntu ve Fedora tabanlı Linux dağıtımlarında artık dotnet dev-certs https --trust ASP.NET Core HTTPS geliştirme sertifikasını güvenilen sertifika olarak yapılandırmaktadır:

  • Google Chrome, Microsoft Edge ve Chromium gibi Chromium tarayıcıları.
  • Mozilla Firefox ve Mozilla türetilmiş tarayıcılar.
  • .NET API'leri, örneğin, HttpClient

Daha önce yalnızca --trust Windows ve macOS üzerinde çalışıyordu. Sertifika güveni kullanıcı başına uygulanır.

OpenSSL'de güven oluşturmak için dev-certs aracını kullanın:

  • Sertifikayı ~/.aspnet/dev-certs/trust içine koyar.
  • Dizinde OpenSSL'nin c_rehash aracının basitleştirilmiş bir sürümünü çalıştırır.
  • Kullanıcıdan ortam değişkenini güncelleştirmesini SSL_CERT_DIR ister.

Dotnet'te güven oluşturmak için araç sertifikayı sertifika deposuna My/Root yerleştirir.

NSS veritabanlarında güven oluşturmak için, varsa, araç ana dizinde Firefox profillerini arar, ~/.pki/nssdb ve ~/snap/chromium/current/.pki/nssdb. Araç, bulunan her dizin için nssdb içine bir kayıt ekler.

Şablonlar en son Bootstrap, jQuery ve jQuery Doğrulama sürümlerine güncelleştirildi

ASP.NET Core proje şablonları ve kitaplıkları, özellikle de Bootstrap, jQuery ve jQuery Doğrulaması'nın en son sürümlerini kullanacak şekilde güncelleştirildi:

  • Bootstrap 5.3.3
  • jQuery 3.7.1
  • jQuery Doğrulama 1.21.0