Condividi tramite


Novità di ASP.NET Core 7.0

Questo articolo illustra le modifiche più significative in ASP.NET Core 7.0 con collegamenti alla documentazione pertinente.

Middleware di limite di frequenza in ASP.NET Core

Il middleware fornisce middleware di limitazione della Microsoft.AspNetCore.RateLimiting velocità. Le app configurano i criteri di limitazione della frequenza e quindi allegano i criteri agli endpoint. Per altre informazioni, vedere Middleware di limitazione della frequenza in ASP.NET Core.

L'autenticazione usa uno schema singolo come DefaultScheme

Come parte del lavoro per semplificare l'autenticazione, quando è registrato un solo schema di autenticazione, viene usato automaticamente come DefaultScheme e non deve essere specificato. Per altre informazioni, vedere DefaultScheme.

MVC e Razor pagine

Supporto per i modelli nullable nelle visualizzazioni MVC e Razor nelle pagine

I modelli di visualizzazione o pagina nullable sono supportati per migliorare l'esperienza quando si usa il controllo dello stato Null con le app ASP.NET Core:

@model Product?

Eseguire l'associazione con IParsable<T>.TryParse nei controller MVC e API

L'API IParsable<TSelf>.TryParse supporta i valori dei parametri di azione del controller di associazione. Per altre informazioni, vedere Associare con IParsable<T>.TryParse.

In ASP.NET versioni di Core precedenti a 7, la cookie convalida del consenso usa il valore yes per indicare il cookie consenso. È ora possibile specificare il valore che rappresenta il consenso. Ad esempio, è possibile usare true invece di 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();

Per altre informazioni, vedere Personalizzare il valore di cookie consenso.

Controller API

Associazione di parametri con inserimento di dipendenze nei controller API

L'associazione di parametri per le azioni del controller API associa i parametri tramite l'inserimento delle dipendenze quando il tipo è configurato come servizio. Ciò significa che non è più necessario applicare in modo esplicito l'attributo [FromServices] a un parametro. Nel codice seguente entrambe le azioni restituiscono l'ora:

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

In rari casi, l'inserimento automatico delle dipendenze può interrompere le app con un tipo di inserimento di dipendenze che viene accettato anche in un metodo di azione dei controller API. Non è comune avere un tipo di inserimento delle dipendenze e come argomento in un'azione del controller API. Per disabilitare l'associazione automatica dei parametri, impostare 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();

In ASP.NET Core 7.0 i tipi di inserimento delle dipendenze vengono controllati all'avvio dell'app con IServiceProviderIsService per determinare se un argomento in un'azione del controller API proviene dall'inserimento delle dipendenze o dalle altre origini.

Il nuovo meccanismo per dedurre l'origine dell'associazione dei parametri di azione del controller API usa le regole seguenti:

  1. Un oggetto BindingInfo.BindingSource specificato in precedenza non viene mai sovrascritto.
  2. A un parametro di tipo complesso, registrato nel contenitore di inserimento delle dipendenze, viene assegnato BindingSource.Services.
  3. Viene assegnato BindingSource.Bodyun parametro di tipo complesso, non registrato nel contenitore DI, .
  4. A un parametro con un nome visualizzato come valore di route in qualsiasi modello di route viene assegnato BindingSource.Path.
  5. Tutti gli altri parametri sono BindingSource.Query.

Nomi di proprietà JSON negli errori di convalida

Per impostazione predefinita, quando si verifica un errore di convalida, la convalida del modello produce un ModelStateDictionary oggetto con il nome della proprietà come chiave di errore. Alcune app, ad esempio le app a pagina singola, traggono vantaggio dall'uso dei nomi delle proprietà JSON per gli errori di convalida generati dalle API Web. Il codice seguente configura la convalida per l'uso di SystemTextJsonValidationMetadataProvider per usare i nomi delle proprietà 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();

Il codice seguente configura la convalida per l'uso di per usare il NewtonsoftJsonValidationMetadataProvider nome della proprietà JSON quando si usa 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();

Per altre informazioni, vedere Usare i nomi delle proprietà JSON negli errori di convalida

API minime

Filtri nelle app per le API minime

I filtri API minimi consentono agli sviluppatori di implementare la logica di business che supporta:

  • Esecuzione del codice prima e dopo il gestore di route.
  • Controllo e modifica dei parametri forniti durante una chiamata del gestore di route.
  • Intercettazione del comportamento della risposta di un gestore di route.

