Compartir vía


Novedades de ASP.NET Core 10.0

En este artículo se resaltan los cambios más significativos de ASP.NET Core 10.0 con vínculos a la documentación pertinente.

Este artículo se actualizará a medida que se publiquen nuevas versiones preliminares. Consulte la página de anuncio de Asp.Net Core hasta que se actualice esta página.

Blazor

En esta sección se describen las nuevas características de Blazor.

parámetro QuickGridRowClass

Aplique una clase de hoja de estilos a una fila de la cuadrícula basada en el elemento de fila mediante el nuevo parámetro RowClass. En el ejemplo siguiente, se llama al método GetRowCssClass en cada fila para aplicar condicionalmente una clase de hoja de estilos basada en el elemento de fila:

<QuickGrid ... RowClass="GetRowCssClass">
    ...
</QuickGrid>

@code {
    private string GetRowCssClass(MyGridItem item) =>
        item.IsArchived ? "row-archived" : null;
}

Para obtener más información, vea ASP.NET Core Blazor `QuickGrid` componente.

Blazor script como recurso web estático

En versiones anteriores de .NET, el script de Blazor se sirve desde un recurso incrustado en el marco compartido de ASP.NET Core. En .NET 10 o posterior, el script de Blazor se sirve como un recurso web estático con compresión automática y huella digital.

Para obtener más información, consulte los siguientes recursos:

Resaltados de la plantilla de ruta

El atributo [Route] ahora admite el resaltado de sintaxis de ruta para ayudar a visualizar la estructura de la plantilla de ruta:

El patrón de plantilla de ruta de un atributo de ruta para el valor de contador muestra el resaltado de sintaxis

Anteriormente, NavigationManager.NavigateTo se desplazaba a la parte superior de la página para las navegaciones de la misma página. Este comportamiento se ha cambiado en .NET 10 para que el explorador ya no se desplácese hasta la parte superior de la página al navegar a la misma página. Esto significa que el viewport ya no se restablece al hacer actualizaciones en la dirección de la página actual, como cambiar la cadena de búsqueda o el fragmento.

Componente de interfaz de usuario de reconexión agregado a la plantilla de proyecto de Blazor Web App

La plantilla de proyecto de Blazor Web App ahora incluye un componente de ReconnectModal, incluida la hoja de estilos intercalada y los archivos JavaScript, para mejorar el control del desarrollador sobre la interfaz de usuario de reconexión cuando el cliente pierde la conexión de WebSocket al servidor. El componente no inserta estilos mediante programación, lo que garantiza el cumplimiento de la configuración más estricta de la política de seguridad de contenido (CSP) para la política style-src. En versiones anteriores, el marco creó la interfaz de usuario de reconexión predeterminada de una manera que podría provocar infracciones de CSP. Tenga en cuenta que la interfaz de usuario de reconexión predeterminada todavía se usa como reserva cuando la aplicación no define la interfaz de usuario de reconexión, como mediante el componente ReconnectModal de la plantilla de proyecto o un componente personalizado similar.

Nuevas características de la interfaz de usuario de reconexión:

  • Aparte de indicar el estado de reconexión estableciendo una clase CSS específica en el elemento de interfaz de usuario de reconexión, el nuevo evento components-reconnect-state-changed se envía para los cambios de estado de reconexión.
  • El código puede diferenciar mejor las fases del proceso de reconexión con el nuevo estado de reconexión "retrying", indicado por la clase CSS y el nuevo evento.

Para obtener más información, vea las Instrucciones de ASP.NET Core BlazorSignalR.

Omitir la cadena de consulta y el fragmento al usar NavLinkMatch.All

El componente NavLink ahora omite la cadena de consulta y el fragmento al usar el valor de NavLinkMatch.All para el parámetro Match. Esto significa que el vínculo conserva la clase active si la ruta de acceso de la URL coincide, pero la cadena de consulta o el fragmento cambian. Para revertir al comportamiento original, use el Microsoft.AspNetCore.Components.Routing.NavLink.EnableMatchAllForQueryStringAndFragmentAppContext interruptor establecido en true.

También puede invalidar el método ShouldMatch en NavLink para personalizar el comportamiento coincidente:

public class CustomNavLink : NavLink
{
    protected override bool ShouldMatch(string currentUriAbsolute)
    {
        // Custom matching logic
    }
}

