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.

Bu makale .NET 9 Sürüm Adayı 2 için güncelleştirildi.

Blazor

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

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

Yeni bir çözüm şablonu, aynı kullanıcı arabirimini paylaşan yerel ve Blazor web istemcisi uygulamaları oluşturmayı .NET MAUI 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.
  • Bir (genel Etkileşimli Otomatik işleme) ve bir uygulama da dahil olmak üzere Blazor Web App uygun projelerin otomatik oluşturulması .NET MAUIBlazor Hybrid .
  • Oluşturulan projeler, kullanıcı arabiriminin Razor bileşenlerini korumak için paylaşılan Razor bir sınıf kitaplığı (RCL) kullanır.
  • Uygulama ve için farklı arabirim uygulamaları sağlamak üzere bağımlılık eklemenin Blazor Hybrid nasıl kullanılacağını gösteren örnek kod eklenmiştir Blazor Web App.

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. ile Blazor Web Appuygulama oluşturma.NET MAUIBlazor Hybrid.

Statik varlık teslim iyileştirmesi

Statik Varlıkları eşleme uç noktası kuralları (MapStaticAssets), uygulamalar da dahil olmak üzere Blazor tüm ASP.NET Core uygulamalarında statik varlıkların teslimini iyileştirmeye yardımcı olan yeni bir özelliktir.

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

Ç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 özellikle 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.

s için Blazor Web Appbasitleştirilmiş kimlik doğrulama durumu serileştirmesi

Yeni API'ler, mevcut Blazor Web Appbir öğesine kimlik doğrulaması eklemeyi kolaylaştırır. Tek Tek Hesapları kullanarak kimlik doğrulamasıyla yeni Blazor Web App bir hesap oluşturduğunuzda ve WebAssembly tabanlı etkileşimi etkinleştirdiğinizde, proje hem sunucu hem de istemci projelerinde bir özel AuthenticationStateProvider 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 açıklamalarına seri hale getirmek ve yeni AuthenticationState bir örnek oluşturmak için WebAssembly'den geri okumak için Kalıcı Bileşen Durumu hizmetini (PersistentComponentState) kullanır.

Proje şablonundan Blazor Web App başlayıp Tek Tek Hesaplar seçeneğini belirlediyseniz ancak mevcut bir projeye kimlik doğrulaması eklemeye çalışıyorsanız kendinizi uygulamak veya kopyalamak için çok fazla kod kullanabilirsiniz. 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:

  • AddAuthenticationStateSerialization: Sunucudaki kimlik doğrulama durumunu seri hale getirmek için gerekli hizmetleri ekler.
  • AddAuthenticationStateDeserialization: Tarayıcıda kimlik doğrulama durumunu seri durumdan çıkarmak için gerekli hizmetleri ekler.

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 seçeneği AddAuthenticationStateSerialization geçirilebilir.

Daha fazla bilgi için, Güvenli ASP.NET Core sunucu tarafı Blazor uygulamalarının 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 yalnızca uygulamanın etkileşimli Sunucu veya WebAssembly işleme ile çalışamaz belirli sayfaları olduğunda yararlıdır. Örneğin, okuma/yazma HTTP tanımlama bilgilerine bağımlı 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.

Herhangi bir Razor bileşen sayfasını yönergesiyle atanan yeni [ExcludeFromInteractiveRouting] öznitelikle @attributeRazor işaretleyin:

@attribute [ExcludeFromInteractiveRouting]

özniteliğinin uygulanması, sayfada gezintinin 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.

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

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

  • Genel etkileşime sahip [ExcludeFromInteractiveRouting] işleme moduna varsayılan InteractiveServer olarak ek açıklama eklenmemiş sayfalar. veya ile InteractiveWebAssembly InteractiveAuto değiştirerek InteractiveServer farklı bir varsayılan genel işleme modu belirtebilirsiniz.
  • Statik SSR'yi benimseme ile [ExcludeFromInteractiveRouting] ek açıklamalı sayfalar (PageRenderMode atanır null).
<!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;
}

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

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

Oluşturucu ekleme

Razor bileşenler oluşturucu eklemeyi destekler.

Aşağıdaki örnekte, kısmi (arka planda kod) sınıfı birincil oluşturucu kullanarak hizmeti ekliyorNavigationManager:

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 yalnızca sıkıştırma etkinleştirildiğinde veya WebSocket bağlamı için bir frame-ancestors yapılandırma sağlandığında uygulamanın hizmet verildiği kaynaktan birinde <iframe> eklemeye izin veren bir İçerik Güvenlik İlkesi (CSP) yönergesi olarak ayarlanır'self'.

Sıkıştırma ayarı olarak devre dışı bırakılabilir ConfigureWebSocketOptions nullve bu da uygulamanın saldırıyla ilgili güvenlik açığını azaltır ancak performansın düşmesine neden olabilir:

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

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

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

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

uygulamasında klavye oluşturma olaylarını işleme Blazor

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.