I filtri possono essere utili negli scenari seguenti:

  • Convalida dei parametri della richiesta e del corpo inviati a un endpoint.
  • Registrazione delle informazioni sulla richiesta e sulla risposta.
  • Convalidare che una richiesta sia destinata a una versione dell'API supportata.

Per altre informazioni, vedere Filtri nelle app per le API minime

Associare matrici e valori stringa da intestazioni e stringhe di query

In ASP.NET 7 è supportata l'associazione di stringhe di query a una matrice di tipi primitivi, matrici di stringhe e StringValues :

// 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]}");

L'associazione di stringhe di query o valori di intestazione a una matrice di tipi complessi è supportata quando il tipo è TryParse stato implementato. Per altre informazioni, vedere Associare matrici e valori stringa da intestazioni e stringhe di query.

Per altre informazioni, vedere Aggiungere il riepilogo o la descrizione dell'endpoint.

Associare il corpo della richiesta come o StreamPipeReader

Il corpo della richiesta può essere associato come o Stream PipeReader per supportare in modo efficiente gli scenari in cui l'utente deve elaborare i dati e:

  • Archiviare i dati nell'archivio BLOB o accodare i dati a un provider di code.
  • Elaborare i dati archiviati con un processo di lavoro o una funzione cloud.

Ad esempio, i dati potrebbero essere accodati all'archiviazione code di Azure o archiviati nell'archivio BLOB di Azure.

Per altre informazioni, vedere Associare il corpo della richiesta come o StreamPipeReader

Nuovi overload Results.Stream

Sono stati introdotti nuovi Results.Stream overload per supportare scenari che richiedono l'accesso al flusso di risposta HTTP sottostante senza buffering. Questi overload migliorano anche i casi in cui un'API trasmette i dati al flusso di risposta HTTP, ad esempio da Archiviazione BLOB di Azure. L'esempio seguente usa ImageSharp per restituire una dimensione ridotta dell'immagine specificata:

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

Per altre informazioni, vedere Esempi di flusso

Risultati tipizzato per API minime

In .NET 6 l'interfaccia IResult è stata introdotta per rappresentare i valori restituiti dalle API minime che non usano il supporto implicito per JSON serializzando l'oggetto restituito alla risposta HTTP. La classe static Results viene usata per creare oggetti variabili IResult che rappresentano tipi diversi di risposte. Ad esempio, impostare il codice di stato della risposta o reindirizzare a un altro URL. I IResult tipi di framework di implementazione restituiti da questi metodi erano tuttavia interni, rendendo difficile verificare il tipo specifico IResult restituito dai metodi in uno unit test.

In .NET 7 i tipi che implementano IResult sono pubblici, consentendo le asserzioni di tipo durante il test. Ad esempio:

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

Miglioramento della testabilità degli unit test per gestori di route minimi

IResult I tipi di implementazione sono ora disponibili pubblicamente nello spazio dei Microsoft.AspNetCore.Http.HttpResults nomi . I IResult tipi di implementazione possono essere usati per unit test dei gestori di route minimi quando si usano metodi denominati anziché espressioni lambda.

Il codice seguente usa la Ok<TValue> classe :

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

Per altre informazioni, vedere IResult Tipi di implementazione.

Nuove interfacce HttpResult

Le interfacce seguenti nello Microsoft.AspNetCore.Http spazio dei nomi consentono di rilevare il IResult tipo in fase di esecuzione, un modello comune nelle implementazioni del filtro:

Per altre informazioni, vedere Interfacce IHttpResult.

Miglioramenti di OpenAPI per API minime

pacchetto NuGet Microsoft.AspNetCore.OpenApi

Il Microsoft.AspNetCore.OpenApi pacchetto consente interazioni con le specifiche OpenAPI per gli endpoint. Il pacchetto funge da collegamento tra i modelli OpenAPI definiti nel Microsoft.AspNetCore.OpenApi pacchetto e gli endpoint definiti nelle API minime. Il pacchetto fornisce un'API che esamina i parametri, le risposte e i metadati di un endpoint per costruire un tipo di annotazione OpenAPI usato per descrivere un endpoint.

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();

Chiamare WithOpenApi con parametri