Para más información, vea Enrutamiento y navegación de Blazor de ASP.NET Core.

Cerrar las opciones de columna de QuickGrid

Ahora puede cerrar la interfaz de opciones de columna de QuickGrid utilizando el nuevo método CloseColumnOptionsAsync.

En el ejemplo siguiente se usa el método CloseColumnOptionsAsync para cerrar la interfaz de usuario de opciones de columna en cuanto se aplica el filtro de título:

<QuickGrid @ref="movieGrid" Items="movies">
    <PropertyColumn Property="@(m => m.Title)" Title="Title">
        <ColumnOptions>
            <input type="search" @bind="titleFilter" placeholder="Filter by title" 
                @bind:after="@(() => movieGrid.CloseColumnOptionsAsync())" />
        </ColumnOptions>
    </PropertyColumn>
    <PropertyColumn Property="@(m => m.Genre)" Title="Genre" />
    <PropertyColumn Property="@(m => m.ReleaseYear)" Title="Release Year" />
</QuickGrid>

@code {
    private QuickGrid<Movie>? movieGrid;
    private string titleFilter = string.Empty;
    private IQueryable<Movie> movies = new List<Movie> { ... }.AsQueryable();
    private IQueryable<Movie> filteredMovies => 
        movies.Where(m => m.Title!.Contains(titleFilter));
}

El streaming de respuestas está sujeto a activación voluntaria y cómo desactivarlo

En versiones anteriores Blazor, el streaming de respuesta para HttpClient las solicitudes era opcional. Ahora, el streaming de respuesta está habilitado de forma predeterminada.

Se trata de un cambio importante porque llamar a HttpContent.ReadAsStreamAsync para un HttpResponseMessage.Content (response.Content.ReadAsStreamAsync()) devuelve un BrowserHttpReadStream y ya no un MemoryStream. BrowserHttpReadStream no admite operaciones sincrónicas, como Stream.Read(Span<Byte>). Si su código utiliza operaciones sincrónicas, puede optar por no participar en la transmisión de respuesta o copiar el Stream en el MemoryStream usted mismo.

Para no participar en el streaming de respuesta globalmente, establezca la DOTNET_WASM_ENABLE_STREAMING_RESPONSE variable de entorno en false o 0.

Para excluirse del streaming de respuesta para una solicitud individual, establezca SetBrowserResponseStreamingEnabled en false en HttpRequestMessage (requestMessage en el ejemplo siguiente):

requestMessage.SetBrowserResponseStreamingEnabled(false);

Para obtener más información, consulte HttpClient y HttpRequestMessage con las opciones de solicitud de la Fetch API (artículo Llamada a API web).

Huella digital del lado cliente

El año pasado, la versión de .NET 9 introdujo la huella digital del lado servidor de los recursos estáticos en Blazor Web App con la introducción de las convenciones de punto de conexión de enrutamiento de recursos estáticos de mapa (MapStaticAssets), el componente ImportMap y la propiedad ComponentBase.Assets(@Assets["..."]) para resolver módulos javaScript con huellas digitales. Para .NET 10, puede optar por la huella digital en el lado del cliente de los módulos de JavaScript para aplicaciones independientes Blazor WebAssembly.

En las aplicaciones independientes Blazor WebAssembly durante la compilación o publicación, el marco sobrescribe los marcadores de posición en index.html con valores calculados durante la compilación para generar una huella digital de los recursos estáticos. Se coloca una huella digital en el nombre del archivo del script blazor.webassembly.js.

Se deben realizar los siguientes cambios en el wwwwoot/index.html archivo para adoptar la característica de huella digital. La plantilla de proyecto independiente Blazor WebAssembly se actualizará para incluir estos cambios en una próxima versión preliminar:

<head>
    ...
+   <script type="importmap"></script>
</head>

<body>
    ...
-   <script src="_framework/blazor.webassembly.js"></script>
+   <script src="_framework/blazor.webassembly#[.{fingerprint}].js"></script>
</body>

</html>

En el archivo de proyecto (.csproj), agregue la <WriteImportMapToHtml> propiedad establecida en true:

<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">

  <PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
+   <WriteImportMapToHtml>true</WriteImportMapToHtml>
  </PropertyGroup>
</Project>

