Bagikan melalui


Apa yang baru dalam ASP.NET Core 7.0

Artikel ini menyoroti perubahan paling signifikan dalam ASP.NET Core 7.0 dengan tautan ke dokumentasi yang relevan.

Middleware pembatasan laju di ASP.NET Core

Middleware Microsoft.AspNetCore.RateLimiting menyediakan middleware pembatasan laju. Aplikasi mengonfigurasi kebijakan pembatasan tarif lalu melampirkan kebijakan ke titik akhir. Untuk informasi selengkapnya, lihat Middleware pembatasan laju di ASP.NET Core.

Autentikasi menggunakan skema tunggal sebagai DefaultScheme

Sebagai bagian dari pekerjaan untuk menyederhanakan autentikasi, ketika hanya ada satu skema autentikasi yang terdaftar, secara otomatis digunakan sebagai DefaultScheme dan tidak perlu ditentukan. Untuk informasi selengkapnya, lihat DefaultScheme.

MVC dan Razor halaman

Dukungan untuk model nullable dalam tampilan MVC dan Razor Pages

Model halaman atau tampilan nullable didukung untuk meningkatkan pengalaman saat menggunakan pemeriksaan status null dengan aplikasi ASP.NET Core:

@model Product?

Ikat dengan IParsable<T>.TryParse di Pengontrol MVC dan API

IParsable<TSelf>.TryParse API mendukung nilai parameter tindakan pengikatan pengontrol. Untuk informasi selengkapnya, lihat Mengikat dengan IParsable<T>.TryParse.

Dalam versi ASP.NET Core yang lebih lama dari 7, cookie validasi persetujuan menggunakan cookie nilai yes untuk menunjukkan persetujuan. Sekarang Anda dapat menentukan nilai yang mewakili persetujuan. Misalnya, Anda dapat menggunakan true alih-alih yes:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.Configure<CookiePolicyOptions>(options =>
{
    options.CheckConsentNeeded = context => true;
    options.MinimumSameSitePolicy = SameSiteMode.None;
    options.ConsentCookieValue = "true";
});

var app = builder.Build();

Untuk informasi selengkapnya, lihat Menyesuaikan cookie nilai persetujuan.

Pengontrol API

Pengikatan parameter dengan DI di pengontrol API

Pengikatan parameter untuk tindakan pengontrol API mengikat parameter melalui injeksi dependensi saat jenis dikonfigurasi sebagai layanan. Ini berarti tidak lagi diperlukan untuk menerapkan [FromServices] atribut secara eksplisit ke parameter. Dalam kode berikut, kedua tindakan mengembalikan waktu:

[Route("[controller]")]
[ApiController]
public class MyController : ControllerBase
{
    public ActionResult GetWithAttribute([FromServices] IDateTime dateTime) 
                                                        => Ok(dateTime.Now);

    [Route("noAttribute")]
    public ActionResult Get(IDateTime dateTime) => Ok(dateTime.Now);
}

Dalam kasus yang jarang terjadi, DI otomatis dapat memutus aplikasi yang memiliki jenis di DI yang juga diterima dalam metode tindakan pengontrol API. Memiliki suatu jenis dalam DI dan sebagai suatu argumen di tindakan pengontrol API bukanlah hal yang umum terjadi. Untuk menonaktifkan pengikatan parameter otomatis, atur DisableImplicitFromServicesParameters

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddSingleton<IDateTime, SystemDateTime>();

builder.Services.Configure<ApiBehaviorOptions>(options =>
{
    options.DisableImplicitFromServicesParameters = true;
});

var app = builder.Build();

app.MapControllers();

app.Run();

Dalam ASP.NET Core 7.0, jenis di DI diperiksa di startup aplikasi dengan IServiceProviderIsService untuk menentukan apakah argumen dalam tindakan pengontrol API berasal dari DI atau dari sumber lain.

Mekanisme baru untuk menyimpulkan sumber pengikatan parameter tindakan PENGONTROL API menggunakan aturan berikut:

  1. BindingInfo.BindingSource yang telah ditentukan tidak akan pernah ditimpa.
  2. BindingSource.Services ditetapkan untuk parameter jenis kompleks yang terdaftar di kontainer DI.
  3. BindingSource.Body ditetapkan untuk parameter jenis kompleks yang tidak terdaftar di kontainer DI.
  4. BindingSource.Path ditetapkan untuk parameter dengan nama yang ditampilkan sebagai nilai rute di templat rute apa pun.
  5. Semua parameter lainnya adalah BindingSource.Query.

Nama properti JSON dalam kesalahan validasi

Secara default, ketika kesalahan validasi terjadi, validasi model menghasilkan ModelStateDictionary dengan nama properti sebagai kunci kesalahan. Beberapa aplikasi, seperti aplikasi halaman tunggal, mendapat manfaat dari penggunaan nama properti JSON untuk kesalahan validasi yang dihasilkan dari API Web. Kode berikut mengonfigurasi validasi untuk menggunakan SystemTextJsonValidationMetadataProvider untuk menggunakan nama properti JSON:

using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers(options =>
{
    options.ModelMetadataDetailsProviders.Add(new SystemTextJsonValidationMetadataProvider());
});

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Kode berikut mengonfigurasi validasi untuk menggunakan NewtonsoftJsonValidationMetadataProvider nama properti JSON saat menggunakan Json.NET:

using Microsoft.AspNetCore.Mvc.NewtonsoftJson;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers(options =>
{
    options.ModelMetadataDetailsProviders.Add(new NewtonsoftJsonValidationMetadataProvider());
}).AddNewtonsoftJson();

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Untuk informasi selengkapnya, lihat Menggunakan nama properti JSON dalam kesalahan validasi

Minimal API

Filter di aplikasi Minimal API

Filter API minimal memungkinkan pengembang untuk menerapkan logika bisnis yang mendukung:

  • Menjalankan kode sebelum dan sesudah handler rute.
  • Memeriksa dan memodifikasi parameter yang disediakan selama pemanggilan handler rute.
  • Mencegat perilaku respons penangan rute.

