Dela via


Nyheter i ASP.NET Core 7.0

Den här artikeln belyser de viktigaste ändringarna i ASP.NET Core 7.0 med länkar till relevant dokumentation.

Hastighetsbegränsning av mellanprogram i ASP.NET Core

Det Microsoft.AspNetCore.RateLimiting-mellanprogrammet ger ett mellanprogram för hastighetsbegränsning. Appar konfigurerar principer för hastighetsbegränsning och kopplar sedan principerna till slutpunkter. Mer information finns i Hastighetsbegränsning för mellanprogram i ASP.NET Core.

Autentisering använder ett enda schema som DefaultScheme

Som en del av arbetet med att förenkla autentiseringen, när det bara finns ett enda autentiseringsschema registrerat, används det automatiskt som DefaultScheme och behöver inte anges. Mer information finns i DefaultScheme.

MVC- och Razor-sidor

Stöd för nullbara modeller i MVC-vyer och Razor-sidor

Nullsid- och vymodeller stöds för att förbättra upplevelsen vid kontroll av null-tillstånd med ASP.NET Core-appar.

@model Product?

Binda med IParsable<T>.TryParse i MVC- och API-styrenheter

API:et IParsable<TSelf>.TryParse stöder parametervärden för bindningskontrollantåtgärd. Mer information finns i Bind med IParsable<T>.TryParse.

I ASP.NET Core-versioner tidigare än 7 använder cookie medgivandeverifiering det cookie värdet yes för att ange medgivande. Nu kan du ange det värde som representerar medgivande. Du kan till exempel använda true i stället för 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();

Mer information finns i Anpassa cookie värdet för samtycke.

API-kontrollanter

Parameterbindning med DI i API-kontrollanter

Parameterbindning för API-kontrollantåtgärder binder parametrar via beroendeinmatning när typen konfigureras som en tjänst. Det innebär att det inte längre krävs att uttryckligen tillämpa attributet [FromServices] på en parameter. I följande kod returnerar båda åtgärderna tiden:

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

I sällsynta fall kan automatisk DI bryta appar som har en typ i DI som också accepteras i en API-kontrollantåtgärdsmetod. Det är inte vanligt att ha en typ i DI och som argument i en API-kontrollantåtgärd. Om du vill inaktivera automatisk bindning av parametrar anger du 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();

I ASP.NET Core 7.0 kontrolleras typer i DI vid appstart med IServiceProviderIsService för att avgöra om ett argument i en API-kontrollantåtgärd kommer från DI eller från andra källor.

Den nya mekanismen för att härleda bindningskällan för API Controller-åtgärdsparametrar använder följande regler:

  1. En tidigare specificerad BindingInfo.BindingSource skrivs aldrig över.
  2. En komplex typparameter, registrerad i DI-containern, tilldelas BindingSource.Services.
  3. En komplex typparameter, som inte är registrerad i DI-containern, tilldelas BindingSource.Body.
  4. En parameter med ett namn som visas som ett vägvärde i någon rutmall tilldelas BindingSource.Path.
  5. Alla andra parametrar är BindingSource.Query.

JSON-egenskapsnamn i valideringsfel

När ett valideringsfel inträffar skapar modellverifiering som standard en ModelStateDictionary med egenskapsnamnet som felnyckel. Vissa appar, till exempel ensidiga applikationer, drar fördel av att använda JSON-egenskapsnamn för valideringsfel som genereras från webb-API:er. Följande kod konfigurerar validering för att använda SystemTextJsonValidationMetadataProvider för att använda JSON-egenskapsnamn:

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

Följande kod konfigurerar validering för att använda NewtonsoftJsonValidationMetadataProvider för att använda JSON-egenskapsnamn när du använder 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();

Mer information finns i Använda JSON-egenskapsnamn i verifieringsfel

Minimala API:er

Filter i minimala API-appar

Med minimala API-filter kan utvecklare implementera affärslogik som stöder:

  • Kör kod före och efter routningshanteraren.
  • Inspektera och ändra parametrar som tillhandahålls vid ett routahanterarens anrop.
  • Fånga upp svarsbeteendet hos en routerhanterare.