Para realizar huellas digitales de módulos adicionales JS en aplicaciones independientes Blazor WebAssembly , use la propiedad <StaticWebAssetFingerprintPattern> en el archivo de proyecto de la aplicación (.csproj).

En el ejemplo siguiente, se agrega una huella digital para todos los archivos proporcionados .mjs por el desarrollador en la aplicación:

<StaticWebAssetFingerprintPattern Include="JSModule" Pattern="*.mjs" 
  Expression="#[.{fingerprint}]!" />

Los archivos se colocan automáticamente en el mapa de importación:

  • Automáticamente para Blazor Web App CSR.
  • Al participar en la huella digital del módulo en aplicaciones independientes Blazor WebAssembly según las instrucciones anteriores.

Al resolver la importación para la interoperabilidad de JavaScript, el explorador usa el mapa de importación para resolver los archivos con huellas digitales.

Configura el entorno en las aplicaciones independientes Blazor WebAssembly

El Properties/launchSettings.json archivo ya no se usa para controlar el entorno en aplicaciones independientes Blazor WebAssembly .

A partir de .NET 10, establezca el entorno con la <WasmApplicationEnvironmentName> propiedad en el archivo de proyecto de la aplicación (.csproj).

En el ejemplo siguiente se establece el entorno de la aplicación en Staging:

<WasmApplicationEnvironmentName>Staging</WasmApplicationEnvironmentName>

Los entornos predeterminados son:

  • Development para compilación.
  • Production para publicar.

Cambio del nombre del archivo de configuración de arranque

El archivo de configuración de arranque cambia los nombres de blazor.boot.json a dotnet.boot.js. Este cambio de nombre solo afecta a los desarrolladores que interactúan directamente con el archivo, como cuando los desarrolladores son:

Modelo declarativo para conservar el estado de componentes y servicios

Ahora puede especificar de forma declarativa el estado para conservar desde componentes y servicios mediante el atributo [SupplyParameterFromPersistentComponentState]. Las propiedades con este atributo se conservan automáticamente mediante el servicio PersistentComponentState durante la representación previa. El estado se recupera cuando el componente se renderiza interactivamente o se instancia el servicio.

En versiones anteriores Blazor, el estado del componente persistente durante la representación previa mediante el servicio PersistentComponentState implicaba una cantidad significativa de código, como se muestra en el ejemplo siguiente:

@page "/movies"
@implements IDisposable
@inject IMovieService MovieService
@inject PersistentComponentState ApplicationState

@if (MoviesList == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <QuickGrid Items="MoviesList.AsQueryable()">
        ...
    </QuickGrid>
}

@code {
    public List<Movie>? MoviesList { get; set; }
    private PersistingComponentStateSubscription? persistingSubscription;

    protected override async Task OnInitializedAsync()
    {
        if (!ApplicationState.TryTakeFromJson<List<Movie>>(nameof(MoviesList), 
            out var movies))
        {
            MoviesList = await MovieService.GetMoviesAsync();
        }
        else
        {
            MoviesList = movies;
        }

        persistingSubscription = ApplicationState.RegisterOnPersisting(() =>
        {
            ApplicationState.PersistAsJson(nameof(MoviesList), MoviesList);
            return Task.CompletedTask;
        });
    }

    public void Dispose() => persistingSubscription?.Dispose();
}

Este código ahora se puede simplificar mediante el nuevo modelo declarativo:

@page "/movies"
@inject IMovieService MovieService

@if (MoviesList == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <QuickGrid Items="MoviesList.AsQueryable()">
        ...
    </QuickGrid>
}

@code {
    [SupplyParameterFromPersistentComponentState]
    public List<Movie>? MoviesList { get; set; }

    protected override async Task OnInitializedAsync()
    {
        MoviesList ??= await MovieService.GetMoviesAsync();
    }
}

