Freigeben über


Neuerungen in ASP.NET Core 7.0

In diesem Artikel werden die wichtigsten Änderungen in ASP.NET Core 7.0 aufgezeigt und Links zu relevanter Dokumentation bereitgestellt.

Middleware mit Bandbreitenbegrenzung in ASP.NET Core

Die Microsoft.AspNetCore.RateLimiting-Middleware bietet Middleware mit Bandbreitenbegrenzung. Apps konfigurieren Richtlinien zur Begrenzung der Bandbreite und wenden dann die Richtlinien auf Endpunkten an. Weitere Informationen finden Sie unter Middleware mit Bandbreitenbegrenzung in ASP.NET Core.

Authentifizierung verwendet ein einzelnes Schema als DefaultScheme

Im Rahmen der Vereinfachung der Authentifizierung wird, wenn nur ein einziges Authentifizierungsschema registriert ist, dieses automatisch als DefaultScheme verwendet und muss nicht angegeben werden. Weitere Informationen finden Sie unter DefaultScheme.

MVC und Razor-Seiten

Unterstützung für Nullwerte zulassende Modelle in MVC-Ansichten und Razor-Seiten

Nullwerte zulassende Seiten oder Ansichtsmodelle werden unterstützt, um die Erfahrung bei der Überprüfung des NULL-Status mit ASP.NET Core-Apps zu verbessern:

@model Product?

Binden mit IParsable<T>.TryParse in MVC und API-Controllern

Die IParsable<TSelf>.TryParse-API unterstützt das Binden von Parameterwerten für Controlleraktionen. Weitere Informationen finden Sie unter Binden mit IParsable<T>.TryParse.

In ASP.NET Core Versionen vor 7 verwendet die cookie Zustimmungsüberprüfung den cookie Wert yes, um Zustimmung anzugeben. Jetzt können Sie den Wert angeben, welcher die Zustimmung darstellt. So können Sie beispielsweise true anstelle von yes verwenden:

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

Weitere Informationen finden Sie unter Anpassen des cookie Zustimmungswerts.

API-Controller

Parameterbindung mit DI in API-Controllern

Parameterbindung für API-Controlleraktionen bindet Parameter durch Abhängigkeitsinjektion (Dependency Injection, DI), wenn der Typ als Dienst konfiguriert wird. Das bedeutet, dass es nicht mehr erforderlich ist, das Attribut [FromServices] explizit auf einen Parameter anzuwenden. Im folgenden Code geben beide Aktionen die Uhrzeit zurück:

[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 seltenen Fällen kann die automatische DI Apps zum Scheitern bringen, die einen Typ in DI haben, der auch in den Aktionsmethoden eines API-Controllers akzeptiert wird. Es ist nicht üblich, einen Typ in DI und als Argument in einer API-Controlleraktion zu verwenden. Um die automatische Bindung von Parametern zu deaktivieren, legen Sie DisableImplicitFromServicesParameters fest.

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 werden Typen in DI beim App-Start mit IServiceProviderIsService überprüft, um festzustellen, ob ein Argument in einer API-Controlleraktion aus DI oder den anderen Quellen stammt.

Der neue Mechanismus zur Ableitung der Bindungsquelle von Aktionsparametern des API-Controllers verwendet die folgenden Regeln:

  1. Ein zuvor angegebenes BindingInfo.BindingSource-Element wird nie überschrieben.
  2. Einem komplexen Typparameter, der im DI-Container registriert ist, wird BindingSource.Services zugewiesen.
  3. Einem komplexen Typparameter, der nicht im DI-Container registriert ist, wird BindingSource.Body zugewiesen.
  4. Einem Parameter mit einem Namen, der als Routenwert in jeder beliebigen Routenvorlage angezeigt wird, wird BindingSource.Path zugewiesen.
  5. Alle anderen Parameter sind BindingSource.Query.

JSON-Eigenschaftsnamen in Validierungsfehlern

Wenn ein Validierungsfehler auftritt, erzeugt die Modellvalidierung standardmäßig ein ModelStateDictionary mit dem Eigenschaftsnamen als Fehlerschlüssel. Einige Apps, z. B. Single-Page-Apps, profitieren von der Verwendung von JSON-Eigenschaftsnamen für Validierungsfehler, die von Web-APIs generiert werden. Der folgende Code konfiguriert die Validierung für die Verwendung von SystemTextJsonValidationMetadataProvider für JSON-Eigenschaftsnamen:

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

Der folgende Code konfiguriert die Validierung für die Verwendung von NewtonsoftJsonValidationMetadataProvider für JSON-Eigenschaftsnamen beim Verwenden von 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();

Weitere Informationen finden Sie unter Verwenden von JSON-Eigenschaftsnamen bei Validierungsfehlern.

Minimale APIs

Filter in Minimal-API-Apps

Minimal-API-Filter ermöglichen Entwicklern die Implementierung von Geschäftslogik, die Folgendes unterstützt:

  • Ausführen von Code vor und nach dem Routenhandler.
  • Überprüfen und Ändern von Parametern, die während eines Aufrufs eines Routenhandlers bereitgestellt werden.
  • Abfangen des Antwortverhaltens eines Routenhandlers.

Filter können in den folgenden Szenarien hilfreich sein:

  • Überprüfen der Anforderungsparameter und des Texts, die an einen Endpunkt gesendet werden.
  • Protokollierung von Informationen über die Anforderung und Antwort.
  • Überprüfen, ob eine Anforderung auf eine unterstützte API-Version ausgelegt ist.

Weitere Informationen finden Sie unter Filter in Minimal-API-Apps.

Binden von Arrays und Zeichenfolgenwerten aus Headern und Abfragezeichenfolgen

In ASP.NET 7 wird die Bindung von Abfragezeichenfolgen an ein Array von primitiven Typen, Zeichenfolgenarrays und StringValues unterstützt:

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

Die Bindung von Abfragezeichenfolgen oder Headerwerten an ein Array komplexer Typen wird unterstützt, wenn im Typ TryParse implementiert ist. Weitere Informationen finden Sie unter Binden von Arrays und Zeichenfolgenwerten aus Headern und Abfragezeichenfolgen.

Weitere Informationen finden Sie unter Hinzufügen einer Endpunktzusammenfassung oder -beschreibung.

Binden des Anforderungstexts als Stream oder PipeReader

Der Anforderungstext kann als Stream oder PipeReader gebunden werden, um effizient Szenarien zu unterstützen, in denen der Benutzer Daten verarbeiten und Folgendes tun muss:

  • Daten im Blobspeicher speichern oder Daten in die Warteschlange eines Warteschlangenanbieters einreihen.
  • Die gespeicherten Daten mit einem Workerprozess oder einer Cloudfunktion verarbeiten.

Beispielsweise werden die Daten möglicherweise in Azure Queue Storage eingereiht oder in Azure Blob Storage gespeichert.

Weitere Informationen finden Sie unter Binden des Anforderungstexts als Stream oder PipeReader.

Neue Results.Stream-Überladungen

Wir haben neue Results.Stream-Überladungen eingeführt, um Szenarien zu berücksichtigen, die Zugriff auf den zugrunde liegenden HTTP-Antwortdatenstrom benötigen, ohne puffern zu müssen. Diese Überladungen verbessern auch Fälle, in denen eine API Daten an den HTTP-Antwortdatenstrom streamt, wie von Azure Blob Storage. Im folgenden Beispiel wird ImageSharp verwendet, um eine reduzierte Größe des angegebenen Bilds zurückzugeben:

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

Weitere Informationen finden Sie unter Streambeispiele.

Typisierte Ergebnisse für minimale APIs

Die IResult-Schnittstelle wurde in .NET 6 eingeführt, um von minimalen APIs zurückgegebene Werte darzustellen, die nicht die implizite Unterstützung für die JSON-Serialisierung des zurückgegebenen Objekts in der HTTP-Antwort verwenden. Die statische Results-Klasse wird verwendet, um unterschiedliche IResult-Objekte zu erstellen, die verschiedene Arten von Antworten darstellen. Beispiel: Festlegen des Antwortstatuscodes oder Umleitung an eine andere URL. Die von diesen Methoden zurückgegebenen IResult-Implementierungsframeworktypen waren jedoch intern, was die Überprüfung des spezifischen IResult-Typs erschwert, der von Methoden in einem Komponententest zurückgegeben wird.

Die IResult implementierenden Typen in .NET 7 sind öffentlich, sodass Typassertionen beim Testen zugelassen werden. Zum Beispiel:

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

Verbesserte Komponententestbarkeit für minimale Routenhandler

IResult-Implementierungstypen sind jetzt im Microsoft.AspNetCore.Http.HttpResults-Namespace öffentlich verfügbar. Die IResult-Implementierungstypen können verwendet werden, um Komponententests für minimale Routenhandler auszuführen, wenn anstelle von Lambdafunktionen benannte Methoden verwendet werden.

Im folgenden Code wird die Ok<TValue>-Klasse verwendet:

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

Weitere Informationen finden Sie unter IResult-Implementierungstypen.

Neue HttpResult-Schnittstellen

Die folgenden Schnittstellen im Microsoft.AspNetCore.Http-Namespace bieten eine Möglichkeit, den IResult-Typ zur Laufzeit zu erkennen. Dies ist ein häufiges Muster in Filterimplementierungen:

Weitere Informationen finden Sie unter IHttpResult-Schnittstellen.

OpenAPI-Verbesserungen für minimale APIs

Microsoft.AspNetCore.OpenApi NuGet-Paket

Das Microsoft.AspNetCore.OpenApi-Paket ermöglicht Interaktionen mit OpenAPI-Spezifikationen für Endpunkte. Das Paket verhält sich wie eine Verknüpfung zwischen den OpenAPI-Modellen, die im Microsoft.AspNetCore.OpenApi Paket definiert sind, und den Endpunkten, die in minimalen APIs definiert sind. Das Paket stellt eine API bereit, welche die Parameter, Antworten und Metadaten eines Endpunkts untersucht, um einen OpenAPI-Anmerkungstyp zu erstellen, der zum Beschreiben eines Endpunkts verwendet wird.

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

WithOpenApi mit Parametern aufrufen.

Die WithOpenApi Methode akzeptiert eine Funktion, die benutzt werden kann, um die OpenAPI-Anmerkung zu verändern. Im folgenden Code wird beispielsweise eine Beschreibung zum ersten Parameter des Endpunkts hinzugefügt:

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

Bereitstellen von Endpunktbeschreibungen und -zusammenfassungen

Minimale APIs unterstützen jetzt die Kommentierung von Vorgängen mit Beschreibungen und Zusammenfassungen für die OpenAPI-Spezifikationsgenerierung. Sie können die Erweiterungsmethoden WithDescription und WithSummary oder die Attribute [EndpointDescription] und [EndpointSummary] aufrufen.

Weitere Informationen finden Sie unter OpenAPI in Minimal-API-Apps.

Dateiuploads mit IFormFile und IFormFileCollection

Minimale APIs unterstützen jetzt den Dateiupload mit IFormFile und IFormFileCollection. Der folgende Code verwendet IFormFile und IFormFileCollection zum Hochladen der Datei:

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

Authentifizierte Dateiuploadanforderungen werden mithilfe eines Autorisierungsheaders, eines Clientzertifikats oder eines cookie-Headers unterstützt.

Es gibt keine integrierte Unterstützung für Anti-Forgery-Systeme. Die Implementierung ist jedoch mit dem IAntiforgery-Dienst möglich.

Das [AsParameters]-Attribut ermöglicht Parameterbindung für Argumentlisten.

Das [AsParameters]-Attribut ermöglicht eine Parameterbindung für Argumentlisten. Weitere Informationen finden Sie unter Parameterbindung für Argumentlisten mit [AsParameters].

Minimale APIs und API-Controller

Neuer Dienst für Problemdetails

Der Dienst für Problemdetails implementiert die Schnittstelle IProblemDetailsService, die das Erstellen von Problemdetails für HTTP-APIs unterstützt.

Weitere Informationen finden Sie unter Dienst für Problemdetails.

Routengruppen

Die MapGroup-Erweiterungsmethode hilft, Gruppen von Endpunkten mit einem gemeinsamen Präfix zu organisieren. Sie reduziert sich wiederholenden Code und ermöglicht die benutzerdefinierte Anpassung ganzer Gruppen von Endpunkten mit einem einzigen Aufruf von Methoden wie RequireAuthorization und WithMetadata,die Endpunktmetadaten hinzufügen.

Der folgende Code erstellt beispielsweise zwei ähnliche Endpunktgruppen:

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 diesem Szenario können Sie eine relative Adresse für den Location-Header im 201 Created-Ergebnis verwenden:

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

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

Die erste Gruppe von Endpunkten entspricht nur Anforderungen mit dem Präfix /public/todos und ist ohne Authentifizierung zugänglich. Die zweite Gruppe von Endpunkten entspricht nur Anforderungen mit dem Präfix /private/todos und erfordert Authentifizierung.

Die QueryPrivateTodos-Endpunktfilterfactory ist eine lokale Funktion, die die TodoDb-Parameter des Routenhandlers so ändert, dass Zugriff auf private Aufgabendaten zulässig ist und diese gespeichert werden können.

Routengruppen unterstützen auch geschachtelte Gruppen und komplexe Präfixmuster mit Routenparametern und -einschränkungen. Im folgenden Beispiel kann der der user-Gruppe zugeordnete Routenhandler die Routenparameter {org} und {group} erfassen, die in den Präfixen der äußeren Gruppe definiert sind.

Das Präfix kann auch leer sein. Dies kann hilfreich sein, um Endpunktmetadaten oder Filter einer Gruppe von Endpunkten hinzuzufügen, ohne das Routenmuster zu ändern.

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

Das Hinzufügen von Filtern oder Metadaten zu einer Gruppe verhält sich genauso wie das individuelle Hinzufügen zu jedem Endpunkt, bevor zusätzliche Filter oder Metadaten hinzugefügt werden, die einer inneren Gruppe oder einem bestimmten Endpunkt hinzugefügt wurden.

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

Im Beispiel oben protokolliert der äußere Filter die eingehende Anforderung vor dem inneren Filter, obwohl er als zweiter hinzugefügt wurde. Da die Filter auf verschiedene Gruppen angewendet wurden, spielt die Reihenfolge, in der sie relativ zueinander hinzugefügt wurden, keine Rolle. Die Reihenfolge, in der Filter hinzugefügt werden, spielt eine Rolle, wenn sie auf dieselbe Gruppe oder einen bestimmten Endpunkt angewendet werden.

Eine Anforderung an /outer/inner/ protokolliert Folgendes:

/outer group filter
/inner group filter
MapGet filter

gRPC

JSON-Transcodierung

gRPC JSON-Transcodierung ist eine Erweiterung für ASP.NET Core, die RESTful-JSON-APIs für gRPC-Dienste erstellt. gRPC JSON-Transcodierung ermöglicht:

  • Apps den Aufruf von gRPC-Diensten mit den bekannten HTTP-Konzepten
  • ASP.NET Core gRPC-Apps, gRPC- und RESTful-JSON-APIs ohne Replikationsfunktionen zu unterstützen.
  • Experimentelle Unterstützung für die Generierung von OpenAPI aus transcodierten RESTful-APIs durch Integration in Swashbuckle.

Weitere Informationen finden Sie unter gRPC JSON-Transcodierung in ASP.NET Core gRPC-Apps und Verwenden von OpenAPI mit ASP.NET Core-Apps zur gRPC JSON-Transcodierung.

gRPC-Integritätsprüfungen in ASP.NET Core

Das gRPC-Integritätsprüfungsprotokoll ist ein Standard zum Melden der Integrität von gRPC-Server-Apps. Eine App macht Integritätsprüfungen als gRPC-Dienst verfügbar. Sie werden normalerweise mit einem externen Überwachungsdienst verwendet, der den Status einer App überprüft.

gRPC in ASP.NET Core bietet mit dem Paket Grpc.AspNetCore.HealthChecks zusätzliche integrierte Unterstützung für gRPC-Integritätprüfungen. Ergebnisse von .NET-Integritätsprüfungen werden Aufrufern gemeldet.

Weitere Informationen finden Sie unter gRPC-Integritätsprüfungen in ASP.NET Core.

Verbesserte Unterstützung von Anrufanmeldeinformationen

Anrufanmeldeinformationen werden empfohlen, um einen gRPC-Client zum Senden eines Authentifizierungstokens an den Server zu konfigurieren. gRPC-Clients unterstützen zwei neue Features, um die Verwendung von Anrufanmeldeinformationen zu vereinfachen:

  • Unterstützung für Anrufanmeldeinformationen mit Klartextverbindungen. Zuvor hat ein gRPC-Aufruf nur Anrufanmeldeinformationen gesendet, wenn die Verbindung mit TLS gesichert wurde. Eine neue Einstellung in GrpcChannelOptions mit Namen UnsafeUseInsecureChannelCallCredentials ermöglicht das Anpassen dieses Verhaltens. Es hat Auswirkungen auf die Sicherheit, wenn keine Verbindung mit TLS gesichert wird.
  • Eine neue Methode namens AddCallCredentials ist mit der gRPC-Clientfactory verfügbar. AddCallCredentials ist eine schnelle Möglichkeit zum Konfigurieren von Anrufanmeldeinformationen für einen gRPC-Client und lässt sich gut in Abhängigkeitsinjektion (Dependency Injection, DI) integrieren.

Der folgende Code konfiguriert die gRPC-Clientfactory zum Senden von Authorization-Metadaten:

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

Weitere Informationen finden Sie unter Bearertoken mit gRPC-Clientfactory.

SignalR

Clientergebnisse

Der Server unterstützt jetzt das Anfordern eines Ergebnisses von einem Client. Dazu muss der Server ISingleClientProxy.InvokeAsync verwenden, und der Client muss ein Ergebnis aus seinem .On-Handler zurückzugeben. Stark typisierte Hubs können auch Werte aus Schnittstellenmethoden zurückgeben.

Weitere Informationen finden Sie unter Clientergebnisse.

Abhängigkeitsinjektion für SignalR-Hubmethoden

SignalR-Hubmethoden unterstützen ab sofort die Einbindung von Diensten per Abhängigkeitsinjektion (Dependency Injection, DI).

Hubkonstruktoren können Dienste der Abhängigkeitsinjektion als Parameter akzeptieren, die in Eigenschaften der Klasse zur Verwendung in einer Hubmethode gespeichert werden können. Weitere Informationen finden Sie unter Einfügen von Diensten in einen Hub.

Blazor

Behandeln von Standortänderungsereignissen und Navigationszustand

In .NET 7 unterstützt Blazor Standortänderungsereignisse und die Beibehaltung des Navigationszustands. Dadurch können Sie Benutzer*innen bei nicht gespeicherten Arbeiten warnen oder verwandte Aktionen ausführen, wenn die Benutzer*innen eine Seitennavigation ausführen.

Weitere Informationen finden Sie in den folgenden Abschnitten des Artikels Routing und Navigation:

Leere Blazor-Projektvorlagen

Blazor verfügt über zwei neue Projektvorlagen zum Starten von einer leeren Tafel. Die neuen Projektvorlagen Blazor Server App leer und Blazor WebAssembly App leer verhalten sich wie ihre nicht leeren Entsprechungen, enthalten aber keinen Beispielcode. Diese leeren Vorlagen enthalten nur eine einfache home-Seite. Außerdem wurde Bootstrap entfernt, damit Sie mit einem anderen CSS-Framework beginnen können.

Weitere Informationen finden Sie in den folgenden Artikeln:

Benutzerdefinierte Blazor-Elemente

Das Microsoft.AspNetCore.Components.CustomElements-Paket ermöglicht das Erstellen von standardbasierten, benutzerdefinierten DOM-Elementen mithilfe von Blazor.

Weitere Informationen finden Sie unter Razor-Komponenten in ASP.NET Core.

Binden von Modifizierern (@bind:after, @bind:get, @bind:set)

Wichtig

Die Features @bind:after/@bind:get/@bind:set erhalten derzeit weitere Updates. Um die neuesten Updates zu nutzen, vergewissern Sie sich, dass Sie das neueste SDK installiert haben.

Die Verwendung eines Ereignisrückrufparameters ([Parameter] public EventCallback<string> ValueChanged { get; set; }) wird nicht unterstützt. Übergeben Sie stattdessen eine Action-returning- oder Task-returning-Methode an @bind:set/@bind:after.

Weitere Informationen finden Sie in den folgenden Ressourcen:

In .NET 7 können Sie asynchrone Logik ausführen, nachdem ein Bindungsereignis mit dem neuen Modifizierer @bind:after abgeschlossen wurde. Im folgenden Beispiel wird die asynchrone PerformSearch-Methode automatisch ausgeführt, nachdem Änderungen an dem Suchtext erkannt wurden:

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

@code {
    private string searchText;

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

In .NET 7 ist es auch einfacher, Bindungen für Komponentenparameter einzurichten. Komponenten können die Zwei-Wege-Datenbindung durch Definieren eines Parameterpaars unterstützen:

  • @bind:get gibt den Wert an, der gebunden werden soll.
  • @bind:set gibt einen Rückruf zum Zeitpunkt einer Änderung des Werts an.

Die Modifizierer @bind:get und @bind:set werden immer zusammen verwendet.

Beispiele:

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

Weitere Informationen zur InputText-Komponente finden Sie unter ASP.NET Core Blazor-Eingabekomponenten.

Verbesserungen beim Hot Reload

In .NET 7 umfasst die Hot Reload-Unterstützung Folgendes:

  • Komponenten können ihre Parameter auf ihre Standardwerte zurücksetzen, wenn ein Wert entfernt wird.
  • Blazor WebAssembly:
    • Es wurden neue Typen hinzugefügt.
    • Es wurden geschachtelte Klassen hinzugefügt.
    • Vorhandenen Typen wurden statische und Instanzmethoden hinzugefügt.
    • Vorhandenen Typen wurden statische Felder und Methoden hinzugefügt.
    • Vorhandenen Methoden wurden statische Lambdafunktionen hinzugefügt.
    • Vorhandenen Methoden, die bereits zuvor this erfasst haben, wurden Lambdafunktionen hinzugefügt, die this erfassen.

Dynamische Authentifizierungsanforderungen mit MSAL in Blazor WebAssembly

Als Neuerung in .NET 7 unterstützt Blazor WebAssembly jetzt das Erstellen dynamischer Authentifizierungsanforderungen zur Laufzeit mit benutzerdefinierten Parametern, die auch komplexere Authentifizierungsszenarien ermöglichen.

Weitere Informationen finden Sie in den folgenden Artikeln:

Blazor WebAssembly: Verbesserungen beim Debuggen

Folgende Verbesserungen wurden beim Blazor WebAssembly-Debuggen vorgenommen:

  • Unterstützung für die Einstellung Nur eigenen Code, um Typmember anzuzeigen oder auszublenden, die nicht aus dem Benutzercode stammen
  • Unterstützung für die Überprüfung mehrdimensionaler Arrays
  • Die Aufrufliste zeigt nun den richtigen Namen für asynchrone Methoden an.
  • Verbesserte Ausdrucksauswertung
  • Richtige Behandlung des Schlüsselworts new bei abgeleiteten Membern
  • Unterstützung für debuggerbezogene Attribute in System.Diagnostics

System.Security.Cryptography-Unterstützung in WebAssembly

.NET 6 unterstützte die SHA-Hashalgorithmen bei der Ausführung in WebAssembly. .NET 7 ermöglicht mehr kryptografische Algorithmen durch die Verwendung von SubtleCrypto (sofern möglich) und einen Fallback auf eine .NET-Implementierung, wenn SubtleCrypto nicht verwendet werden kann. Die folgenden Algorithmen werden für WebAssembly in .NET 7 unterstützt:

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

Weitere Informationen finden Sie unter Developers targeting browser-wasm can use Web Crypto APIs (dotnet/runtime #40074) (Verwenden von Web Crypto-APIs (dotnet/runtime #40074) bei der Entwicklung für browser-wasm).

Injizieren von Diensten in benutzerdefinierte Validierungsattribute

Sie können nun Dienste in benutzerdefinierte Validierungsattribute injizieren. Blazor richtet den ValidationContext so ein, dass er als Dienstanbieter verwendet werden kann.

Weitere Informationen finden Sie unter ASP.NET Core Blazor Formularvalidierung.

Input*-Komponenten außerhalb eines EditContext/EditForm

Die integrierten Eingabekomponenten werden nun außerhalb eines Formulars im Markup der Razor-Komponente unterstützt.

Weitere Informationen finden Sie unter ASP.NET Core Blazor Eingabekomponenten.

Projektvorlagenänderungen

Bei Veröffentlichung von .NET 6 im letzten Jahr wurde das HTML-Markup der _Host-Seite (Pages/_Host.chstml) auf die _Host-Seite und eine neue _Layout-Seite (Pages/_Layout.chstml) in der Blazor Server-Projektvorlage von .NET 6 aufgeteilt.

In .NET 7 wurde das HTML-Markup wieder mit der _Host-Seite in Projektvorlagen zusammengefasst.

Es wurden mehrere weitere Änderungen an den Blazor-Projektvorlagen vorgenommen. Es ist nicht möglich, sämtliche Änderungen an den Vorlagen in der Dokumentation aufzulisten. Informationen zum Migrieren einer App zu .NET 7, um alle Änderungen zu übernehmen, finden Sie unter Migrieren von ASP.NET Core 6.0 zu 7.0.

Experimentelle QuickGrid-Komponente

Die neue QuickGrid-Komponente bietet eine bequeme Datenrasterkomponente für die häufigsten Anforderungen und dient als Referenzarchitektur und Leistungsbaseline für alle, die Blazor-Datenrasterkomponenten erstellen.

Weitere Informationen finden Sie unter ASP.NET Core Blazor QuickGrid-Komponente.

Livedemo: QuickGrid für Blazor-Beispiel-App

Verbesserungen bei der Virtualisierung

Verbesserungen bei der Virtualisierung in .NET 7:

  • Die Virtualize-Komponente unterstützt die Verwendung des eigentlichen Dokuments als Scrollstamm (alternativ zur Verwendung eines anderen Elements mit overflow-y: scroll).
  • Wenn die Virtualize-Komponente innerhalb eines Elements platziert wird, das einen bestimmten untergeordneten Tagnamen erfordert, ermöglicht SpacerElement das Abrufen oder Festlegen des Tagnamens für den Virtualisierungsabstandhalter.

Weitere Informationen finden Sie in den folgenden Abschnitten des Artikels Virtualisierung:

MouseEventArgs-Updates

MovementX und MovementY wurden MouseEventArgs hinzugefügt.

Weitere Informationen finden Sie unter Ereignisbehandlung in Blazor in ASP.NET Core.

Neue Blazor-Ladeseite

Die Blazor WebAssembly-Projektvorlage verfügt über eine neue Ladebenutzeroberfläche, die den Status des Ladenvorgangs der App anzeigt.

Weitere Informationen finden Sie unter Starten von ASP.NET CoreBlazor.

Verbesserte Diagnose für die Authentifizierung bei Blazor WebAssembly

Für die Diagnose von Authentifizierungsproblemen in Blazor WebAssembly-Apps ist eine detaillierte Protokollierung verfügbar.

Weitere Informationen finden Sie unter ASP.NET Core Blazor-Protokollierung.

JavaScript-Interoperabilität in WebAssembly

JavaScript [JSImport]/[JSExport]-Interop-API ist ein neuer Mechanismus auf niedriger Ebene für die Verwendung von .NET in Blazor WebAssembly und JavaScript-basierten Aps. Mit dieser neuen JavaScript-Interoperabilitätsfunktion können Sie mithilfe der .NET WebAssembly-Laufzeit .NET-Code über JavaScript aufrufen und JavaScript-Funktionalität über .NET aufrufen, ohne vom Blazor-UI-Komponentenmodell abhängig zu sein.

Weitere Informationen finden Sie unter:

Bedingte Registrierung des Authentifizierungszustandsanbieters

Vor der Veröffentlichung von .NET 7 wurde AuthenticationStateProvider im Dienstcontainer mit AddScoped registriert. Dadurch war es schwierig, Apps zu debuggen, da beim Bereitstellen einer benutzerdefinierten Implementierung eine bestimmte Reihenfolge von Dienstregistrierungen erzwungen wurde. Aufgrund von internen Frameworkänderungen im Lauf der Zeit ist es nicht mehr erforderlich AuthenticationStateProvider bei AddScoped zu registrieren.

Nehmen Sie im Entwicklercode die folgende Änderung an der Dienstregistrierung des Authentifizierungszustandsanbieters vor:

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

Im vorherigen Beispiel ist ExternalAuthStateProvider die Dienstimplementierung für die Entwicklung.

Verbesserungen an den .NET-WebAssembly-Buildtools

Die folgenden neuen Features in der wasm-tools-Workload für .NET 7 dienen zur Leistungsverbesserung und zur Behandlung von Ausnahmen:

Weitere Informationen finden Sie unter ASP.NET Core Blazor WebAssembly-Buildtools und AOT-Kompilierung (Ahead-of-Time).

Blazor Hybrid

Externe URLs

Es wurde eine Option hinzugefügt, die das Öffnen externer Webseiten im Browser erlaubt.

Weitere Informationen finden Sie unter ASP.NET Core: Routing und Navigation in Blazor Hybrid.

Sicherheit

Es ist ein neuer Leitfaden für Blazor Hybrid-Sicherheitsszenarien verfügbar. Weitere Informationen finden Sie in den folgenden Artikeln:

Leistung

Middleware für die Ausgabezwischenspeicherung

Die Ausgabezwischenspeicherung ist eine neue Middleware, die Antworten aus einer Web-App speichert und von einem Cache aus bereitstellt, anstatt sie jedes Mal zu berechnen. Die Ausgabezwischenspeicherung unterscheidet sich auf folgende Weise vom Zwischenspeichern von Antworten:

  • Das Zwischenspeicherungsverhalten kann auf dem Server konfiguriert werden.
  • Cacheeinträge können programmgesteuert für ungültig erklärt werden.
  • Die Ressourcensperrung verringert das Risiko von Cache Stampede und Thundering Herd Problem.
  • Eine erneute Cacheüberprüfung bedeutet, dass der Server anstelle eines zwischengespeicherten Antworttexts einen 304 Not Modified-HTTP-Statuscode zurückgeben kann.
  • Das Cachespeichermedium ist erweiterbar.

Weitere Informationen finden Sie unter Übersicht über die Zwischenspeicherung in ASP.NET Core und Middleware für die Ausgabezwischenspeicherung.

HTTP/3-Verbesserungen

In diesem Release:

  • HTTP/3 wird vollständig von ASP.NET Core unterstützt und ist nicht mehr experimentell.
  • Verbesserung der Kestrel-Unterstützung für HTTP/3. Die beiden Hauptbereiche der Verbesserung sind Featureparität mit HTTP/1.1 und HTTP/2 sowie die Leistung.
  • Vollständige Unterstützung für UseHttps(ListenOptions, X509Certificate2) mit HTTP/3. Kestrel bietet erweiterte Optionen zum Konfigurieren von Verbindungszertifikaten, z. B. das Einbinden in die Servernamensanzeige (Server Name Indication, SNI).
  • Unterstützung für HTTP/3 in HTTP.sys und IIS.

Im folgenden Beispiel wird gezeigt, wie Sie einen SNI-Rückruf verwenden, um TLS-Optionen aufzulösen:

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

In .NET 7 wurden erhebliche Anstrengungen unternommen, um die HTTP/3-Zuordnungen zu reduzieren. Einige dieser Verbesserungen finden Sie in den folgenden GitHub-PRs:

HTTP/2-Leistungsverbesserungen

In .NET 7 wird eine grundlegende Umstrukturierung der Verarbeitung von HTTP/2-Anforderungen durch Kestrel eingeführt. ASP.NET Core-Apps mit stark ausgelasteten HTTP/2-Verbindungen profitieren von einer geringeren CPU-Auslastung und einem höheren Durchsatz.

Zuvor beruhte die HTTP/2-Multiplexing-Implementierung auf einer Sperre, mit deren Hilfe gesteuert wurde, welche Anforderung die zugrunde liegende TCP-Verbindung für Schreibvorgänge nutzen kann. Die Schreibsperre wird durch eine threadsichere Warteschlange ersetzt. Statt darum zu konkurrieren, welcher Thread die Schreibsperre verwenden darf, werden die Anforderungen nun in eine Warteschlange eingereiht und von einem dedizierten Consumer verarbeitet. Zuvor verschwendete CPU-Ressourcen stehen dem rest der App zur Verfügung.

Diese Verbesserungen machen sich unter anderem in gRPC bemerkbar, einem beliebten RPC-Framework, das HTTP/2 verwendet. Kestrel- und gRPC-Benchmarks zeigen eine deutliche Verbesserung:

Streamingleistung des gRPC-Servers

Änderungen wurden am Code zum Schreiben von HTTP/2-Frames vorgenommen, um die Leistung zu verbessern, wenn mehrere Datenströme versuchen, Daten in einer einzelnen HTTP/2-Verbindung zu schreiben. TLS-Arbeit wird nun an den Threadpool gesendet, und eine Schreibsperre wird schneller veröffentlicht, die von anderen Datenströmen zum Schreiben ihrer Daten verwendet werden können. Die Reduzierung der Wartezeiten kann zu erheblichen Leistungsverbesserungen in den Fällen führen, in denen Konflikte für diese Schreibsperre bestehen. Eine gRPC-Benchmark mit 70 Datenströmen für eine einzelne Verbindung (mit TLS) zeigte eine Verbesserung von etwa 15 % bei Anforderungen pro Sekunde (RPS) mit dieser Änderung.

HTTP/2-Unterstützung für WebSocket

.NET 7 hat WebSockets über die HTTP/2-Unterstützung für Kestrel, den SignalR-JavaScript-Client und SignalR mit Blazor WebAssembly eingeführt.

Wenn Sie WebSocket über HTTP/2 verwenden, können Sie die folgenden neuen Features nutzen:

  • Headerkomprimierung
  • Multiplexing, was die Zeit und Ressourcen reduziert, die beim Erstellen mehrerer Anforderungen an den Server erforderlich sind

Diese unterstützten Features sind in Kestrel für alle aktivierten HTTP/2-Plattformen verfügbar. Die Versionsaushandlung findet in Browsern und in Kestrel automatisch statt, sodass keine neuen APIs benötigt werden.

Weitere Informationen finden Sie unter Http/2 WebSockets-Unterstützung.

Kestrel-Leistungsverbesserungen auf High-Core-Computern

Kestrel verwendet ConcurrentQueue<T> für viele Zwecke. Ein Zweck ist die Planung von E/A-Vorgängen im Standardsockettransport von Kestrel. Durch die Partitionierung von ConcurrentQueue auf der Grundlage des zugeordneten Sockets wird der Inhalt reduziert und der Durchsatz auf Computern mit vielen CPU-Kernen erhöht.

Die Profilerstellung auf High-Core-Computern mit .NET 6 führte in einer der anderen ConcurrentQueue-Instanzen von Kestrel zu erheblichen Konflikten, nämlich in der PinnedMemoryPool-Instanz, die Kestrel zum Zwischenspeichern von Bytepuffern verwendet.

In .NET 7 wird der Arbeitsspeicherpool von Kestrel auf die gleiche Weise wie die E/A-Warteschlange partitioniert. Dadurch verzeichnen High-Core-Computer weniger Konflikte und einen höheren Durchsatz. Auf ARM64-VMs mit 80 Kernen konnte eine Steigerung von über 500 % bei den Antworten pro Sekunde (Responses per Second, RPS) in der Klartextbenchmark von TechEmpower beobachtet werden. Auf AMD-VMs mit 48 Kernen beträgt die Steigerung im HTTPS-JSON-Benchmark nahezu 100 %.

ServerReady Ereignis zum Messen der Startzeit

Apps, die EventSource verwenden, können die Startzeit messen, um die Startleistung zu verstehen und zu optimieren. Das neue ServerReady Ereignis in Microsoft.AspNetCore.Hosting stellt den Punkt dar, an dem der Server bereit ist, auf Anforderungen zu reagieren.

Server

Neues ServerReady-Ereignis zum Messen der Startzeit

Zur Messung der Startzeit von ASP.NET Core-Apps wurde das Ereignis ServerReady hinzugefügt.

IIS

Schattenkopien in IIS

Schattenkopieren von App-Assemblys in das ASP.NET Core-Modul (ANCM) für IIS kann eine bessere Endbenutzerfreundlichkeit bieten als das Beenden der App durch Bereitstellen einer App-Offlinedatei.

Weitere Informationen finden Sie unter Erstellen von Schattenkopien in IIS.

Sonstiges

Kestrel: Verbesserungen für die vollständige Zertifikatkette

HttpsConnectionAdapterOptions hat eine neue ServerCertificateChain-Eigenschaft vom Typ X509Certificate2Collection, die die Überprüfung von Zertifikatketten vereinfacht, indem eine vollständige Kette, einschließlich Zwischenzertifikate, angegeben werden kann. Weitere Informationen finden Sie unter dotnet/aspnetcore#21513.

dotnet watch

Verbesserte Konsolenausgabe für dotnet watch

Die Konsolenausgabe von dotnet watch wurde verbessert, um sie besser an der ASP.NET Core-Protokollierung auszurichten und mit 😮Emojis😍 hervorzuheben.

Hier sehen Sie ein Beispiel dafür, wie die neue Ausgabe aussieht:

Ausgabe für dotnet watch

Weitere Informationen finden Sie in diesem Pull Request in GitHub.

Konfigurieren von dotnet watch, sodass für grobe Bearbeitungen immer ein Neustart durchgeführt wird

Grobe Bearbeitungen sind Bearbeitungen, für die kein Hot Reload durchgeführt werden kann. Um dotnet watch so zu konfigurieren, dass Neustarts stets ohne Aufforderung für grobe Bearbeitungen erfolgen, legen Sie die DOTNET_WATCH_RESTART_ON_RUDE_EDIT-Umgebungsvariable auf true fest.

Seite mit Ausnahmen für Entwickler – dunkler Modus

Dank eines Beitrags von Patrick Westerhoff wurde der Ausnahmeseite für Entwickler Unterstützung für den dunklen Modus hinzugefügt. Um den dunklen Modus in einem Browser zu testen, legen Sie auf der Seite mit den Entwicklertools den dunklen Modus fest. Beispielsweise in Firefox:

F12-Tools: dunkler Modus in Firefox

In Chrome:

F12-Tools: dunkler Modus in Chrome

Projektvorlagenoption zur Verwendung der Methode „Program.Main“ anstelle von Anweisungen auf oberster Ebene

Die .NET 7-Vorlagen enthalten eine Option zum Vermeiden von -Anweisungen auf oberster Ebene und generieren die Methoden namespace und Main, die für eine Program-Klasse deklariert sind.

Verwenden Sie mit der .NET CLI die Option --use-program-main:

dotnet new web --use-program-main

Aktivieren Sie in Visual Studio bei der Projekterstellung das Kontrollkästchen Keine Anweisungen der obersten Ebene verwenden:

Kontrollkästchen

Aktualisierte Angular- und React-Vorlagen

Die Angular-Projektvorlage wurde auf Angular 14 aktualisiert. Die React-Projektvorlage wurde auf React 18.2 aktualisiert.

Verwalten von JSON-Webtoken in der Entwicklung mit dotnet-user-jwts

Das neue Befehlszeilentool dotnet user-jwts kann App-spezifische lokale JSON-Webtoken (JWTs) erstellen und verwalten. Weitere Informationen finden Sie unter Verwalten von JSON-Webtoken in der Entwicklung mit dotnet user-jwts.

Unterstützung für zusätzliche Anforderungsheader in W3CLogger

Sie können jetzt zusätzliche Anforderungsheader angeben, die bei der Verwendung von W3CLogger protokolliert werden sollen, indem Sie AdditionalRequestHeaders() in W3CLoggerOptions aufrufen:

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

Weitere Informationen finden Sie unter W3CLogger-Optionen.

Anforderungsdekomprimierung

Die neue Middleware zum Dekomprimieren von Anforderungen:

  • Ermöglicht API-Endpunkten die Annahme von Anforderungen mit komprimierten Inhalten.
  • Verwendet den Content-Encoding-HTTP-Header, um Anforderungen, die komprimierten Inhalt enthalten, automatisch zu identifizieren und zu dekomprimieren.
  • Damit ist es nicht mehr notwendig, Code zum Behandeln komprimierter Anforderungen zu schreiben.

Weitere Informationen finden Sie unter Middleware zum Dekomprimieren von Anforderungen.