Il WithOpenApi metodo accetta una funzione che può essere usata per modificare l'annotazione OpenAPI. Nel codice seguente, ad esempio, viene aggiunta una descrizione al primo parametro dell'endpoint:

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

Fornire descrizioni e riepiloghi degli endpoint

Le API minime supportano ora operazioni di annotazione con descrizioni e riepiloghi per la generazione di specifiche OpenAPI. È possibile chiamare i metodi WithDescription di estensione e WithSummary usare attributi [EndpointDescription] e [EndpointSummary]).

Per altre informazioni, vedere OpenAPI nelle app per le API minime

Caricamenti di file con IFormFile e IFormFileCollection

Le API minime supportano ora il caricamento di file con IFormFile e IFormFileCollection. Il codice seguente usa IFormFile e IFormFileCollection per caricare il 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();

Le richieste di caricamento di file autenticate sono supportate tramite un'intestazione di autorizzazione, un certificato client o un'intestazionecookie.

Non esiste alcun supporto predefinito per l'antiforgeria. Tuttavia, può essere implementata usando il IAntiforgery servizio .

[AsParameters] attribute abilita l'associazione di parametri per gli elenchi di argomenti

L'attributo abilita l'associazione [AsParameters] di parametri per gli elenchi di argomenti. Per altre informazioni, vedere Associazione di parametri per gli elenchi di argomenti con [AsParameters].

API e controller API minimi

Nuovo servizio dettagli problema

Il servizio dettagli problema implementa l'interfaccia , che supporta la IProblemDetailsService creazione dei dettagli del problema per le API HTTP.

Per altre informazioni, vedere Servizio dettagli problema.

Gruppi di route

Il MapGroup metodo di estensione consente di organizzare gruppi di endpoint con un prefisso comune. Riduce il codice ripetitivo e consente di personalizzare interi gruppi di endpoint con una singola chiamata a metodi come RequireAuthorization e WithMetadata che aggiungono metadati dell'endpoint.

Ad esempio, il codice seguente crea due gruppi simili di endpoint:

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

In questo scenario è possibile usare un indirizzo relativo per l'intestazione Location nel 201 Created risultato:

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

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

Il primo gruppo di endpoint corrisponderà solo alle richieste precedute da /public/todos e sono accessibili senza alcuna autenticazione. Il secondo gruppo di endpoint corrisponderà solo alle richieste precedute /private/todos da e richiederanno l'autenticazione.

La QueryPrivateTodos factory del filtro endpoint è una funzione locale che modifica i parametri del TodoDb gestore di route per consentire l'accesso e l'archiviazione di dati todo privati.

I gruppi di route supportano anche gruppi annidati e modelli di prefisso complessi con parametri e vincoli di route. Nell'esempio seguente e il gestore di route mappato al user gruppo possono acquisire i {org} parametri e {group} di route definiti nei prefissi del gruppo esterno.

Il prefisso può anche essere vuoto. Ciò può essere utile per l'aggiunta di metadati o filtri dell'endpoint a un gruppo di endpoint senza modificare il modello di route.

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

L'aggiunta di filtri o metadati a un gruppo ha lo stesso comportamento dell'aggiunta singolarmente a ogni endpoint prima di aggiungere altri filtri o metadati che potrebbero essere stati aggiunti a un gruppo interno o a un endpoint specifico.

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

Nell'esempio precedente, il filtro esterno registra la richiesta in ingresso prima del filtro interno anche se è stato aggiunto secondo. Poiché i filtri sono stati applicati a gruppi diversi, l'ordine in cui sono stati aggiunti l'uno rispetto all'altro non è importante. I filtri dell'ordine vengono aggiunti se applicati allo stesso gruppo o allo stesso endpoint specifico.

Una richiesta per /outer/inner/ registrare quanto segue:

/outer group filter
/inner group filter
MapGet filter

gRPC

Transcodifica JSON

la transcodifica JSON gRPC è un'estensione per ASP.NET Core che crea API JSON RESTful per i servizi gRPC. La transcodifica JSON gRPC consente di:

  • App per chiamare i servizi gRPC con concetti HTTP familiari.
  • ASP.NET app gRPC di base per supportare sia le API gRPC che LE API JSON RESTful senza replicare funzionalità.
  • Supporto sperimentale per la generazione di OpenAPI da API RESTful transcodificate tramite l'integrazione con Swashbuckle.