Filter dapat membantu dalam skenario berikut:

  • Memvalidasi parameter dan isi permintaan yang dikirim ke titik akhir.
  • Mencatat informasi tentang permintaan dan respons.
  • Memvalidasi bahwa permintaan menargetkan versi API yang didukung.

Untuk informasi selengkapnya, lihat Filter di aplikasi API Minimal

Mengikat array dan nilai string dari header dan string kueri

Di ASP.NET 7, mengikat string kueri ke array jenis primitif, array string, dan StringValues didukung:

// Bind query string values to a primitive type array.
// GET  /tags?q=1&q=2&q=3
app.MapGet("/tags", (int[] q) =>
                      $"tag1: {q[0]} , tag2: {q[1]}, tag3: {q[2]}");

// Bind to a string array.
// GET /tags2?names=john&names=jack&names=jane
app.MapGet("/tags2", (string[] names) =>
            $"tag1: {names[0]} , tag2: {names[1]}, tag3: {names[2]}");

// Bind to StringValues.
// GET /tags3?names=john&names=jack&names=jane
app.MapGet("/tags3", (StringValues names) =>
            $"tag1: {names[0]} , tag2: {names[1]}, tag3: {names[2]}");

Mengikat string kueri atau nilai header ke array jenis kompleks didukung ketika jenis telah TryParse diimplementasikan. Untuk informasi selengkapnya, lihat Mengikat array dan nilai string dari header dan string kueri.

Untuk informasi selengkapnya, lihat Menambahkan ringkasan atau deskripsi titik akhir.

Mengikat isi permintaan sebagai Stream atau PipeReader

Isi permintaan dapat mengikat sebagai Stream atau PipeReader untuk mendukung skenario secara efisien di mana pengguna harus memproses data dan:

  • Simpan data ke penyimpanan blob atau antrekan data ke penyedia antrean.
  • Proses data yang disimpan dengan proses pekerja atau fungsi cloud.

Misalnya, data mungkin diantrekan ke penyimpanan Azure Queue atau disimpan di penyimpanan Azure Blob.

Untuk informasi selengkapnya, lihat Mengikat isi permintaan sebagai Stream atau PipeReader

Overload Results.Stream Baru

Kami memperkenalkan kelebihan beban baru Results.Stream untuk mengakomodasi skenario yang memerlukan akses ke aliran respons HTTP yang mendasarinya tanpa buffering. Kelebihan beban ini juga meningkatkan kasus di mana API mengalirkan data ke aliran respons HTTP, seperti dari Azure Blob Storage. Contoh berikut menggunakan ImageSharp untuk mengembalikan ukuran gambar yang ditentukan yang dikurangi:

using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Processing;

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

app.MapGet("/process-image/{strImage}", (string strImage, HttpContext http, CancellationToken token) =>
{
    http.Response.Headers.CacheControl = $"public,max-age={TimeSpan.FromHours(24).TotalSeconds}";
    return Results.Stream(stream => ResizeImageAsync(strImage, stream, token), "image/jpeg");
});

async Task ResizeImageAsync(string strImage, Stream stream, CancellationToken token)
{
    var strPath = $"wwwroot/img/{strImage}";
    using var image = await Image.LoadAsync(strPath, token);
    int width = image.Width / 2;
    int height = image.Height / 2;
    image.Mutate(x =>x.Resize(width, height));
    await image.SaveAsync(stream, JpegFormat.Instance, cancellationToken: token);
}

Untuk informasi selengkapnya, lihat Contoh aliran

Hasil yang ditik untuk API minimal

Di .NET 6, IResult antarmuka diperkenalkan untuk mewakili nilai yang dikembalikan dari API minimal yang tidak menggunakan dukungan implisit untuk JSON yang menserialisasikan objek yang dikembalikan ke respons HTTP. Kelas Hasil statis digunakan untuk membuat berbagai IResult objek yang mewakili berbagai jenis respons. Misalnya, mengatur kode status respons atau mengalihkan ke URL lain. Jenis IResult kerangka kerja penerapan yang dikembalikan dari metode ini adalah internal, sehingga sulit untuk memverifikasi jenis tertentu IResult yang dikembalikan dari metode dalam pengujian unit.

Di .NET 7 jenis yang IResult diterapkan bersifat publik, memungkinkan pernyataan jenis saat pengujian. Contohnya:

[TestClass()]
public class WeatherApiTests
{
    [TestMethod()]
    public void MapWeatherApiTest()
    {
        var result = WeatherApi.GetAllWeathers();
        Assert.IsInstanceOfType(result, typeof(Ok<WeatherForecast[]>));
    }      
}

Peningkatan uji coba unit untuk handler rute minimal

IResult jenis implementasi sekarang tersedia untuk umum di Microsoft.AspNetCore.Http.HttpResults namespace layanan. Jenis IResult implementasi dapat digunakan untuk menguji unit penangan rute minimal saat menggunakan metode bernama alih-alih lambda.

Kode berikut menggunakan Ok<TValue> kelas :

[Fact]
public async Task GetTodoReturnsTodoFromDatabase()
{
    // Arrange
    await using var context = new MockDb().CreateDbContext();

    context.Todos.Add(new Todo
    {
        Id = 1,
        Title = "Test title",
        Description = "Test description",
        IsDone = false
    });

    await context.SaveChangesAsync();

    // Act
    var result = await TodoEndpointsV1.GetTodo(1, context);

    //Assert
    Assert.IsType<Results<Ok<Todo>, NotFound>>(result);

    var okResult = (Ok<Todo>)result.Result;

    Assert.NotNull(okResult.Value);
    Assert.Equal(1, okResult.Value.Id);
}

Untuk informasi selengkapnya, lihat IResult jenis implementasi.

Antarmuka HttpResult baru