QuickGrid özelliğine OverscanCount 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 model bağlamayı ve form doğrulamayı type="range" destekleyen bir aralık girişi oluşturan ve genellikle metin kutusu yerine kaydırıcı veya arama denetimi olarak işlenen ö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; }
    }
}

Sunucu projesi başına birden çok Blazor Web Appsn

.NET 10 (Kasım 2025) için sunucu başına birden çok Blazor Web Appproje desteği dikkate alınacaktır.

Daha fazla bilgi için bkz . Sunucu projesi başına birden çok Blazor Web uygulaması desteği (dotnet/aspnetcore #52216).

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; }
}

için Geliştirilmiş Etkinlikler SignalR

SignalR şimdi hub yöntemi çağrıları için olayları yayan adlı Microsoft.AspNetCore.SignalR.Server bir ActivitySource'a sahip:

  • 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 örnekte pano ve OpenTelemetry paketleri kullanılır.NET Aspire:

<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:

// 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())
        {
            // We want to view all traces in development
            tracing.SetSampler(new AlwaysOnSampler());
        }

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

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

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

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

SignalR kırpmayı ve Yerel AOT'yi destekler

.NET 8'de başlayan Yerel AOT yolculuğuna devam edersek, hem istemci hem de SignalR sunucu senaryoları için kırpmayı ve yerel önceden (AOT) derleme desteğini 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şlarken

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 Sunucuda, valueType () türünde IAsyncEnumerable<T> ve ChannelReader<T> burada bir ValueType (struct) olan T 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> Kullanma (dotnet/aspnetcore #56179).
  • Yerel AOT (PublishAot) ile kesin türemiş hub'lar 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.

ve InternalServerError<TValue> eklendi InternalServerErrorTypedResults

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 döndürebileceğini ProblemDetails veya ValidationProblemDetails yanıt verebileceğini gösterir.

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, değerlerle IEnumerable<KeyValuePair<string, object?>> yapılışı destekler

.NET 9'un öncesinde, ve özelliklerinin uygulamasıyla IDictionary<string, object?>başlatılması için en az API'lerde errors Sorun ve extensions ValidationProblem sonuç türlerini oluşturma. Bu sürümde, bu yapı API'leri kullanan IEnumerable<KeyValuePair<string, object?>>aşırı yüklemeleri 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 --prerelease

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, paket eklenerek Microsoft.Extensions.ApiDescription.Server derleme zamanında da oluşturulabilir:

dotnet add package Microsoft.Extensions.ApiDescription.Server --prerelease

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'daki yeni yerleşik OpenAPI desteği artık kırpmayı ve Yerel AOT'yi de destekliyor.

Kullanmaya başlayın

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 --prerelease

Bu önizlemede, kırpma uyarılarını önlemek için en son Microsoft.OpenAPI paketini de eklemeniz gerekir.

dotnet add package Microsoft.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

Uygulama, uyarı olmadan Yerel AOT kullanarak yayımlar.

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'ten Joe 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 parametrelerini tarayıcıdaki yeniden yönlendirme URL'lerinden makinenin arka uçtaki makine http çağrılarına yönlendirmesine taşıma.

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 identity sağlayıcı tarafından desteklenir

.NET 9 için, sağlayıcının identity bulma belgesi PAR desteğini tanıtıyorsa PAR'yi varsayılan olarak etkinleştirmeye karar verdik, çünkü bunu destekleyen sağlayıcılar için gelişmiş güvenlik sağlamalıdır. Sağlayıcının identity bulma belgesi genellikle adresinde .well-known/openid-configurationbulunur. 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ı olduğundan emin olmak için bunun yerine PushedAuthorizationBehavior.Require komutunu 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 OnRedirectToIdentityProvider bir geri çağırma veya geçersiz kılma 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 HTTP_AUTH_EX_FLAG_ENABLE_KERBEROS_CREDENTIAL_CACHING nasıl işleneceğini iyileştirmek için HTTP.sys yeni EnableKerberosCredentialCaching ve özelliklerini kullanarak ve HTTP_AUTH_EX_FLAG_CAPTURE_CREDENTIAL CaptureCredentials HTTP.sys AuthenticationManager bayraklarını 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 var olan IDistributedCache ve IMemoryCache kullanım için açılan bir yerine geçecek şekilde tasarlanmıştır ve yeni önbelleğe alma 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. Kullanımın nasıl IDistributedCache göründüğüne bir örnek aşağıda verilmişti:

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ığı elde edebilir, hepsi önbellek kaçırması alabilir, tüm temel alınan verileri getirebilir, hepsini seri hale getirebilir ve tüm bu verileri önbelleğe gönderebilirsiniz.

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 için HybridCacheboşaltılabilir:

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şlem işleme dahil olmak üzere önbelleğe almayla ilgili her şeyi ele alır. Buradaki cancel belirteç, yalnızca görebildiğimiz çağıranın iptalini (yani token) değil, tüm eş zamanlı arayanların birleştirilmiş iptalini temsil eder.

Yakalanan değişkenlerin TState ve örnek başına geri çağırmaların bazı ek yüklerini önlemek için yüksek aktarım hızı senaryoları desen kullanılarak daha da iyileştirilebilir:

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 IDistributedCacheHybridCache olmadan bile hizmet işlem içi önbelleğe alma ve "damgalı" koruma sağlamaya devam eder.

Nesne yeniden kullanımıyla ilgili bir not

kullanan IDistributedCachetipik mevcut kodda, önbellekten bir nesnenin her alınması seri durumdan çıkarılır. 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 elde edilir çü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ğini [ImmutableObject(true)] uygulama. [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.

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

Serileştirme, çağrıdan zincirlenmiş ve .WithSerializerFactory yöntemleri aracılığıyla WithSerializer türe özgü ve genelleştirilmiş seri hale getiriciler desteğiyle hizmeti kaydetmenin AddHybridCache bir parçası olarak yapılandırılır. Varsayılan olarak, kitaplık diğer her şeyi işler ve byte[] dahili olarak işler string ve kullanırSystem.Text.Json, ancak protobuf, xml veya başka herhangi bir şeyi 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 gönderildi:

  • 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ı eklemez.
  • 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
  • Tanımlama bilgileri
  • Verileri görüntüleme
  • Veri yönlendirme
  • Özellikler

IIS'de uygulama geri dönüşümü sırasında 503'ler için düzeltme

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, ortam değişkeni aracılığıyla ANCM_shutdownDelay veya işleyici ayarı ayarlanarak shutdownDelay 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.

Statik web varlığı teslimini iyileştirme

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. , Razor Pages ve MVC dahil olmak üzere Blazortüm kullanıcı arabirimi çerçeveleriyle çalışacak şekilde tasarlanmıştır. Bu genellikle için UseStaticFilesbir açılan listedir:

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 ekli kaynaklar UseStaticFiles gibi diğer konumlardan varlıklara hizmet verirse kullanılmalıdır.

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

  • Uygulamadaki tüm varlıklar için derleme zamanı sıkıştırma:
    • 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 değeri, içeriğin SHA-256 karması için Base64 kodlanmış dizesidir.Etags 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 Razor Sayfalar şablonundaki CSS ve dosyaların özgün ve JS 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
akıcı.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 MudBlazorBlazor bileşen kitaplığı kullanılarak özgün 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, varlıklar derlemenin bir parçası olarak iyileştirilir. İ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 ve kullanma MapStaticAssets

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

  • Sunucuya özgü bir yapılandırma olmadığından daha basittir.
  • Varlıklar derleme zamanında sıkıştırıldığından daha yüksek performanslıdır.
  • 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%

ASP0026: [Authorize] [AllowAnonymous] tarafından "uzaktan" geçersiz kılındığında uyarır

Bir özniteliğin [Authorize] MVC eylemine bir öznitelikten [AllowAnonymous] "daha yakın" yerleştirilmesinin özniteliği geçersiz kılıp yetkilendirmeyi zorlaması [AllowAnonymous] sezgisel 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 [Authorize] bir özniteliğin MVC eyleminden daha uzakta olan bir öznitelik tarafından geçersiz kılındığı örnekler gibi örnekleri vurgulayan bir [AllowAnonymous] çözümleyici sunduk. 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. [AllowAnonymous] Uç nokta yanlışlıkla anonim kullanıcılara açıksa uzak özniteliği kaldırılmalıdır. Özniteliğin [AllowAnonymous] daha yakın [Authorize] bir özniteliği geçersiz kılması amaçlandıysa, amacı netleştirmek için özniteliğinden [Authorize] sonra yineleyebilirsiniz[AllowAnonymous].

[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 kestrel.connection.duration artık özniteliğinde bağlantı kapatma nedenini error.type 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üğe kaydetmesi 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. Ölçümlerle ilgili üst düzey bir sorun belirlendikten sonra, günlüğe kaydetme ve diğer araçları kullanarak daha fazla araştırma başlayabilir.

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.
  • 'nin yerleşik güvenlik sağlamlaştırması engellenen dış saldırı Kestrel Kestrelgirişimini 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, yanıtta ProblemDetails ayarlanan durum kodunu dosyasından ExceptionHandlerMiddlewaredeğ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 için eklendiIHttpMetricsTagsFeature:

  • İsteğin bir uç noktaya eşlendiği 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 koruma anahtarları, veri kaybını önlemek için tasarım gereği temsilci seçilemezdi. 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 yönteminde Keyed DI'yiInvokeAsync/Invoke destekliyor:

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 dev-certs güven oluşturmak için araç:

  • Sertifikayı ~/.aspnet/dev-certs/trust
  • 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.

Varsa, NSS veritabanlarında güven oluşturmak için araç, dizininde home Firefox profilleri, ~/.pki/nssdbve ~/snap/chromium/current/.pki/nssdbiçin arar. Araç, bulunan her dizin için öğesine nssdbbir girdi 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