Per altre informazioni, vedere transcodifica JSON gRPC in ASP.NET app gRPC core e Usare OpenAPI con transcodifica JSON gRPC ASP.NET app Core.

Controlli di integrità gRPC in ASP.NET Core

Il protocollo di controllo dell'integrità gRPC è uno standard per segnalare l'integrità delle app server gRPC. Un'app espone i controlli di integrità come servizio gRPC. Vengono in genere usati con un servizio di monitoraggio esterno per controllare lo stato di un'app.

gRPC ASP.NET Core ha aggiunto il supporto predefinito per i controlli di integrità gRPC con il Grpc.AspNetCore.HealthChecks pacchetto. I risultati dei controlli di integrità .NET vengono segnalati ai chiamanti.

Per altre informazioni, vedere controlli di integrità gRPC in ASP.NET Core.

Supporto migliorato delle credenziali delle chiamate

Le credenziali di chiamata sono il modo consigliato per configurare un client gRPC per inviare un token di autenticazione al server. I client gRPC supportano due nuove funzionalità per semplificare l'uso delle credenziali delle chiamate:

  • Supporto per le credenziali di chiamata con connessioni in testo non crittografato. In precedenza, una chiamata gRPC ha inviato credenziali di chiamata solo se la connessione è stata protetta con TLS. Una nuova impostazione su GrpcChannelOptions, denominata UnsafeUseInsecureChannelCallCredentials, consente di personalizzare questo comportamento. Esistono implicazioni per la sicurezza per non proteggere una connessione con TLS.
  • È disponibile un nuovo metodo denominato AddCallCredentials con la factory client gRPC. AddCallCredentials è un modo rapido per configurare le credenziali di chiamata per un client gRPC e integra bene con l'inserimento delle dipendenze.

Il codice seguente configura la factory client gRPC per l'invio Authorization di metadati:

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

Per altre informazioni, vedere Configurare un token di connessione con la factory client gRPC.

SignalR

Risultati del client

Il server supporta ora la richiesta di un risultato da un client. Ciò richiede che il server usi ISingleClientProxy.InvokeAsync e che il client restituisca un risultato dal relativo .On gestore. Gli hub fortemente tipizzati possono anche restituire valori dai metodi di interfaccia.

Per altre informazioni, vedere Risultati del client

Inserimento delle dipendenze per SignalR i metodi hub

SignalR I metodi hub supportano ora l'inserimento di servizi tramite inserimento delle dipendenze .

I costruttori dell'hub possono accettare i servizi di inserimento delle dipendenze come parametri, che possono essere archiviati nelle proprietà della classe da usare in un metodo hub. Per altre informazioni, vedere Inserire i servizi in un hub

Blazor

Gestire gli eventi di modifica della posizione e lo stato di spostamento

In .NET 7 Blazor supporta la modifica della posizione degli eventi e la gestione dello stato di spostamento. In questo modo è possibile avvisare gli utenti del lavoro non salvato o di eseguire azioni correlate quando l'utente esegue una navigazione nella pagina.

Per altre informazioni, vedere le sezioni seguenti dell'articolo Routing e navigazione :

Modelli di progetto vuoti Blazor

Blazor ha due nuovi modelli di progetto per iniziare da uno slate vuoto. I nuovi Blazor Server modelli di progetto App Empty eBlazor WebAssembly App Empty sono esattamente come le controparti non vuote, ma senza codice di esempio. Questi modelli vuoti includono solo una pagina di base home ed è stato rimosso Bootstrap in modo da poter iniziare con un framework CSS diverso.

Per altre informazioni, vedere gli articoli seguenti:

Elementi personalizzati di Blazor

Il Microsoft.AspNetCore.Components.CustomElements pacchetto abilita la compilazione di elementi DOM personalizzati basati su standard usando Blazor.

Per altre informazioni, vedere ASP.NET Componenti di baseRazor.

Modificatori di binding (@bind:after, @bind:get, @bind:set)

Importante

Le @bind:after//@bind:get@bind:set funzionalità ricevono ulteriori aggiornamenti in questo momento. Per sfruttare i vantaggi degli aggiornamenti più recenti, verificare di aver installato l'SDK più recente.

L'uso di un parametro di callback di eventi ([Parameter] public EventCallback<string> ValueChanged { get; set; }) non è supportato. Passare invece un Actionmetodo -returning o Task-returning a/@bind:set@bind:after .

Per ulteriori informazioni, vedi le seguenti risorse:

In .NET 7 è possibile eseguire la logica asincrona dopo il completamento di un evento di associazione usando il nuovo @bind:after modificatore. Nell'esempio seguente il PerformSearch metodo asincrono viene eseguito automaticamente dopo che sono state rilevate modifiche al testo di ricerca:

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

@code {
    private string searchText;

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

In .NET 7 è anche più semplice configurare l'associazione per i parametri del componente. I componenti possono supportare il data binding bidirezionale definendo una coppia di parametri:

  • @bind:get: specifica il valore da associare.
  • @bind:set: specifica un callback per quando il valore cambia.

I @bind:get modificatori e @bind:set vengono sempre usati insieme.

Esempi:

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

Per altre informazioni sul InputText componente, vedere ASP.NET Componenti di input principaliBlazor.

miglioramenti Ricaricamento rapido

In .NET 7, Ricaricamento rapido supporto include quanto segue:

  • I componenti reimpostano i relativi parametri ai valori predefiniti quando viene rimosso un valore.
  • Blazor WebAssembly:
    • Aggiungere nuovi tipi.
    • Aggiungere classi annidate.
    • Aggiungere metodi statici e di istanza ai tipi esistenti.
    • Aggiungere campi e metodi statici ai tipi esistenti.
    • Aggiungere espressioni lambda statiche ai metodi esistenti.
    • Aggiungere espressioni lambda che acquisiscino this ai metodi esistenti già acquisiti this in precedenza.

Richieste di autenticazione dinamica con MSAL in Blazor WebAssembly

Novità di .NET 7 supporta Blazor WebAssembly la creazione di richieste di autenticazione dinamica in fase di esecuzione con parametri personalizzati per gestire scenari di autenticazione avanzati.

Per altre informazioni, vedere gli articoli seguenti:

Blazor WebAssembly miglioramenti al debug

Blazor WebAssembly Il debug presenta i miglioramenti seguenti:

  • Supporto per l'impostazione Just My Code per mostrare o nascondere i membri di tipo che non provengono dal codice utente.
  • Supporto per l'ispezione di matrici multidimensionali.
  • Stack di chiamate mostra ora il nome corretto per i metodi asincroni.
  • Valutazione migliorata delle espressioni.
  • Gestione corretta della new parola chiave nei membri derivati.
  • Supporto per gli attributi correlati al debugger in System.Diagnostics.

System.Security.Cryptography supporto in WebAssembly

.NET 6 supporta la famiglia sha di algoritmi hash durante l'esecuzione in WebAssembly. .NET 7 consente un maggior numero di SubtleCryptoalgoritmi di crittografia sfruttando , quando possibile, e eseguendo il fallback a un'implementazione .NET quando SubtleCrypto non è possibile usare . Gli algoritmi seguenti sono supportati in WebAssembly in .NET 7:

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

Per altre informazioni, vedere Developers targeting browser-wasm can use Web Crypto APIs (dotnet/runtime #40074).

Inserire i servizi negli attributi di convalida personalizzati

È ora possibile inserire i servizi negli attributi di convalida personalizzati. Blazor imposta l'oggetto ValidationContext in modo che possa essere usato come provider di servizi.

Per altre informazioni, vedere ASP.NET Convalida dei moduli principaliBlazor.

Input* componenti esterni a un EditContext/EditForm

I componenti di input predefiniti sono ora supportati all'esterno di un modulo nel Razor markup dei componenti.

Per altre informazioni, vedere ASP.NET Componenti di input coreBlazor.

Modifiche al modello di progetto

Quando .NET 6 è stato rilasciato lo scorso anno, il markup HTML della pagina (Pages/_Host.chstml) è stato suddiviso tra la _Host pagina e una nuova _Layout pagina (Pages/_Layout.chstml) nel modello di progetto .NET 6Blazor Server._Host

In .NET 7 il markup HTML è stato ricombinato con la _Host pagina nei modelli di progetto.

Sono state apportate diverse modifiche aggiuntive ai modelli di Blazor progetto. Non è possibile elencare tutte le modifiche apportate ai modelli nella documentazione. Per eseguire la migrazione di un'app a .NET 7 per adottare tutte le modifiche, vedere Eseguire la migrazione da ASP.NET Core 6.0 a 7.0.

Componente sperimentale QuickGrid

Il nuovo QuickGrid componente fornisce un pratico componente griglia di dati per i requisiti più comuni e come architettura di riferimento e baseline delle prestazioni per chiunque compili Blazor componenti della griglia dati.

Per altre informazioni, vedere ASP.NET componente Core Blazor QuickGrid.

Demo live: QuickGrid per un'app Blazor di esempio

Miglioramenti della virtualizzazione

Miglioramenti della virtualizzazione in .NET 7:

  • Il Virtualize componente supporta l'uso del documento stesso come radice di scorrimento, in alternativa all'applicazione di un altro elemento overflow-y: scroll .
  • Se il Virtualize componente viene inserito all'interno di un elemento che richiede un nome di tag figlio specifico, SpacerElement consente di ottenere o impostare il nome del tag di spacer di virtualizzazione.

Per altre informazioni, vedere le sezioni seguenti dell'articolo Virtualizzazione :

MouseEventArgs Aggiornamenti

MovementX e MovementY sono stati aggiunti a MouseEventArgs.

Per altre informazioni, vedere ASP.NET Gestione degli eventi CoreBlazor.

Nuova Blazor pagina di caricamento

Il Blazor WebAssembly modello di progetto ha una nuova interfaccia utente di caricamento che mostra lo stato di avanzamento del caricamento dell'app.

Per altre informazioni, vedere ASP.NET avvio di CoreBlazor.

Diagnostica migliorata per l'autenticazione in Blazor WebAssembly

Per diagnosticare i problemi di autenticazione nelle Blazor WebAssembly app, è disponibile la registrazione dettagliata.

Per altre informazioni, vedere registrazione ASP.NET CoreBlazor.

Interoperabilità JavaScript in WebAssembly

L'API di interoperabilità JavaScript [JSImport]/[JSExport] è un nuovo meccanismo di basso livello per l'uso di .NET nelle Blazor WebAssembly app basate su JavaScript e . Con questa nuova funzionalità di interoperabilità JavaScript, è possibile richiamare il codice .NET da JavaScript usando il runtime .NET WebAssembly e chiamare la funzionalità JavaScript da .NET senza alcuna dipendenza dal modello del componente dell'interfaccia Blazor utente.

Per altre informazioni:

Registrazione condizionale del provider di stato di autenticazione

Prima del rilascio di .NET 7, AuthenticationStateProvider è stato registrato nel contenitore del servizio con AddScoped. In questo modo è stato difficile eseguire il debug delle app, perché ha forzato un ordine specifico di registrazioni del servizio quando si fornisce un'implementazione personalizzata. A causa delle modifiche al framework interno nel tempo, non è più necessario eseguire la registrazione AuthenticationStateProvider con AddScoped.

Nel codice per sviluppatore apportare le modifiche seguenti alla registrazione del servizio del provider di stato di autenticazione:

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

Nell'esempio precedente è ExternalAuthStateProvider l'implementazione del servizio dello sviluppatore.

Miglioramenti agli strumenti di compilazione WebAssembly .NET

Nuove funzionalità del wasm-tools carico di lavoro per .NET 7 che consentono di migliorare le prestazioni e gestire le eccezioni:

Per altre informazioni, vedere ASP.NET Compilazione di core Blazor WebAssembly e compilazione anticipata (AOT).

Blazor Hybrid

URL esterni

È stata aggiunta un'opzione che consente di aprire pagine Web esterne nel browser.

Per altre informazioni, vedere ASP.NET routing e navigazione coreBlazor Hybrid.

Sicurezza

Sono disponibili nuove indicazioni per Blazor Hybrid gli scenari di sicurezza. Per altre informazioni, vedere gli articoli seguenti:

Prestazioni

Middleware di memorizzazione nella cache di output

La memorizzazione nella cache dell'output è un nuovo middleware che archivia le risposte da un'app Web e le gestisce da una cache anziché elaborarle ogni volta. La memorizzazione nella cache dell'output differisce dalla memorizzazione nella cache delle risposte nei modi seguenti:

  • Il comportamento di memorizzazione nella cache è configurabile nel server.
  • Le voci della cache possono essere invalidate a livello di codice.
  • Il blocco delle risorse riduce il rischio di cache stampede e fulmine.
  • La riconvalida della cache indica che il server può restituire un 304 Not Modified codice di stato HTTP anziché un corpo della risposta memorizzato nella cache.
  • Il supporto di archiviazione della cache è estendibile.

Per altre informazioni, vedere Panoramica della memorizzazione nella cache e del middleware di memorizzazione nella cache di output.

Miglioramenti di HTTP/3

Questa versione:

  • Rende HTTP/3 completamente supportato da ASP.NET Core, non è più sperimentale.
  • Migliora il Kestrelsupporto di HTTP/3. Le due aree principali del miglioramento sono la parità delle funzionalità con HTTP/1.1 e HTTP/2 e le prestazioni.
  • Fornisce supporto completo per UseHttps(ListenOptions, X509Certificate2) con HTTP/3. Kestreloffre opzioni avanzate per la configurazione dei certificati di connessione, ad esempio l'associazione all'indicazione del nome del server (SNI).
  • Aggiunge il supporto per HTTP/3 in HTTP.sys e IIS.

L'esempio seguente illustra come usare un callback SNI per risolvere le opzioni 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);
            },
        });
    });
});