Antarmuka berikut di Microsoft.AspNetCore.Http namespace layanan menyediakan cara untuk mendeteksi IResult jenis pada runtime, yang merupakan pola umum dalam implementasi filter:

Untuk informasi selengkapnya, lihat Antarmuka IHttpResult.

Peningkatan OpenAPI untuk API minimal

Microsoft.AspNetCore.OpenApi Paket NuGet

Paket ini Microsoft.AspNetCore.OpenApi memungkinkan interaksi dengan spesifikasi OpenAPI untuk titik akhir. Paket bertindak sebagai tautan antara model OpenAPI yang ditentukan dalam Microsoft.AspNetCore.OpenApi paket dan titik akhir yang ditentukan dalam API Minimal. Paket ini menyediakan API yang memeriksa parameter, respons, dan metadata titik akhir untuk membuat jenis anotasi OpenAPI yang digunakan untuk menjelaskan titik akhir.

app.MapPost("/todoitems/{id}", async (int id, Todo todo, TodoDb db) =>
{
    todo.Id = id;
    db.Todos.Add(todo);
    await db.SaveChangesAsync();

    return Results.Created($"/todoitems/{todo.Id}", todo);
})
.WithOpenApi();

Panggilan WithOpenApi dengan parameter

Metode WithOpenApi ini menerima fungsi yang dapat digunakan untuk memodifikasi anotasi OpenAPI. Misalnya, dalam kode berikut, deskripsi ditambahkan ke parameter pertama titik akhir:

app.MapPost("/todo2/{id}", async (int id, Todo todo, TodoDb db) =>
{
    todo.Id = id;
    db.Todos.Add(todo);
    await db.SaveChangesAsync();

    return Results.Created($"/todoitems/{todo.Id}", todo);
})
.WithOpenApi(generatedOperation =>
{
    var parameter = generatedOperation.Parameters[0];
    parameter.Description = "The ID associated with the created Todo";
    return generatedOperation;
});

Memberikan deskripsi dan ringkasan titik akhir

API minimal sekarang mendukung operasi anotasi dengan deskripsi dan ringkasan untuk pembuatan spesifikasi OpenAPI. Anda dapat memanggil metode ekstensi dan WithSummary atau menggunakan atribut [EndpointDescription] dan [EndpointSummary]).WithDescription

Untuk informasi selengkapnya, lihat OpenAPI di aplikasi API minimal

Unggahan file menggunakan IFormFile dan IFormFileCollection

API minimal sekarang mendukung pengunggahan file dengan IFormFile dan IFormFileCollection. Kode berikut menggunakan IFormFile dan IFormFileCollection untuk mengunggah file:

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

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

app.MapPost("/upload", async (IFormFile file) =>
{
    var tempFile = Path.GetTempFileName();
    app.Logger.LogInformation(tempFile);
    using var stream = File.OpenWrite(tempFile);
    await file.CopyToAsync(stream);
});

app.MapPost("/upload_many", async (IFormFileCollection myFiles) =>
{
    foreach (var file in myFiles)
    {
        var tempFile = Path.GetTempFileName();
        app.Logger.LogInformation(tempFile);
        using var stream = File.OpenWrite(tempFile);
        await file.CopyToAsync(stream);
    }
});

app.Run();

Permintaan unggahan file yang diautentikasi didukung menggunakan header Otorisasi, sertifikat klien, atau cookie header.

Tidak ada dukungan bawaan untuk antiforgery. Namun, dapat diimplementasikan menggunakan IAntiforgery layanan .

[AsParameters] atribut memungkinkan pengikatan parameter untuk daftar argumen

Atribut [AsParameters] memungkinkan pengikatan parameter untuk daftar argumen. Untuk informasi selengkapnya, lihat Pengikatan parameter untuk daftar argumen dengan [AsParameters].

API minimal dan pengontrol API

Layanan detail masalah baru

Layanan detail masalah mengimplementasikan IProblemDetailsService antarmuka, yang mendukung pembuatan Detail Masalah untuk API HTTP.

Untuk informasi selengkapnya, lihat Layanan detail masalah.

Grup rute

Metode MapGroup ekstensi membantu mengatur grup titik akhir dengan awalan umum. Ini mengurangi kode berulang dan memungkinkan untuk menyesuaikan seluruh grup titik akhir dengan satu panggilan ke metode seperti RequireAuthorization dan WithMetadata yang menambahkan metadata titik akhir.

Misalnya, kode berikut membuat dua grup titik akhir serupa:

app.MapGroup("/public/todos")
    .MapTodosApi()
    .WithTags("Public");

app.MapGroup("/private/todos")
    .MapTodosApi()
    .WithTags("Private")
    .AddEndpointFilterFactory(QueryPrivateTodos)
    .RequireAuthorization();


EndpointFilterDelegate QueryPrivateTodos(EndpointFilterFactoryContext factoryContext, EndpointFilterDelegate next)
{
    var dbContextIndex = -1;

    foreach (var argument in factoryContext.MethodInfo.GetParameters())
    {
        if (argument.ParameterType == typeof(TodoDb))
        {
            dbContextIndex = argument.Position;
            break;
        }
    }

    // Skip filter if the method doesn't have a TodoDb parameter.
    if (dbContextIndex < 0)
    {
        return next;
    }

    return async invocationContext =>
    {
        var dbContext = invocationContext.GetArgument<TodoDb>(dbContextIndex);
        dbContext.IsPrivate = true;

        try
        {
            return await next(invocationContext);
        }
        finally
        {
            // This should only be relevant if you're pooling or otherwise reusing the DbContext instance.
            dbContext.IsPrivate = false;
        }
    };
}
public static RouteGroupBuilder MapTodosApi(this RouteGroupBuilder group)
{
    group.MapGet("/", GetAllTodos);
    group.MapGet("/{id}", GetTodo);
    group.MapPost("/", CreateTodo);
    group.MapPut("/{id}", UpdateTodo);
    group.MapDelete("/{id}", DeleteTodo);

    return group;
}