Filter kan vara användbara i följande scenarier:

  • Validera parametrarna och innehållet i begäran som skickas till en slutpunkt.
  • Loggningsinformation om begäran och svar.
  • Verifiera att en begäran riktar sig till en API-version som stöds.

Mer information finns i filter i Minimala API-appar

Binda matriser och strängvärden från rubriker och frågesträngar

I ASP.NET 7 stöds bindning av frågesträngar till en matris med primitiva typer, strängmatriser och 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]}");

Bindning av frågesträngar eller sidhuvudvärden till en matris med komplexa typer stöds när typen har TryParse implementerats. För mer information, se Bindning av matriser och strängvärden från rubriker och frågesträngar.

Mer information finns i Lägg till slutpunktssammanfattning eller beskrivning.

Binda begärandetexten som en Stream eller PipeReader

Begärandetexten kan bindas som en Stream eller PipeReader för att effektivt stödja scenarier där användaren måste bearbeta data och:

  • Lagra data i bloblagring eller lagra data i en kötjänst.
  • Bearbeta lagrade data med en arbetsprocess eller molnfunktion.

Data kan till exempel köas i Azure Queue Storage eller lagras i Azure Blob Storage.

Mer information finns i Binda begärandetexten som en Stream eller PipeReader

Nya överlagringar i Results.Stream

Vi introducerade nya Results.Stream överlagringar för att hantera scenarier som behöver åtkomst till den underliggande HTTP-svarsströmmen utan buffring. Dessa överlagringar förbättrar också fall där ett API strömmar data till HTTP-svarsströmmen, till exempel från Azure Blob Storage. I följande exempel används ImageSharp- för att returnera en reducerad storlek på den angivna bilden:

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

Mer information finns i Stream-exempel

Inskrivna resultat för minimala API:er

I .NET 6 introducerades IResult-gränssnittet för att representera värden som returneras från minimala API:er som inte använder implicit stöd för JSON-serialisering av det returnerade objektet till HTTP-svaret. Klassen static Results används för att skapa varierande IResult objekt som representerar olika typer av svar. Du kan till exempel ange svarsstatuskoden eller omdirigera till en annan URL. Den IResult implementering av ramverkstyper som returnerades från dessa metoder var dock intern, vilket gör det svårt att verifiera den specifika IResult typ som returneras från metoder i ett enhetstest.

I .NET 7 är de typer som implementerar IResult offentliga, vilket möjliggör typkontroller vid testning. Till exempel:

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

Förbättrad enhetstestbarhet för minimala routningshanterare

IResult implementeringstyper är nu offentligt tillgängliga i Microsoft.AspNetCore.Http.HttpResults namnområdet. De IResult implementeringstyperna kan användas för att enhetstesta minimala routningshanterare när du använder namngivna metoder i stället för lambdas.

Följande kod använder klassen Ok<TValue>:

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

Mer information finns i IResult implementeringstyper.

Nya HttpResult-gränssnitt

Följande gränssnitt i namnområdet Microsoft.AspNetCore.Http ger ett sätt att identifiera IResult typen under körning, vilket är ett vanligt mönster i filterimplementeringar.

Mer information finns i IHttpResult-gränssnitt.

OpenAPI-förbättringar för minimala API:er

Microsoft.AspNetCore.OpenApi NuGet-paket

Microsoft.AspNetCore.OpenApi-paketet tillåter interaktioner med OpenAPI-specifikationer för slutpunkter. Paketet fungerar som en länk mellan OpenAPI-modellerna som definieras i Microsoft.AspNetCore.OpenApi-paketet och de slutpunkter som definieras i Minimala API:er. Paketet tillhandahåller ett API som undersöker en slutpunkts parametrar, svar och metadata för att konstruera en OpenAPI-anteckningstyp som används för att beskriva en slutpunkt.

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

Anropa WithOpenApi med parametrar

Metoden WithOpenApi accepterar en funktion som kan användas för att ändra OpenAPI-kommentaren. I följande kod läggs till exempel en beskrivning till i slutpunktens första parameter:

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