Sono state eseguite operazioni significative in .NET 7 per ridurre le allocazioni HTTP/3. È possibile visualizzare alcuni di questi miglioramenti nelle richieste pull di GitHub seguenti:

Miglioramenti delle prestazioni HTTP/2

.NET 7 introduce una ri-architettura significativa del modo in cui Kestrel elabora le richieste HTTP/2. ASP.NET le app core con connessioni HTTP/2 occupato avranno una riduzione dell'utilizzo della CPU e una maggiore velocità effettiva.

In precedenza, l'implementazione del multiplexing HTTP/2 si basava su un controllo di blocco che può scrivere nella connessione TCP sottostante. Una coda thread-safe sostituisce il blocco di scrittura. Ora, invece di combattere su quale thread ottiene l'uso del blocco di scrittura, le richieste ora in coda e un consumer dedicato li elabora. Le risorse cpu sprecate in precedenza sono disponibili per l'oggetto rest dell'app.

Un luogo in cui questi miglioramenti possono essere notati è in gRPC, un framework RPC popolare che usa HTTP/2. Kestrel + benchmark gRPC mostrano un miglioramento significativo:

Prestazioni di streaming del server gRPC

Le modifiche sono state apportate nel codice di scrittura di frame HTTP/2 che migliora le prestazioni quando sono presenti più flussi che tentano di scrivere dati in una singola connessione HTTP/2. È ora possibile inviare tls al pool di thread e rilasciare più rapidamente un blocco di scrittura che altri flussi possono acquisire per scrivere i dati. La riduzione dei tempi di attesa può produrre miglioramenti significativi delle prestazioni nei casi in cui è presente una contesa per questo blocco di scrittura. Un benchmark gRPC con 70 flussi su una singola connessione (con TLS) ha mostrato un miglioramento del 15% delle richieste al secondo (RPS) con questa modifica.