Dalam skenario ini, Anda dapat menggunakan alamat relatif untuk Location header dalam hasil 201 Created :

public static async Task<Created<Todo>> CreateTodo(Todo todo, TodoDb database)
{
    await database.AddAsync(todo);
    await database.SaveChangesAsync();

    return TypedResults.Created($"{todo.Id}", todo);
}

Grup titik akhir pertama hanya akan cocok dengan permintaan yang diawali dan /public/todos dapat diakses tanpa autentikasi apa pun. Grup titik akhir kedua hanya akan cocok dengan permintaan yang diawali dan /private/todos memerlukan autentikasi.

Pabrik QueryPrivateTodos filter titik akhir adalah fungsi lokal yang memodifikasi parameter handler TodoDb rute untuk memungkinkan mengakses dan menyimpan data todo privat.

Grup rute juga mendukung grup berlapis dan pola awalan kompleks dengan parameter rute dan batasan. Dalam contoh berikut, dan handler rute yang dipetakan user ke grup dapat menangkap {org} parameter rute dan {group} yang ditentukan dalam awalan grup luar.

Awalan juga dapat kosong. Ini dapat berguna untuk menambahkan metadata titik akhir atau filter ke sekelompok titik akhir tanpa mengubah pola rute.

var all = app.MapGroup("").WithOpenApi();
var org = all.MapGroup("{org}");
var user = org.MapGroup("{user}");
user.MapGet("", (string org, string user) => $"{org}/{user}");

Menambahkan filter atau metadata ke grup berulah dengan cara yang sama seperti menambahkannya satu per satu ke setiap titik akhir sebelum menambahkan filter atau metadata tambahan yang mungkin telah ditambahkan ke grup dalam atau titik akhir tertentu.

var outer = app.MapGroup("/outer");
var inner = outer.MapGroup("/inner");

inner.AddEndpointFilter((context, next) =>
{
    app.Logger.LogInformation("/inner group filter");
    return next(context);
});

outer.AddEndpointFilter((context, next) =>
{
    app.Logger.LogInformation("/outer group filter");
    return next(context);
});

inner.MapGet("/", () => "Hi!").AddEndpointFilter((context, next) =>
{
    app.Logger.LogInformation("MapGet filter");
    return next(context);
});

Dalam contoh di atas, filter luar akan mencatat permintaan masuk sebelum filter dalam meskipun ditambahkan kedua. Karena filter diterapkan ke grup yang berbeda, urutan yang ditambahkan relatif satu sama lain tidak masalah. Filter pesanan ditambahkan tidak masalah jika diterapkan ke grup yang sama atau titik akhir tertentu.

Permintaan untuk /outer/inner/ mencatat hal berikut:

/outer group filter
/inner group filter
MapGet filter

gRPC

Transcoding JSON

Transcoding JSON gRPC adalah ekstensi untuk ASP.NET Core yang membuat API JSON RESTful untuk layanan gRPC. Transcoding JSON gRPC memungkinkan:

  • Aplikasi untuk memanggil layanan gRPC dengan konsep HTTP yang sudah dikenal.
  • ASP.NET aplikasi gRPC Core untuk mendukung API JSON gRPC dan RESTful tanpa mereplikasi fungsionalitas.
  • Dukungan eksperimental untuk menghasilkan OpenAPI dari API RESTful yang ditranskodekan dengan mengintegrasikan dengan Swashbuckle.

Untuk informasi selengkapnya, lihat transcoding GRPC JSON di aplikasi gRPC ASP.NET Core dan Gunakan OpenAPI dengan transcoding JSON gRPC ASP.NET aplikasi Core.

Pemeriksaan kesehatan gRPC di ASP.NET Core

Protokol pemeriksaan kesehatan gRPC adalah standar untuk melaporkan kesehatan aplikasi server gRPC. Aplikasi memaparkan pemeriksaan kesehatan sebagai layanan gRPC. Mereka biasanya digunakan dengan layanan pemantauan eksternal untuk memeriksa status aplikasi.

gRPC ASP.NET Core telah menambahkan dukungan bawaan untuk pemeriksaan kesehatan gRPC dengan Grpc.AspNetCore.HealthChecks paket. Hasil dari pemeriksaan kesehatan .NET dilaporkan ke penelepon.

Untuk informasi selengkapnya, lihat pemeriksaan kesehatan gRPC di ASP.NET Core.

Dukungan kredensial panggilan yang disempurnakan

Info masuk panggilan adalah cara yang disarankan untuk mengonfigurasi klien gRPC untuk mengirim token autentikasi ke server. Klien gRPC mendukung dua fitur baru untuk membuat kredensial panggilan lebih mudah digunakan:

  • Dukungan untuk kredensial panggilan dengan koneksi teks biasa. Sebelumnya, panggilan gRPC hanya mengirim info masuk panggilan jika koneksi diamankan dengan TLS. Pengaturan baru pada GrpcChannelOptions, yang disebut UnsafeUseInsecureChannelCallCredentials, memungkinkan perilaku ini disesuaikan. Ada implikasi keamanan untuk tidak mengamankan koneksi dengan TLS.
  • Metode baru yang disebut AddCallCredentials tersedia dengan pabrik klien gRPC. AddCallCredentials adalah cara cepat untuk mengonfigurasi kredensial panggilan untuk klien gRPC dan terintegrasi dengan baik dengan injeksi dependensi (DI).

Kode berikut mengonfigurasi pabrik klien gRPC untuk mengirim Authorization metadata:

builder.Services
    .AddGrpcClient<Greeter.GreeterClient>(o =>
    {
       o.Address = new Uri("https://localhost:5001");
    })
    .AddCallCredentials((context, metadata) =>
    {
       if (!string.IsNullOrEmpty(_token))
       {
          metadata.Add("Authorization", $"Bearer {_token}");
       }
       return Task.CompletedTask;
    });