Ange slutpunktsbeskrivningar och sammanfattningar

Minimala API:er stöder nu anteckningar med beskrivningar och sammanfattningar för generering av OpenAPI-specifikation. Du kan anropa tilläggsmetoder WithDescription och WithSummary eller använda attribut [EndpointDescription] och [EndpointSummary]).

Mer information finns i OpenAPI i minimala API-appar

Filuppladdningar med IFormFile och IFormFileCollection

Minimala API:er stöder nu filuppladdning med IFormFile och IFormFileCollection. Följande kod använder IFormFile och IFormFileCollection för att ladda upp filen:

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

Autentiserade filuppladdningsbegäranden stöds med hjälp av ett auktoriseringshuvud, ett klientcertifikateller ett cookie-huvud.

Det finns inget inbyggt stöd för falskningsskydd. Den kan dock implementeras med hjälp av IAntiforgery-tjänsten.

[AsParameters]-attributet aktiverar parameterbindning för argumentlistor

Attributet [AsParameters] aktiverar parameterbindning för argumentlistor. Mer information finns i Parameterbindning för argumentlistor med [AsParameters].

Minimala API:er och API-kontrollanter

Ny probleminformationstjänst

Probleminformationstjänsten implementerar IProblemDetailsService-gränssnittet, som har stöd för att skapa probleminformation för HTTP-API:er.

Mer information finns i Probleminformationstjänsten.

Routtgrupper

Tilläggsmetoden MapGroup hjälper till att organisera grupper av slutpunkter med ett gemensamt prefix. Det minskar repetitiv kod och gör det möjligt att anpassa hela grupper av slutpunkter med ett enda anrop till metoder som RequireAuthorization och WithMetadata som lägger till slutpunktsmetadata.

Följande kod skapar till exempel två liknande grupper av slutpunkter:

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

I det här scenariot kan du använda en relativ adress för Location-huvudet i 201 Created resultat:

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

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

Den första gruppen med slutpunkter matchar endast begäranden som är prefix med /public/todos och är tillgängliga utan autentisering. Den andra gruppen med slutpunkter matchar endast begäranden som är prefix med /private/todos och kräver autentisering.

QueryPrivateTodos slutpunktsfilterfabriken är en lokal funktion som ändrar routningshanterarens TodoDb parametrar för att tillåta åtkomst till och lagra privata data.

Routningsgrupper stöder också kapslade grupper och komplexa prefixmönster med vägparametrar och begränsningar. I följande exempel kan routhanteraren som mappas till gruppen user fånga de {org}- och {group}-routningsparametrar som definierats i de yttre gruppens prefix.

Prefixet kan också vara tomt. Detta kan vara användbart för att lägga till slutpunktsmetadata eller filter till en grupp slutpunkter utan att ändra vägmönstret.

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

Att lägga till filter eller metadata i en grupp fungerar på samma sätt som att lägga till dem individuellt i varje slutpunkt innan du lägger till extra filter eller metadata som kan ha lagts till i en inre grupp eller en specifik slutpunkt.

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

I exemplet ovan loggar det yttre filtret den inkommande begäran före det inre filtret trots att det lades till tvåa. Eftersom filtren tillämpades på olika grupper spelar det ingen roll vilken ordning de lades till i förhållande till varandra. Orderfiltren som läggs till spelar roll om de tillämpas på samma grupp eller specifika slutpunkt.

En begäran om att /outer/inner/ loggar följande:

/outer group filter
/inner group filter
MapGet filter

gRPC

JSON-transkodning

gRPC JSON-transkodning är ett tillägg för ASP.NET Core som skapar RESTful JSON-API:er för gRPC-tjänster. gRPC JSON-omkodning tillåter:

  • Appar som anropar gRPC-tjänster med välbekanta HTTP-begrepp.
  • ASP.NET Core gRPC-appar som stöder både gRPC- och RESTful JSON-API:er utan att replikera funktioner.
  • Experimentellt stöd för att generera OpenAPI från transkodade RESTful-API:er genom att integrera med Swashbuckle.