Supporto di WebSocket Http/2

.NET 7 introduce il supporto webSocket su HTTP/2 per Kestrel, il SignalR client JavaScript e SignalR con Blazor WebAssembly.

L'uso di WebSocket su HTTP/2 sfrutta le nuove funzionalità, ad esempio:

  • Compressione dell'intestazione.
  • Multiplexing, che riduce il tempo e le risorse necessarie quando si effettuano più richieste al server.

Queste funzionalità supportate sono disponibili in in Kestrel tutte le piattaforme abilitate per HTTP/2. La negoziazione della versione è automatica nei browser e Kestrel, quindi non sono necessarie nuove API.

Per altre informazioni, vedere Supporto webSocket Http/2.

Kestrel miglioramenti delle prestazioni nei computer con core elevati

Kestrel utilizza ConcurrentQueue<T> per molti scopi. Uno scopo è pianificare le operazioni di I/O nel Kestreltrasporto Socket predefinito. ConcurrentQueue Il partizionamento basato sul socket associato riduce la contesa e aumenta la velocità effettiva nei computer con molti core CPU.

La profilatura su computer con core elevati in .NET 6 ha mostrato una contesa significativa in una delle Kestrelaltre ConcurrentQueue istanze di , che PinnedMemoryPool Kestrel usa per memorizzare nella cache i buffer di byte.