Untuk informasi selengkapnya, lihat Mengonfigurasi token pembawa dengan pabrik klien gRPC.

SignalR

Hasil klien

Server sekarang mendukung permintaan hasil dari klien. Ini mengharuskan server untuk menggunakan ISingleClientProxy.InvokeAsync dan klien untuk mengembalikan hasil dari handler-nya .On . Hub yang sangat ditik juga dapat mengembalikan nilai dari metode antarmuka.

Untuk informasi selengkapnya, lihat Hasil klien

Injeksi dependensi untuk SignalR metode hub

SignalR metode hub sekarang mendukung layanan injeksi melalui injeksi dependensi (DI).

Konstruktor hub dapat menerima layanan dari DI sebagai parameter, yang dapat disimpan di properti di kelas untuk digunakan dalam metode hub. Untuk informasi selengkapnya, lihat Menyuntikkan layanan ke hub

Blazor

Menangani peristiwa perubahan lokasi dan status navigasi

Di .NET 7, Blazor mendukung lokasi yang mengubah peristiwa dan mempertahankan status navigasi. Ini memungkinkan Anda memperingatkan pengguna tentang pekerjaan yang belum disimpan atau melakukan tindakan terkait saat pengguna melakukan navigasi halaman.

Untuk informasi selengkapnya, lihat bagian berikut dari artikel Perutean dan navigasi :

Templat proyek kosong Blazor

Blazor memiliki dua templat proyek baru untuk memulai dari garis miring kosong. Templat proyek App Empty dan Blazor WebAssembly App Empty baru Blazor Server sama seperti rekan-rekan yang tidak kosong tetapi tanpa contoh kode. Templat kosong ini hanya menyertakan halaman dasar home , dan kami telah menghapus Bootstrap sehingga Anda dapat memulai dengan kerangka kerja CSS yang berbeda.

Untuk informasi lebih lanjut, baca artikel berikut:

Elemen kustom Blazor

Paket ini Microsoft.AspNetCore.Components.CustomElements memungkinkan membangun elemen DOM kustom berbasis standar menggunakan Blazor.

Untuk informasi selengkapnya, lihat komponen ASP.NET CoreRazor.

Pengubah ikatan (@bind:after, @bind:get, @bind:set)

Penting

Fitur-fitur tersebut @bind:after//@bind:get@bind:set menerima pembaruan lebih lanjut saat ini. Untuk memanfaatkan pembaruan terbaru, konfirmasikan bahwa Anda telah menginstal SDK terbaru.

Menggunakan parameter panggilan balik peristiwa ([Parameter] public EventCallback<string> ValueChanged { get; set; }) tidak didukung. Sebagai gantinya, berikan Actionmetode -returning atau Task-returning ke/@bind:set@bind:after .

Untuk informasi selengkapnya, lihat sumber daya berikut:

Di .NET 7, Anda dapat menjalankan logika asinkron setelah peristiwa pengikatan selesai menggunakan pengubah baru @bind:after . Dalam contoh berikut, PerformSearch metode asinkron berjalan secara otomatis setelah perubahan apa pun pada teks pencarian terdeteksi:

<input @bind="searchText" @bind:after="PerformSearch" />

@code {
    private string searchText;

    private async Task PerformSearch()
    {
        ...
    }
}

Di .NET 7, juga lebih mudah untuk menyiapkan pengikatan untuk parameter komponen. Komponen dapat mendukung pengikatan data dua arah dengan menentukan sepasang parameter:

  • @bind:get: Menentukan nilai yang akan diikat.
  • @bind:set: Menentukan panggilan balik saat nilai berubah.

Pengubah @bind:get dan @bind:set selalu digunakan bersama-sama.

Contoh:

@* Elements *@

<input type="text" @bind="text" @bind:after="() => { }" />

<input type="text" @bind:get="text" @bind:set="(value) => { }" />

<input type="text" @bind="text" @bind:after="AfterAsync" />

<input type="text" @bind:get="text" @bind:set="SetAsync" />

<input type="text" @bind="text" @bind:after="() => { }" />

<input type="text" @bind:get="text" @bind:set="(value) => { }" />

<input type="text" @bind="text" @bind:after="AfterAsync" />

<input type="text" @bind:get="text" @bind:set="SetAsync" />

@* Components *@

<InputText @bind-Value="text" @bind-Value:after="() => { }" />

<InputText @bind-Value:get="text" @bind-Value:set="(value) => { }" />

<InputText @bind-Value="text" @bind-Value:after="AfterAsync" />

<InputText @bind-Value:get="text" @bind-Value:set="SetAsync" />

<InputText @bind-Value="text" @bind-Value:after="() => { }" />

<InputText @bind-Value:get="text" @bind-Value:set="(value) => { }" />

<InputText @bind-Value="text" @bind-Value:after="AfterAsync" />

<InputText @bind-Value:get="text" @bind-Value:set="SetAsync" />

@code {
    private string text = "";

    private void After(){}
    private void Set() {}
    private Task AfterAsync() { return Task.CompletedTask; }
    private Task SetAsync(string value) { return Task.CompletedTask; }
}

Untuk informasi selengkapnya tentang InputText komponen, lihat komponen input ASP.NET CoreBlazor.

Peningkatan Hot Reload

Di .NET 7, dukungan Hot Reload mencakup hal berikut:

  • Komponen mengatur ulang parameternya ke nilai defaultnya saat nilai dihapus.
  • Blazor WebAssembly:
    • Tambahkan jenis baru.
    • Tambahkan kelas berlapis.
    • Tambahkan metode statis dan instans ke jenis yang ada.
    • Tambahkan bidang statis dan metode ke jenis yang sudah ada.
    • Tambahkan lambda statis ke metode yang ada.
    • Tambahkan lambda yang menangkap this ke metode yang sudah ada yang sudah diambil this sebelumnya.

Permintaan autentikasi dinamis dengan MSAL di Blazor WebAssembly