Mer information finns i gRPC JSON-omkodning i ASP.NET Core gRPC-appar och Använda OpenAPI med gRPC JSON-transkodning ASP.NET Core-appar.

gRPC-hälsokontroller i ASP.NET Core

Protokollet gRPC-hälsokontroll är en standard för rapportering av hälsotillståndet för gRPC-serverappar. En app erbjuder hälsokontroller som en gRPC-tjänst. De används vanligtvis med en extern övervakningstjänst för att kontrollera status för en app.

gRPC ASP.NET Core har lagt till inbyggt stöd för gRPC-hälsokontroller med Grpc.AspNetCore.HealthChecks-paketet. Resultat från .NET-hälsokontroller rapporteras till de som anropar.

För mer information, se gRPC-hälsokontroller i ASP.NET Core.

Förbättrat stöd för autentiseringsuppgifter för samtal

Autentiseringsuppgifter för anrop är det rekommenderade sättet att konfigurera en gRPC-klient för att skicka en autentiseringstoken till servern. gRPC-klienter har stöd för två nya funktioner för att göra anropsuppgifterna enklare att använda:

  • Stöd för autentiseringsuppgifter för samtal med klartextanslutningar. Tidigare skickade ett gRPC-anrop endast autentiseringsuppgifter för samtal om anslutningen var skyddad med TLS. Med en ny inställning för GrpcChannelOptions, som kallas UnsafeUseInsecureChannelCallCredentials, kan det här beteendet anpassas. Det finns säkerhetsaspekter för att inte skydda en anslutning med TLS.
  • En ny metod med namnet AddCallCredentials är tillgänglig med gRPC-klientfabrik. AddCallCredentials är ett snabbt sätt att konfigurera autentiseringsuppgifter för anrop för en gRPC-klient och integrerar väl med beroendeinmatning (DI).

Följande kod konfigurerar gRPC-klientfabriken för att skicka 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;
    });

För mer information, se Konfigurera en bearertoken med gRPC-klientfabriken.

SignalR

Klientresultat

Servern har nu stöd för att begära ett resultat från en klient. Detta kräver att servern använder ISingleClientProxy.InvokeAsync och att klienten ska returnera ett resultat från sin .On-hanterare. Starkt typade hubbar kan också returnera värden från gränssnittsmetoder.

Mer information finns i klientresultat

Beroendeinmatning för SignalR hubbmetoder

SignalR hubbmetoder stöder nu inmatning av tjänster via beroendeinmatning (DI).

Hubbkonstruktorer kan acceptera tjänster från DI som parametrar, som kan lagras i egenskaper i klassen för användning i en hubbmetod. Mer information finns i Mata in tjänster i en hubb

Blazor

Hantera platsändringshändelser och navigeringstillstånd

I .NET 7 stöder Blazor platsändringshändelser och underhåll av navigeringstillstånd. På så sätt kan du varna användare om arbete som inte har sparats eller utföra relaterade åtgärder när användaren utför en sidnavigering.

Mer information finns i följande avsnitt i artikeln Routning och navigering:

Tomma Blazor projektmallar

Blazor har två nya projektmallar för att starta från en tom skiffer. De nya Blazor Server App Empty och Blazor WebAssembly App Empty-projektmallar är precis som deras icke-tomma motsvarigheter men utan exempelkod. De här tomma mallarna innehåller bara en grundläggande startsida och vi har tagit bort Bootstrap så att du kan börja med ett annat CSS-ramverk.

Mer information finns i följande artiklar:

Blazor specialanpassade element

Med Microsoft.AspNetCore.Components.CustomElements-paketet kan du skapa standardbaserade anpassade DOM-element med hjälp av Blazor.

Mer information finns i ASP.NET Core Razor-komponenter.

Bindningsmodifierare (@bind:after, @bind:get, @bind:set)

Viktig

De @bind:after/@bind:get/@bind:set funktionerna får för närvarande ytterligare uppdateringar. Om du vill dra nytta av de senaste uppdateringarna bekräftar du att du har installerat senaste SDK-.

Det går inte att använda en händelseåteranropsparameter ([Parameter] public EventCallback<string> ValueChanged { get; set; }). Skicka i stället en Action-returning- eller Task-returning-metod till @bind:set/@bind:after.