Para obtener más información, consulta Representación previa de componentes Razor de ASP.NET Core . Las notas de implementación de API adicionales, que están sujetas a cambios en cualquier momento, están disponibles en [Blazor] Compatibilidad con el mantenimiento declarativo del estado de componentes y servicios (dotnet/aspnetcore #60634).

Blazor Hybrid

En esta sección se describen las nuevas características de Blazor Hybrid.

Nuevo .NET MAUIBlazor Hybrid con un artículo y un ejemplo de Blazor Web App y ASP.NET Core Identity

Se ha agregado un nuevo artículo y una aplicación de ejemplo para .NET MAUIBlazor Hybrid y aplicación web mediante ASP.NET Core Identity.

Para obtener más información, consulte los siguientes recursos:

SignalR

En esta sección se describen las nuevas características de SignalR.

API mínimas

En esta sección se describen las nuevas características de las API mínimas.

Tratar la cadena vacía en el envío del formulario como nula para los tipos de valor anulables

Cuando se usa el atributo [FromForm] con un objeto complejo en API mínimas, los valores de cadena vacíos de una publicación de formulario ahora se convierten en null en lugar de provocar un fallo de análisis. Este comportamiento coincide con la lógica de procesamiento de entradas de formulario que no están asociadas a objetos complejos en api mínimas.

using Microsoft.AspNetCore.Http;

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

app.MapPost("/todo", ([FromForm] Todo todo) => TypedResults.Ok(todo));

app.Run();

public class Todo
{
  public int Id { get; set; }
  public DateOnly? DueDate { get; set; } // Empty strings map to `null`
  public string Title { get; set; }
  public bool IsCompleted { get; set; }
}

Gracias a @nvmkpk por contribuir a este cambio!

Compatibilidad con la validación en las API mínimas

La compatibilidad con la validación en las API mínimas ya está disponible. Esta característica permite solicitar la validación de los datos enviados a los puntos de conexión de API. Habilitar la validación permite que el entorno de ejecución de ASP.NET Core realice las validaciones definidas en:

  • Consultar
  • Cabecera
  • Cuerpo de la solicitud

Las validaciones se definen mediante atributos en el espacio de nombres DataAnnotations. Los desarrolladores personalizan el comportamiento del sistema de validación mediante:

  • Creación de implementaciones de atributos personalizados [Validation] .
  • Implementando la interfaz IValidatableObject para la lógica compleja de validación.

Si se produce un error en la validación, el tiempo de ejecución devuelve una respuesta de solicitud incorrecta 400 con detalles de los errores de validación.

Habilitar el soporte de validación integrada para APIs mínimas

Habilite el soporte de validación integrado para las API mínimas llamando al método de extensión AddValidation para registrar los servicios necesarios en el contenedor de servicios para su aplicación.

builder.Services.AddValidation();

La implementación detecta automáticamente los tipos definidos en controladores de API mínimos o como tipos base de tipos definidos en controladores de API mínimos. Un filtro de punto de conexión realiza la validación en estos tipos y se agrega para cada punto de conexión.

La validación se puede deshabilitar para puntos de conexión específicos mediante el DisableValidation método de extensión , como en el ejemplo siguiente:

app.MapPost("/products",
    ([EvenNumber(ErrorMessage = "Product ID must be even")] int productId, [Required] string name)
        => TypedResults.Ok(productId))
    .DisableValidation();

Compatibilidad con eventos de Server-Sent (SSE)

ASP.NET Core ahora admite la devolución de un resultado ServerSentEvents mediante la API TypedResults.ServerSentEvents . Esta característica se admite tanto en las API mínimas como en las aplicaciones basadas en controladores.

Server-Sent Eventos es una tecnología de inserción de servidor que permite a un servidor enviar una secuencia de mensajes de eventos a un cliente a través de una única conexión HTTP. En .NET, los mensajes de evento se representan como SseItem<T> objetos, que pueden contener un tipo de evento, un identificador y una carga de datos de tipo T.

La clase TypedResults tiene un nuevo método estático denominado ServerSentEvents que se puede usar para devolver un ServerSentEvents resultado. El primer parámetro de este método es un IAsyncEnumerable<SseItem<T>> que representa la secuencia de mensajes de evento que se enviarán al cliente.

En el ejemplo siguiente se muestra cómo usar la TypedResults.ServerSentEvents API para devolver un flujo de eventos de frecuencia cardíaca como objetos JSON al cliente:

app.MapGet("/json-item", (CancellationToken cancellationToken) =>
{
    async IAsyncEnumerable<HeartRateRecord> GetHeartRate(
        [EnumeratorCancellation] CancellationToken cancellationToken)
    {
        while (!cancellationToken.IsCancellationRequested)
        {
            var heartRate = Random.Shared.Next(60, 100);
            yield return HeartRateRecord.Create(heartRate);
            await Task.Delay(2000, cancellationToken);
        }
    }

    return TypedResults.ServerSentEvents(GetHeartRate(cancellationToken),
                                                  eventType: "heartRate");
});

Para obtener más información, consulte:

OpenAPI

En esta sección se describen las nuevas características de OpenAPI.

Compatibilidad con OpenAPI 3.1

ASP.NET Core ha agregado compatibilidad para generar documentos de OpenAPI versión 3.1 en .NET 10. A pesar del aumento de la versión secundaria, OpenAPI 3.1 es una actualización significativa de la especificación de OpenAPI, en particular con compatibilidad completa con esquema JSON borrador 2020-12.

Algunos de los cambios que verá en el documento openAPI generado incluyen:

  • Los tipos anulables ya no tienen la propiedad nullable: true en el esquema.
  • En lugar de una propiedad nullable: true, tienen una palabra clave type cuyo valor es una matriz que incluye null como uno de los tipos.
  • Las propiedades o los parámetros definidos como C# int o long ahora aparecen en el documento OpenAPI generado sin el type: integer campo y tienen un pattern campo que limita el valor a dígitos. Esto sucede cuando la propiedad NumberHandling en JsonSerializerOptions está establecida en AllowReadingFromString, el valor predeterminado para aplicaciones web de ASP.NET Core. Para habilitar C# int y long para representarse en el documento OpenAPI como type: integer, establezca la propiedad NumberHandling a Strict.

Con esta característica, la versión predeterminada de OpenAPI para los documentos generados es3.1. La versión se puede cambiar estableciendo explícitamente la propiedad OpenApiVersion del OpenApiOptions en el parámetro delegado configureOptions de AddOpenApi.

builder.Services.AddOpenApi(options =>
{
    // Specify the OpenAPI version to use.
    options.OpenApiVersion = Microsoft.OpenApi.OpenApiSpecVersion.OpenApi3_0;
});

Al generar el documento de OpenAPI en tiempo de compilación, se puede seleccionar la versión de OpenAPI estableciendo el --openapi-version en el elemento de MSBuild de OpenApiGenerateDocumentsOptions.

    <!-- Configure build-time OpenAPI generation to produce an OpenAPI 3.0 document. -->
    <OpenApiGenerateDocumentsOptions>--openapi-version OpenApi3_0</OpenApiGenerateDocumentsOptions>

La compatibilidad con OpenAPI 3.1 se agregó principalmente en el siguiente PR.

Cambios importantes en OpenAPI 3.1

La compatibilidad con OpenAPI 3.1 requiere una actualización de la biblioteca de OpenAPI.NET subyacente a una nueva versión principal, 2.0. Esta nueva versión tiene algunos cambios importantes de la versión anterior. Los cambios disruptivos pueden afectar a las aplicaciones si tienen transformadores de documentos, operaciones o esquemas. Los cambios importantes en esta iteración incluyen lo siguiente:

  • Las entidades del documento openAPI, como las operaciones y los parámetros, se escriben como interfaces. Existen implementaciones concretas para las variantes insertadas y a las que se hace referencia de una entidad. Por ejemplo, un IOpenApiSchema puede ser un OpenApiSchema insertado o un OpenApiSchemaReference que apunte a un esquema definido en otro lugar del documento.
  • La propiedad Nullable se ha quitado del tipo OpenApiSchema. Para determinar si un tipo admite valores NULL, evalúe si la propiedad OpenApiSchema.Type establece JsonSchemaType.Null.

Uno de los cambios más significativos es que la clase OpenApiAny se ha quitado en favor de usar JsonNode directamente. Los transformadores que usan OpenApiAny deben actualizarse para usar JsonNode. La diferencia siguiente muestra los cambios en el transformador de esquema de .NET 9 a .NET 10:

options.AddSchemaTransformer((schema, context, cancellationToken) =>
{
    if (context.JsonTypeInfo.Type == typeof(WeatherForecast))
    {
-       schema.Example = new OpenApiObject
+       schema.Example = new JsonObject
        {
-           ["date"] = new OpenApiString(DateTime.Now.AddDays(1).ToString("yyyy-MM-dd")),
+           ["date"] = DateTime.Now.AddDays(1).ToString("yyyy-MM-dd"),
-           ["temperatureC"] = new OpenApiInteger(0),
+           ["temperatureC"] = 0,
-           ["temperatureF"] = new OpenApiInteger(32),
+           ["temperatureF"] = 32,
-           ["summary"] = new OpenApiString("Bracing"),
+           ["summary"] = "Bracing",
        };
    }
    return Task.CompletedTask;
});

Tenga en cuenta que estos cambios son necesarios incluso cuando solo se configura la versión de OpenAPI en 3.0.

OpenAPI en YAML

ASP.NET ahora admite el servicio del documento OpenAPI generado en formato YAML. YAML puede ser más conciso que JSON, lo que elimina llaves y comillas cuando se pueden deducir. YAML también admite cadenas de varias líneas, que pueden ser útiles para descripciones largas.

Para configurar una aplicación para que sirva el documento OpenAPI generado en formato YAML, especifique el punto de conexión en la llamada MapOpenApi con un sufijo ".yaml" o ".yml", como se muestra en el ejemplo siguiente:

app.MapOpenApi("/openapi/{documentName}.yaml");

Compatibilidad con:

  • YAML solo está disponible actualmente para OpenAPI servido desde el endpoint de OpenAPI.
  • La generación de documentos de OpenAPI en formato YAML en tiempo de compilación se agrega en una versión preliminar futura.

Consulte este PR que agregó soporte para mostrar el documento OpenAPI generado en formato YAML.

Descripción de la respuesta en ProduceResponseType para controladores de API

Los atributos ProducesAttribute, ProduceResponseTypeAttributey ProducesDefaultResponseType ahora aceptan un parámetro de cadena opcional, Description, que establecerá la descripción de la respuesta. Este es un ejemplo:

[HttpGet(Name = "GetWeatherForecast")]
[ProducesResponseType<IEnumerable<WeatherForecast>>(StatusCodes.Status200OK,
                   Description = "The weather forecast for the next 5 days.")]
public IEnumerable<WeatherForecast> Get()
{

Y el OpenAPI generado:

        "responses": {
          "200": {
            "description": "The weather forecast for the next 5 days.",
            "content": {

Actualmente, las API mínimas no admiten ProducesResponseType.

contribución comunitaria por Sander ten Brinke🙏

Poblar comentarios de documentos XML en un documento de OpenAPI

La generación de documentos OpenAPI de ASP.NET Core ahora incluirá los metadatos de los comentarios de documentación XML en las definiciones de métodos, clases y miembros dentro del documento OpenAPI. Debe habilitar los comentarios de documentos XML en el archivo de proyecto para usar esta característica. Para ello, agregue la siguiente propiedad al archivo del proyecto:

  <PropertyGroup>
    <GenerateDocumentationFile>true</GenerateDocumentationFile>
  </PropertyGroup>

En tiempo de compilación, el paquete OpenAPI aprovechará un generador de código fuente para detectar comentarios XML en el ensamblado de aplicación actual y cualquier referencia de proyecto y emitir código fuente para insertarlos en el documento a través de un transformador de documentos openAPI.

Tenga en cuenta que el proceso de compilación de C# no captura los comentarios de documentos XML colocados en expresiones lambda, por lo que para usar comentarios de documento XML para agregar metadatos a un punto de conexión de API mínimo, debe definir el controlador de puntos de conexión como un método, colocar los comentarios del documento XML en el método y, a continuación, hacer referencia a ese método desde el método MapXXX. Por ejemplo, para usar comentarios de documentos XML para agregar metadatos a un punto de conexión de API mínimo definido originalmente como una expresión lambda:

app.MapGet("/hello", (string name) =>$"Hello, {name}!");

Cambie la llamada MapGet para hacer referencia a un método:

app.MapGet("/hello", Hello);

Defina el método Hello con comentarios de documentos XML:

static partial class Program
{
    /// <summary>
    /// Sends a greeting.
    /// </summary>
    /// <remarks>
    /// Greeting a person by their name.
    /// </remarks>
    /// <param name="name">The name of the person to greet.</param>
    /// <returns>A greeting.</returns>
    public static string Hello(string name)
    {
        return $"Hello, {name}!";
    }
}

En el ejemplo anterior, el método Hello se agrega a la clase Program, pero puede agregarlo a cualquier clase del proyecto.

En el ejemplo anterior se muestran los comentarios de documentos XML <summary>, <remarks>, y <param>. Para obtener más información sobre los comentarios de documentos XML, incluidas todas las etiquetas admitidas, consulte la documentación de C#.

Dado que la funcionalidad principal se proporciona a través de un generador de origen, se puede deshabilitar agregando el siguiente MSBuild al archivo de proyecto.

<ItemGroup>
  <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0-preview.2.*" GeneratePathProperty="true" />
</ItemGroup>

<Target Name="DisableCompileTimeOpenApiXmlGenerator" BeforeTargets="CoreCompile">
  <ItemGroup>
    <Analyzer Remove="$(PkgMicrosoft_AspNetCore_OpenApi)/analyzers/dotnet/cs/Microsoft.AspNetCore.OpenApi.SourceGenerators.dll" />
  </ItemGroup>
</Target>

El generador de origen procesa archivos XML incluidos en la propiedad AdditionalFiles. Para agregar (o quitar), los orígenes modifican la propiedad de la siguiente manera:

<Target Name="AddXmlSources" BeforeTargets="CoreCompile">
  <ItemGroup>
    <AdditionalFiles Include="$(PkgSome_Package)/lib/net10.0/Some.Package.xml" />
  </ItemGroup>
</Target>

Microsoft.AspNetCore.OpenApi agregado a la plantilla ASP.NET Core web API (AOT nativa)

La plantilla de proyecto ASP.NET Core Web API (AOT nativo) (nombre corto webapiaot) ahora incluye soporte para la generación de documentos OpenAPI mediante el paquete Microsoft.AspNetCore.OpenApi de forma predeterminada. Esta compatibilidad está deshabilitada mediante la --no-openapi marca al crear un nuevo proyecto.

Esto fue una contribución de la comunidad por @sander1095. ¡Gracias por esta contribución!

Autenticación y autorización

En esta sección se describen las nuevas características de autenticación y autorización.

Métricas de autenticación y autorización

Se han agregado métricas para determinados eventos de autenticación y autorización en ASP.NET Core. Con este cambio, ahora puede obtener métricas para los siguientes eventos:

  • Autenticación:
    • Duración de la solicitud autenticada
    • Número de desafíos
    • Número de prohibiciones
    • Número de inicios de sesión
    • Número de cierres de sesión
  • Autorización:
    • Recuento de solicitudes que requieren autorización

La siguiente imagen muestra un ejemplo de la métrica de duración de la solicitud autenticada en el panel Aspire.

Duración de la solicitud autenticada en el panel Aspire

Para obtener más información, consulte ASP.NET métricas de autenticación y autorización principales.

Misceláneo

En esta sección se describen varias características nuevas de ASP.NET Core 10.0.

Mejor compatibilidad con las aplicaciones de prueba con instrucciones de nivel superior

.NET 10 ahora tiene mejor soporte para probar aplicaciones que usan instrucciones de nivel superior. Anteriormente, los desarrolladores tenían que agregar manualmente public partial class Program al archivo Program.cs para que el proyecto de prueba pudiera hacer referencia al Program class. public partial class Program era necesario porque la declaración de nivel superior de C# 9 generó un Program class, que fue declarado como interno.

En .NET 10, se usa un generador de origen para generar la declaración de public partial class Program si el programador no la ha declarado explícitamente. Además, se ha agregado un analizador para detectar cuándo public partial class Program se declara explícitamente y aconseja al desarrollador que lo quite.

Imagen

Las siguientes solicitudes de incorporación de cambios contribuyeron a esta característica.

Detección de si la dirección URL es local mediante RedirectHttpResult.IsLocalUrl

Use el nuevo método auxiliar de RedirectHttpResult.IsLocalUrl(url) para detectar si una dirección URL es local. Una dirección URL se considera local si se cumple lo siguiente:

Las direcciones URL que usan rutas de acceso virtuales"~/" también son locales.

IsLocalUrl es útil para validar las direcciones URL antes de redirigirlas a ellas para evitar ataques de redirección abierta.

if (RedirectHttpResult.IsLocalUrl(url))
{
    return Results.LocalRedirect(url);
}

¡Gracias @martincostello por esta contribución!