Baru di .NET 7, Blazor WebAssembly mendukung pembuatan permintaan autentikasi dinamis saat runtime dengan parameter kustom untuk menangani skenario autentikasi tingkat lanjut.

Untuk informasi lebih lanjut, baca artikel berikut:

Blazor WebAssembly penyempurnaan penelusuran kesalahan

Blazor WebAssembly penelusuran kesalahan memiliki penyempurnaan berikut:

  • Dukungan untuk pengaturan Just My Code untuk menampilkan atau menyembunyikan anggota jenis yang bukan dari kode pengguna.
  • Dukungan untuk memeriksa array multidirmani.
  • Call Stack sekarang menunjukkan nama yang benar untuk metode asinkron.
  • Evaluasi ekspresi yang ditingkatkan.
  • Penanganan kata kunci yang new benar pada anggota turunan.
  • Dukungan untuk atribut terkait debugger di System.Diagnostics.

System.Security.Cryptography dukungan di WebAssembly

.NET 6 mendukung keluarga SHA dari algoritma hashing saat berjalan di WebAssembly. .NET 7 memungkinkan lebih banyak algoritma kriptografi dengan memanfaatkan SubtleCrypto, jika memungkinkan, dan kembali ke implementasi .NET ketika SubtleCrypto tidak dapat digunakan. Algoritma berikut didukung di WebAssembly di .NET 7:

  • SHA1
  • SHA256
  • SHA384
  • SHA512
  • HMACSHA1
  • HMACSHA256
  • HMACSHA384
  • HMACSHA512
  • AES-CBC
  • PBKDF2
  • HKDF

Untuk informasi selengkapnya, lihat Pengembang yang menargetkan browser-wasm dapat menggunakan API Web Crypto (dotnet/runtime #40074).

Menyuntikkan layanan ke dalam atribut validasi kustom

Anda sekarang dapat menyuntikkan layanan ke dalam atribut validasi kustom. Blazor menyiapkan ValidationContext sehingga dapat digunakan sebagai penyedia layanan.

Untuk informasi selengkapnya, lihat validasi formulir ASP.NET CoreBlazor.

Input* komponen di luar EditContext/EditForm

Komponen input bawaan sekarang didukung di luar formulir dalam Razor markup komponen.

Untuk informasi selengkapnya, lihat komponen input ASP.NET CoreBlazor.

Perubahan templat proyek

Ketika .NET 6 dirilis tahun lalu, markup _Host HTML halaman (Pages/_Host.chstml) dibagi antara _Host halaman dan halaman baru _Layout (Pages/_Layout.chstml) dalam templat proyek .NET 6 Blazor Server .

Di .NET 7, markup HTML telah dikombinasikan ulang dengan _Host halaman dalam templat proyek.

Beberapa perubahan tambahan dilakukan pada Blazor templat proyek. Tidak layak untuk mencantumkan setiap perubahan pada templat dalam dokumentasi. Untuk memigrasikan aplikasi ke .NET 7 untuk mengadopsi semua perubahan, lihat Migrasi dari ASP.NET Core 6.0 ke 7.0.

Komponen eksperimental QuickGrid

Komponen baru QuickGrid menyediakan komponen kisi data yang nyaman untuk persyaratan paling umum dan sebagai arsitektur referensi dan garis besar performa bagi siapa pun yang membangun Blazor komponen kisi data.

Untuk informasi selengkapnya, lihat komponen ASP.NET Core Blazor QuickGrid.

Demo langsung: QuickGrid untuk Blazor aplikasi sampel

Peningkatan virtualisasi

Peningkatan virtualisasi di .NET 7:

  • Komponen ini Virtualize mendukung penggunaan dokumen itu sendiri sebagai akar gulir, sebagai alternatif untuk memiliki beberapa elemen lain dengan overflow-y: scroll diterapkan.
  • Virtualize Jika komponen ditempatkan di dalam elemen yang memerlukan nama tag anak tertentu, SpacerElement memungkinkan Anda untuk mendapatkan atau mengatur nama tag spacer virtualisasi.

Untuk informasi selengkapnya, lihat bagian berikut dari artikel Virtualisasi :

MouseEventArgs Memperbarui

MovementX dan MovementY telah ditambahkan ke MouseEventArgs.

Untuk informasi selengkapnya, lihat penanganan peristiwa ASP.NET CoreBlazor.

Halaman pemuatan baru Blazor

Blazor WebAssembly Templat proyek memiliki UI pemuatan baru yang menunjukkan kemajuan pemuatan aplikasi.

Untuk informasi selengkapnya, lihat startup ASP.NET CoreBlazor.

Diagnostik yang ditingkatkan untuk autentikasi di Blazor WebAssembly

Untuk membantu mendiagnosis masalah autentikasi di Blazor WebAssembly aplikasi, pembuatan log terperinci tersedia.

Untuk informasi selengkapnya, lihat pengelogan ASP.NET CoreBlazor.

Interop JavaScript di WebAssembly

JavaScript [JSImport]/[JSExport] interop API adalah mekanisme tingkat rendah baru untuk menggunakan .NET di Blazor WebAssembly dan aplikasi berbasis JavaScript. Dengan kemampuan interop JavaScript baru ini, Anda dapat memanggil kode .NET dari JavaScript menggunakan runtime .NET WebAssembly dan memanggil fungsionalitas JavaScript dari .NET tanpa dependensi pada Blazor model komponen UI.

Untuk informasi selengkapnya:

Pendaftaran berskala penyedia status autentikasi

Sebelum rilis .NET 7, AuthenticationStateProvider terdaftar dalam kontainer layanan dengan AddScoped. Ini membuatnya sulit untuk men-debug aplikasi, karena memaksa urutan pendaftaran layanan tertentu saat memberikan implementasi kustom. Karena perubahan kerangka kerja internal dari waktu ke waktu, tidak perlu lagi mendaftar AuthenticationStateProvider dengan AddScoped.

Dalam kode pengembang, buat perubahan berikut pada pendaftaran layanan penyedia status autentikasi:

- builder.Services.AddScoped<AuthenticationStateProvider, ExternalAuthStateProvider>();
+ builder.Services.TryAddScoped<AuthenticationStateProvider, ExternalAuthStateProvider>();

Dalam contoh sebelumnya, ExternalAuthStateProvider adalah implementasi layanan pengembang.

Penyempurnaan pada alat build .NET WebAssembly

Fitur baru dalam wasm-tools beban kerja untuk .NET 7 yang membantu meningkatkan performa dan menangani pengecualian:

Untuk informasi selengkapnya, lihat ASP.NET alat build Core Blazor WebAssembly dan kompilasi ahead-of-time (AOT).

Blazor Hybrid

URL Eksternal

Opsi telah ditambahkan yang mengizinkan pembukaan halaman web eksternal di browser.

Untuk informasi selengkapnya, lihat perutean dan navigasi ASP.NET CoreBlazor Hybrid.

Keamanan

Panduan baru tersedia untuk Blazor Hybrid skenario keamanan. Untuk informasi lebih lanjut, baca artikel berikut:

Performa

Middleware penembolokan output

Penembolokan output adalah middleware baru yang menyimpan respons dari aplikasi web dan melayaninya dari cache daripada menghitungnya setiap saat. Penembolokan output berbeda dari penembolokan respons dengan cara berikut:

  • Perilaku penembolokan dapat dikonfigurasi di server.
  • Entri singgahan dapat dibatalkan secara terprogram.
  • Penguncian sumber daya mengurangi risiko stampede cache dan kawanan guntur.
  • Validasi ulang cache berarti server dapat mengembalikan 304 Not Modified kode status HTTP alih-alih isi respons yang di-cache.
  • Media penyimpanan cache dapat diperluas.

Untuk informasi selengkapnya, lihat Gambaran umum penembolokan dan Middleware penembolokan output.

Peningkatan HTTP/3

Rilis ini:

  • Membuat HTTP/3 didukung sepenuhnya oleh ASP.NET Core, http tidak lagi eksperimental.
  • KestrelMeningkatkan dukungan untuk HTTP/3. Dua bidang utama peningkatan adalah paritas fitur dengan HTTP/1.1 dan HTTP/2, dan performa.
  • Menyediakan dukungan penuh untuk UseHttps(ListenOptions, X509Certificate2) dengan HTTP/3. Kestrel menawarkan opsi lanjutan untuk mengonfigurasi sertifikat koneksi, seperti menghubungkan ke Indikasi Nama Server (SNI).
  • Menambahkan dukungan untuk HTTP/3 di HTTP.sys dan IIS.

Contoh berikut menunjukkan cara menggunakan panggilan balik SNI untuk mengatasi opsi TLS:

using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Https;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenAnyIP(8080, listenOptions =>
    {
        listenOptions.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
        listenOptions.UseHttps(new TlsHandshakeCallbackOptions
        {
            OnConnection = context =>
            {
                var options = new SslServerAuthenticationOptions
                {
                    ServerCertificate = 
                         MyResolveCertForHost(context.ClientHelloInfo.ServerName)
                };
                return new ValueTask<SslServerAuthenticationOptions>(options);
            },
        });
    });
});