Mer information finns i följande resurser:

I .NET 7 kan du köra asynkron logik när en bindningshändelse har slutförts med hjälp av den nya @bind:after-modifieraren. I följande exempel körs den PerformSearch asynkrona metoden automatiskt när ändringar i söktexten har identifierats:

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

@code {
    private string searchText;

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

I .NET 7 är det också enklare att konfigurera bindning för komponentparametrar. Komponenter kan stödja dubbelriktad databindning genom att definiera ett par parametrar:

  • @bind:get: Anger värdet som ska bindas.
  • @bind:set: Anger ett återanrop för när värdet ändras.

De @bind:get och @bind:set modifierare används alltid tillsammans.

Exempel:

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

Mer information om komponenten InputText finns i ASP.NET Core Blazor-indatakomponenter.

Förbättringar av hot reload

I .NET 7 innehåller stöd för frekvent omläsning följande:

  • Komponenter återställer sina parametrar till sina standardvärden när ett värde tas bort.
  • Blazor WebAssembly:
    • Lägg till nya typer.
    • Lägg till kapslade klasser.
    • Lägg till statiska metoder och instansmetoder i befintliga typer.
    • Lägg till statiska fält och metoder i befintliga typer.
    • Lägg till statiska lambdas i befintliga metoder.
    • Lägg till lambdas som infångar this i befintliga metoder som tidigare redan infångade this.

Begäranden om dynamisk autentisering med MSAL i Blazor WebAssembly

Ny i .NET 7 har Blazor WebAssembly stöd för att skapa begäranden om dynamisk autentisering vid körning med anpassade parametrar för att hantera avancerade autentiseringsscenarier.

Mer information finns i följande artiklar:

Blazor WebAssembly felsökningsförbättringar

Blazor WebAssembly felsökning har följande förbättringar:

  • Stöd för inställningen Just My Code för att visa eller dölja typmedlemmar som inte är från användarkoden.
  • Stöd för att inspektera flerdimensionella matriser.
  • Anropsstack visar nu rätt namn för asynkrona metoder.
  • Förbättrad uttrycksutvärdering.
  • Korrekt hantering av nyckelordet new på härledda medlemmar.
  • Stöd för felsökningsrelaterade attribut i System.Diagnostics.

System.Security.Cryptography stöd på WebAssembly

.NET 6 har stöd för SHA-serien med hashalgoritmer när de körs på WebAssembly. .NET 7 möjliggör fler kryptografiska algoritmer genom att dra nytta av SubtleCrypto, när det är möjligt och återgå till en .NET-implementering när SubtleCrypto inte kan användas. Följande algoritmer stöds på WebAssembly i .NET 7:

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

Mer information finns i Utvecklare som riktar in sig på webbläsar-wasm kan använda API:er för webbkryptering (dotnet/runtime #40074).

Mata in tjänster i anpassade valideringsattribut

Du kan nu mata in tjänster i anpassade valideringsattribut. Blazor konfigurerar ValidationContext så att den kan användas som tjänstleverantör.

Mer information finns i ASP.NET Core Blazor formulärverifiering.

Input* komponenter utanför en EditContext/EditForm

De inbyggda indatakomponenterna stöds nu utanför ett formulär i Razor komponentmarkering.

Mer information hittar du i ASP.NET Core Blazor indatakomponenter.

Ändringar i projektmall

När .NET 6 släpptes förra året delades HTML-koden på sidan _Host (Pages/_Host.chstml) mellan sidan _Host och en ny _Layout sida (Pages/_Layout.chstml) i projektmallen .NET 6 Blazor Server.

I .NET 7 har HTML-koden kombinerats med sidan _Host i projektmallar.

Flera ytterligare ändringar har gjorts i Blazor projektmallar. Det går inte att lista varje ändring av mallarna i dokumentationen. Information om hur du migrerar en app till .NET 7 för att implementera alla ändringar finns i Migrera från ASP.NET Core 6.0 till 7.0.

Experimentell QuickGrid komponent

Den nya QuickGrid-komponenten ger en praktisk komponent för datarutnät för de vanligaste kraven och som referensarkitektur och prestandabaslinje för alla som skapar Blazor datarutnätkomponenter.

Mer information finns i ASP.NET Core Blazor komponentenQuickGrid.

Livedemo: QuickGrid för Blazor exempelapp

Förbättringar av virtualisering

Virtualiseringsförbättringar i .NET 7:

  • Komponenten Virtualize stöder användning av själva dokumentet som rullningsrot, som ett alternativ till att använda något annat element med overflow-y: scroll.
  • Om Virtualize komponenten placeras i ett element som kräver ett specifikt underordnat taggnamn kan du SpacerElement hämta eller ange namnet på virtualiseringsavståndstaggen.

Mer information finns i följande avsnitt i artikeln Virtualisering:

MouseEventArgs uppdateringar

MovementX och MovementY har lagts till i MouseEventArgs.

Mer information finns i ASP.NET Core Blazor händelsehantering.

Ny Blazor inläsningssida

Blazor WebAssembly-projektmallen har ett nytt inläsningsgränssnitt som visar förloppet för inläsning av appen.

Mer information finns i ASP.NET Core Blazor start.

Förbättrad diagnostik för autentisering i Blazor WebAssembly

För att diagnostisera autentiseringsproblem i Blazor WebAssembly appar är detaljerad loggning tillgänglig.

Mer information finns i ASP.NET Core Blazor loggning.

JavaScript-interoperabilitet med WebAssembly

JavaScript [JSImport]/[JSExport] interop API är en ny lågnivåmekanism för användning av .NET i Blazor WebAssembly- och JavaScript-baserade appar. Med den här nya JavaScript-interopfunktionen kan du anropa .NET-kod från JavaScript med hjälp av .NET WebAssembly-körningen och anropa JavaScript-funktioner från .NET utan något beroende av komponentmodellen Blazor UI.

Mer information finns i:

Villkorsstyrd registrering av autentiseringstillståndsprovidern

Innan .NET 7 släpptes registrerades AuthenticationStateProvider i tjänstcontainern med AddScoped. Detta gjorde det svårt att felsöka appar eftersom det tvingade fram en viss ordning för tjänstregistreringar när en anpassad implementering tillhandahölls. På grund av interna ramverksändringar över tid behöver du inte längre registrera AuthenticationStateProvider med AddScoped.

I utvecklarkod gör du följande ändring av tjänstregistreringen för autentiseringstillståndsprovidern:

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

I föregående exempel är ExternalAuthStateProvider utvecklarens tjänstimplementering.

Förbättringar av .NET WebAssembly-byggverktygen

Nya funktioner i arbetsbelastningen wasm-tools för .NET 7 som hjälper till att förbättra prestanda och hantera undantag:

Mer information finns i ASP.NET Core Blazor WebAssembly byggverktyg och ahead-of-time (AOT) kompilering.

Blazor Hybrid

Externa URL:er

Ett alternativ har lagts till som tillåter att externa webbsidor öppnas i webbläsaren.

Mer information finns i ASP.NET Core Blazor Hybrid routning och navigering.

Säkerhet

Det finns ny vägledning för Blazor Hybrid säkerhetsscenarier. Mer information finns i följande artiklar:

Prestanda

Mellanprogram för cachelagring av utdata

Cachelagring av utdata är ett nytt mellanprogram som lagrar svar från en webbapp och hanterar dem från en cache i stället för att beräkna dem varje gång. Cachelagring av utdata skiljer sig från cachelagring av svar på följande sätt:

  • Cachelagringsbeteendet kan konfigureras på servern.
  • Cacheposter kan programmatiskt ogiltigförklaras.
  • Resurslåsning minskar risken för cache-anstormning och tordönsflock.
  • Cachevalidering innebär att servern kan returnera en 304 Not Modified HTTP-statuskod istället för ett cachelagrat svarsinnehåll.
  • Cachelagringsmediet är utökningsbart.

Mer information finns i Cacheöversikt och Mellanprogram för cachelagring av utdata.

HTTP/3-förbättringar

Den här versionen:

  • Säkerställer att HTTP/3 stöds fullt ut av ASP.NET Core och att det inte längre är experimentellt.
  • Förbättrar Kestrelstöd för HTTP/3. De två viktigaste förbättringsområdena är funktionsparitet med HTTP/1.1 och HTTP/2 samt prestanda.
  • Ger fullständigt stöd för UseHttps(ListenOptions, X509Certificate2) med HTTP/3. Kestrel erbjuder avancerade alternativ för att konfigurera anslutningscertifikat, till exempel att ansluta till SNI (Server Name Indication).
  • Lägger till stöd för HTTP/3 på HTTP.sys och IIS-.

I följande exempel visas hur du använder ett SNI-återanrop för att lösa TLS-alternativ:

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

Betydande arbete utfördes i .NET 7 för att minska HTTP/3-allokeringar. Du kan se några av dessa förbättringar i följande GitHub PR:er:

Prestandaförbättringar för HTTP/2

.NET 7 introducerar en betydande omarkitektur för hur Kestrel bearbetar HTTP/2-begäranden. ASP.NET Core-appar med upptagna HTTP/2-anslutningar får minskad CPU-användning och högre dataflöde.

Tidigare förlitade sig HTTP/2-multiplexingimplementeringen på ett lås för att styra vilken begäran som kan skriva till den underliggande TCP-anslutningen. En trådsäker kö ersätter skrivlåset. Nu, i stället för att slåss om vilken tråd som får använda skrivlåset, köar begäranden nu och en dedikerad konsument bearbetar dem. Tidigare bortkastade CPU-resurser är tillgängliga för resten av appen.

En plats där dessa förbättringar kan märkas finns i gRPC, ett populärt RPC-ramverk som använder HTTP/2. Kestrel + gRPC benchmarks visar en dramatisk förbättring:

gRPC-serveruppspelningsprestanda

Ändringar har gjorts i HTTP/2-ramens skrivkod som förbättrar prestandan när det finns flera strömmar som försöker skriva data på en enda HTTP/2-anslutning. Vi skickar nu TLS-arbete till trådpoolen och frigör snabbare ett skrivlås som andra strömmar kan tillgå för att skriva sin data. Den minskade väntetiden kan ge betydande prestandaförbättringar i fall där det råder konkurrens om det här skrivlåset. Ett gRPC-prestandatest med 70 strömmar på en enda anslutning (med TLS) visade en förbättring på cirka 15 %% i förfrågningar per sekund (RPS) med denna förändring.

Stöd för Http/2 WebSockets

.NET 7 introducerar WebSockets via HTTP/2-stöd för Kestrel, SignalR JavaScript-klienten och SignalR med Blazor WebAssembly.

Användning av WebSockets via HTTP/2 drar nytta av nya funktioner som:

  • Rubrikkomprimering.
  • Multiplexering, vilket minskar den tid och de resurser som behövs när du gör flera begäranden till servern.

Dessa funktioner som stöds är tillgängliga i Kestrel på alla HTTP/2-aktiverade plattformar. Versionsförhandlingen sker automatiskt i webbläsare och Kestrel, så inga nya API:er behövs.

Mer information finns i Http/2 WebSockets support.

Kestrel prestandaförbättringar på högkärnig datorer

Kestrel använder ConcurrentQueue<T> i många syften. Ett syfte är att schemalägga I/O-åtgärder i Kestrel:s standardtransport för Socket. Partitionering av ConcurrentQueue baserat på den associerade socketen minskar konkurrensen och ökar dataflödet på datorer med många CPU-kärnor.

Profilering på högkärniga datorer på .NET 6 visade betydande låsning i en av Kestrel:s andra ConcurrentQueue-instanser, PinnedMemoryPool som Kestrel använder för att cachelagra bytebuffertar.

I .NET 7 partitioneras Kestrelminnespool på samma sätt som dess I/O-kö, vilket leder till mycket lägre konkurrens och högre dataflöde på datorer med hög kärna. På ARM64 VMs med 80 kärnor ser vi en förbättring på över 500% i svar per sekund (RPS) i TechEmpower's benchmark för klartext. På 48-kärniga AMD-virtuella maskiner är förbättringen nästan 100% för vårt HTTPS JSON-riktmärke.

ServerReady händelse för att mäta starttiden

Appar som använder EventSource kan mäta starttiden för att förstå och optimera startprestanda. Den nya ServerReady händelsen i Microsoft.AspNetCore.Hosting representerar den punkt där servern är redo att svara på begäranden.

Server

Ny ServerReady-händelse för att mäta starttiden

Händelsen ServerReady har lagts till som mäter starttid för ASP.NET Core-appar.

IIS

Skuggkopiering i IIS

Skuggkopiering av appsammansättningar till ASP.NET Core Module (ANCM) för IIS kan ge en bättre slutanvändarupplevelse än att stoppa appen genom att distribuera en offlinefil för app.

Mer information finns i Skuggkopiering i IIS.

Diverse

Kestrel fullständiga förbättringar av certifikatkedjan

HttpsConnectionAdapterOptions har en ny ServerCertificateChain egenskap av typen X509Certificate2Collection, vilket gör det enklare att verifiera certifikatkedjor genom att tillåta att en fullständig kedja med mellanliggande certifikat anges. Mer information finns i dotnet/aspnetcore#21513.

dotnet watch

Förbättrade konsolutdata för dotnet watch

Konsolutdata från dotnet watch har förbättrats för att bättre överensstämma med loggningen av ASP.NET Core och för att sticka ut med 😮emojis😍.

Här är ett exempel på hur de nya utdata ser ut:

utdata för dotnet watch

Mer information finns i denna pull request på GitHub.

Konfigurera dotnet watch för att alltid starta om för oförskämda redigeringar

Oförskämda redigeringar är redigeringar som inte kan läsas in på nytt. Om du vill konfigurera dotnet watch för att alltid starta om utan en uppmaning om oförskämda redigeringar anger du DOTNET_WATCH_RESTART_ON_RUDE_EDIT miljövariabeln till true.

Mörkt läge för undantagssida för utvecklare

Stöd för mörkt läge har lagts till på undantagssidan för utvecklare tack vare ett bidrag från Patrick Westerhoff. Om du vill testa mörkt läge i en webbläsare från sidan med utvecklarverktyg anger du läget till mörkt. Till exempel i Firefox:

F12-verktyg FF mörkt läge

I Chrome:

F12 verktyg Chrome mörkt läge

Projektmallsalternativ för att använda Program.Main-metoden i stället för toppnivåinstruktioner

.NET 7-mallarna innehåller ett alternativ att inte använda toppnivåinstruktioner, och generera en namespace-metod och en Main-metod som deklarerats i en Program-klass.

Använd alternativet --use-program-main med .NET CLI:

dotnet new web --use-program-main

I Visual Studio väljer du kryssrutan Nya Använd inte instruktioner på den översta nivån när du skapar ett projekt:

kryssrutan

Angular- och React-mallar har uppdaterats

Angular-projektmallen har uppdaterats till Angular 14. React-projektmallen har uppdaterats till React 18.2.

Hantera JSON-webbtoken under utveckling med dotnet user-jwts

Det nya dotnet user-jwts kommandoradsverktyget kan skapa och hantera appspecifika lokala JSON-webbtoken (JWT). Mer information finns i Hantera JSON-webbtoken under utveckling med dotnet user-jwts.

Stöd för ytterligare begärandehuvuden i W3CLogger

Du kan nu ange ytterligare begärandehuvuden som ska loggas när du använder W3C-loggaren genom att anropa AdditionalRequestHeaders()W3CLoggerOptions:

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

Mer information finns i W3CLogger-alternativ.

Begär dekomprimering

Det nya Request decompression middleware:

  • Gör att API-slutpunkter kan acceptera begäranden med komprimerat innehåll.
  • Använder Content-Encoding HTTP-huvud för att automatiskt identifiera och dekomprimera begäranden som innehåller komprimerat innehåll.
  • Eliminerar behovet av att skriva kod för att hantera komprimerade begäranden.

Mer information finns i Request decompression middleware.