In .NET 7 il Kestrelpool di memoria viene partizionato allo stesso modo della coda di I/O, che comporta una contesa molto inferiore e una velocità effettiva più elevata nei computer con core elevati. Nelle 80 macchine virtuali ARM64 core si riscontra un miglioramento superiore al 500% delle risposte al secondo (RPS) nel benchmark techEmpower plaintext. Nelle macchine virtuali AMD core 48, il miglioramento è quasi del 100% nel benchmark JSON HTTPS.

ServerReady evento per misurare il tempo di avvio

Le app che usano EventSource possono misurare il tempo di avvio per comprendere e ottimizzare le prestazioni di avvio. Il nuovo ServerReady evento in rappresenta il punto in Microsoft.AspNetCore.Hosting cui il server è pronto per rispondere alle richieste.

Server

Nuovo evento ServerReady per misurare il tempo di avvio

L'evento ServerReady è stato aggiunto per misurare il tempo di avvio delle app ASP.NET Core.

IIS

Copia shadow in IIS

La copia shadow degli assembly dell'app nell'ASP.NET Core Module (ANCM) per IIS può offrire un'esperienza utente finale migliore rispetto all'arresto dell'app distribuendo un file offline dell'app.

Per altre informazioni, vedere Copia shadow in IIS.

Varie

Kestrel miglioramenti completi della catena di certificati

HttpsConnectionAdapterOptions include una nuova proprietà ServerCertificateChain di tipo X509Certificate2Collection, che semplifica la convalida delle catene di certificati consentendo di specificare una catena completa, inclusi i certificati intermedi. Per altri dettagli, vedere dotnet/aspnetcore#21513 .

dotnet watch

Miglioramento dell'output della console per dotnet watch

L'output della console di dotnet Watch è stato migliorato per migliorare l'allineamento con la registrazione di ASP.NET Core e per distinguersi con 😮emoji😍.

Ecco un esempio dell'aspetto del nuovo output:

output per dotnet watch

Per altre informazioni, vedere questa richiesta pull di GitHub.

Configurare dotnet watch per riavviare sempre per le modifiche scortesi

Le modifiche scortesi sono modifiche che non possono essere ricaricate a caldo. Per configurare dotnet watch per il riavvio sempre senza richiedere modifiche scortesi, impostare la DOTNET_WATCH_RESTART_ON_RUDE_EDIT variabile di ambiente su true.

Modalità scura della pagina delle eccezioni per sviluppatori

Il supporto per la modalità scura è stato aggiunto alla pagina delle eccezioni dello sviluppatore, grazie a un contributo di Patrick Westerhoff. Per testare la modalità scura in un browser, dalla pagina degli strumenti di sviluppo impostare la modalità su scura. Ad esempio, in Firefox:

Modalità scura F12 tools FF

In Chrome:

Strumenti F12 Modalità scura chrome

Opzione modello di progetto per l'uso del metodo Program.Main invece delle istruzioni di primo livello

I modelli .NET 7 includono un'opzione per non usare istruzioni di primo livello e generare un namespace e un Main metodo dichiarato in una Program classe.

Usando l'interfaccia della riga di comando di .NET, usare l'opzione --use-program-main :

dotnet new web --use-program-main

Con Visual Studio selezionare la nuova casella di controllo Non usare istruzioni di primo livello durante la creazione del progetto:

casella di controllo

Modelli di Angular e React aggiornati

Il modello di progetto Angular è stato aggiornato a Angular 14. Il modello di progetto React è stato aggiornato a React 18.2.

Gestire i token Web JSON in fase di sviluppo con dotnet user-jwts

Il nuovo dotnet user-jwts strumento da riga di comando può creare e gestire token WEB JSON locali specifici dell'app. Per altre informazioni, vedere Gestire token Web JSON in fase di sviluppo con dotnet user-jwts.

Supporto per intestazioni di richiesta aggiuntive in W3CLogger

È ora possibile specificare intestazioni di richiesta aggiuntive da registrare quando si usa il logger W3C chiamando AdditionalRequestHeaders() su W3CLoggerOptions:

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

Per altre informazioni, vedere Opzioni W3CLogger.

Decompressione delle richieste

Nuovo middleware di decompressione della richiesta:

  • Consente agli endpoint API di accettare richieste con contenuto compresso.
  • Usa l'intestazione Content-Encoding HTTP per identificare e decomprimere automaticamente le richieste che contengono contenuto compresso.
  • Elimina la necessità di scrivere codice per gestire le richieste compresse.

Per altre informazioni, vedere Richiedere il middleware di decompressione.