Pekerjaan signifikan dilakukan di .NET 7 untuk mengurangi alokasi HTTP/3. Anda dapat melihat beberapa peningkatan tersebut dalam GitHub PR berikut:

Peningkatan performa HTTP/2

.NET 7 memperkenalkan arsitektur ulang yang signifikan tentang cara Kestrel memproses permintaan HTTP/2. ASP.NET aplikasi Core dengan koneksi HTTP/2 yang sibuk akan mengalami pengurangan penggunaan CPU dan throughput yang lebih tinggi.

Sebelumnya, implementasi multipleks HTTP/2 bergantung pada pengendalian kunci yang permintaannya dapat menulis ke koneksi TCP yang mendasar. Antrean aman utas menggantikan kunci tulis. Sekarang, daripada memperebutkan utas mana yang akan menggunakan kunci tulis, permintaan sekarang mengantre dan konsumen khusus memprosesnya. Sumber daya CPU yang sebelumnya terbuang tersedia untuk rest aplikasi.

Salah satu tempat di mana peningkatan ini dapat diperhatikan adalah di gRPC, kerangka kerja RPC populer yang menggunakan HTTP/2. Kestrel + tolok ukur gRPC menunjukkan peningkatan dramatis:

Performa streaming server gRPC

Perubahan dilakukan dalam kode penulisan bingkai HTTP/2 yang meningkatkan performa ketika ada beberapa aliran yang mencoba menulis data pada satu koneksi HTTP/2. Kami sekarang mengirimkan pekerjaan TLS ke kumpulan utas dan lebih cepat melepaskan kunci tulis yang dapat diperoleh aliran lain untuk menulis data mereka. Pengurangan waktu tunggu dapat menghasilkan peningkatan performa yang signifikan dalam kasus di mana ada ketidakcocokan untuk kunci tulis ini. Tolok ukur gRPC dengan 70 aliran pada satu koneksi (dengan TLS) menunjukkan peningkatan ~ 15% dalam permintaan per detik (RPS) dengan perubahan ini.

Dukungan Http/2 WebSockets

.NET 7 memperkenalkan WebSocket melalui dukungan HTTP/2 untuk Kestrel, SignalR klien JavaScript, dan SignalR dengan Blazor WebAssembly.

Menggunakan WebSocket melalui HTTP/2 memanfaatkan fitur baru seperti:

  • Pemadatan header.
  • Multiplexing, yang mengurangi waktu dan sumber daya yang diperlukan saat membuat beberapa permintaan ke server.

Fitur yang didukung ini tersedia di Kestrel semua platform yang diaktifkan HTTP/2. Negosiasi versi otomatis di browser dan Kestrel, sehingga tidak ada API baru yang diperlukan.

Untuk informasi selengkapnya, lihat Dukungan Http/2 WebSockets.

Kestrel peningkatan performa pada mesin inti tinggi

KestrelConcurrentQueue<T> digunakan untuk banyak tujuan. Salah satu tujuannya adalah menjadwalkan operasi I/O dalam Kestreltransportasi Soket default. Pemartisian ConcurrentQueue berdasarkan soket terkait mengurangi ketidakcocokan dan meningkatkan throughput pada mesin dengan banyak inti CPU.

Pembuatan profil pada mesin inti tinggi pada .NET 6 menunjukkan ketidakcocokan yang signifikan dalam salah Kestrelsatu instans lain ConcurrentQueue , PinnedMemoryPool yang Kestrel menggunakan untuk buffer byte cache.

Dalam .NET 7, Kestrelkumpulan memori dipartisi dengan cara yang sama seperti antrean I/O-nya, yang menyebabkan ketidakcocokan yang jauh lebih rendah dan throughput yang lebih tinggi pada mesin inti tinggi. Pada 80 VM ARM64 inti, kami melihat peningkatan lebih dari 500% dalam respons per detik (RPS) dalam tolok ukur teks biasa TechEmpower. Pada 48 Core AMD VM, peningkatannya hampir 100% dalam tolok ukur HTTPS JSON kami.

ServerReady peristiwa untuk mengukur waktu startup

Aplikasi yang menggunakan EventSource dapat mengukur waktu startup untuk memahami dan mengoptimalkan performa startup. Peristiwa baru ServerReady di Microsoft.AspNetCore.Hosting mewakili titik di mana server siap merespons permintaan.

Server

Peristiwa ServerReady baru untuk mengukur waktu mulai

Peristiwa ServerReady telah ditambahkan untuk mengukur waktu mulai aplikasi ASP.NET Core.

IIS

Penyalinan bayangan di IIS

Rakitan aplikasi penyalinan bayangan ke ASP.NET Core Module (ANCM) untuk IIS dapat memberikan pengalaman pengguna akhir yang lebih baik daripada menghentikan aplikasi dengan menyebarkan file offline aplikasi.

Untuk informasi selengkapnya, lihat Menyalin bayangan di IIS.

Lain-lain

Kestrel peningkatan rantai sertifikat lengkap

HttpsConnectionAdapterOptions memiliki properti ServerCertificateChain baru jenis X509Certificate2Collection, yang memudahkan untuk memvalidasi rantai sertifikat dengan memungkinkan rantai penuh termasuk sertifikat perantara ditentukan. Lihat dotnet/aspnetcore#21513 untuk detail selengkapnya.

dotnet watch

Output konsol yang ditingkatkan untuk dotnet watch

Output konsol dari dotnet watch telah ditingkatkan agar lebih selaras😍 dengan pengelogan ASP.NET Core dan untuk menonjol dengan 😮emoji.

Berikut adalah contoh tampilan output baru:

output untuk dotnet watch

Untuk informasi selengkapnya, lihat permintaan pull GitHub ini.

Mengonfigurasi dotnet watch untuk selalu menghidupkan ulang untuk pengeditan kasar

Pengeditan kasar adalah pengeditan yang tidak dapat dimuat ulang dengan panas. Untuk mengonfigurasi dotnet watch agar selalu dimulai ulang tanpa permintaan untuk pengeditan yang kasar, atur DOTNET_WATCH_RESTART_ON_RUDE_EDIT variabel lingkungan ke true.

Mode gelap halaman pengecualian pengembang

Dukungan mode gelap telah ditambahkan ke halaman pengecualian pengembang, berkat kontribusi oleh Patrick Westerhoff. Untuk menguji mode gelap di browser, dari halaman alat pengembang, atur mode ke gelap. Misalnya, di Firefox:

Alat F12 mode gelap FF

Di Chrome:

Alat F12 Mode gelap Chrome

Opsi templat proyek untuk menggunakan metode Program.Main alih-alih pernyataan tingkat atas

Templat .NET 7 menyertakan opsi untuk tidak menggunakan pernyataan tingkat atas dan menghasilkan namespace dan metode yang Main dideklarasikan pada Program kelas.

Menggunakan .NET CLI, gunakan --use-program-main opsi :

dotnet new web --use-program-main

Dengan Visual Studio, pilih kotak centang Jangan gunakan pernyataan tingkat atas baru selama pembuatan proyek:

kotak centang

Templat Angular dan React yang Diperbarui

Templat proyek Angular telah diperbarui ke Angular 14. Templat proyek React telah diperbarui ke React 18.2.

Mengelola JSON Web Token dalam pengembangan dengan dotnet user-jwts

Alat baris perintah baru dotnet user-jwts dapat membuat dan mengelola JSON Web Token (JWT) lokal khusus aplikasi. Untuk informasi selengkapnya, lihat Mengelola JSON Web Token dalam pengembangan dengan dotnet user-jwts.

Dukungan untuk header permintaan tambahan di W3CLogger

Anda sekarang dapat menentukan header permintaan tambahan untuk dicatat saat menggunakan pencatat W3C dengan memanggil AdditionalRequestHeaders() di W3CLoggerOptions:

services.AddW3CLogging(logging =>
{
    logging.AdditionalRequestHeaders.Add("x-forwarded-for");
    logging.AdditionalRequestHeaders.Add("x-client-ssl-protocol");
});

Untuk informasi selengkapnya, lihat Opsi W3CLogger.

Meminta dekompresi

Middleware dekompresi Permintaan baru:

  • Memungkinkan titik akhir API untuk menerima permintaan dengan konten terkompresi.
  • Content-Encoding Menggunakan header HTTP untuk mengidentifikasi dan mendekompresi permintaan secara otomatis yang berisi konten terkompresi.
  • Menghilangkan kebutuhan untuk menulis kode untuk menangani permintaan terkompresi.

Untuk informasi selengkapnya, lihat Meminta middleware dekompresi.