{"id":25090,"date":"2021-08-10T15:18:53","date_gmt":"2021-08-10T22:18:53","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/aspnet\/?p=25090"},"modified":"2021-08-10T15:18:53","modified_gmt":"2021-08-10T22:18:53","slug":"asp-net-core-updates-in-net-6-preview-7","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/asp-net-core-updates-in-net-6-preview-7\/","title":{"rendered":"ASP.NET Core updates in .NET 6 Preview 7"},"content":{"rendered":"<p><a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-net-6-preview-7\/\">.NET 6 Preview 7 is now available<\/a> and includes many great new improvements to ASP.NET Core.<\/p>\n<p>Here&#8217;s what&#8217;s new in this preview release:<\/p>\n<ul>\n<li>Parity with existing experiences for minimal APIs<\/li>\n<li>Added <code>IResult<\/code> implementations for producing common HTTP responses<\/li>\n<li>Support Request, Response and User for minimal actions<\/li>\n<li>Minimal host and template improvements<\/li>\n<li>Supply Blazor component parameters from the query string<\/li>\n<li>Replace the current URI in the browser history from Blazor<\/li>\n<li>New <code>DynamicComponent.Instance<\/code> property<\/li>\n<li>Blazor streaming interop from JavaScript to .NET<\/li>\n<li>Large file upload &amp; faster file uploads with Blazor<\/li>\n<li>Modify HTML <code>&lt;head&gt;<\/code> content from Blazor components<\/li>\n<li>Support for the <code>multiple<\/code> attribute on <code>&lt;select&gt;<\/code> elements in Blazor<\/li>\n<li>Support for HTTP\/3 in Kestrel<\/li>\n<li>QUIC support moved to the shared framework<\/li>\n<li>Allow control over <code>Activity<\/code> creation<\/li>\n<li>Support for non-ASCII characters in Kestrel response headers<\/li>\n<li>Add W3CLogger<\/li>\n<li>Add authentication expiration option to SignalR<\/li>\n<\/ul>\n<h2>Get started<\/h2>\n<p>To get started with ASP.NET Core in .NET 6 Preview 7, <a href=\"https:\/\/dotnet.microsoft.com\/download\/dotnet\/6.0\">install the .NET 6 SDK<\/a>.<\/p>\n<p>If you&#8217;re on Windows using Visual Studio, <a href=\"https:\/\/aka.ms\/vs2022preview\">install the latest preview of Visual Studio 2022<\/a>. .NET 6 will be supported in a future public release of <a href=\"https:\/\/visualstudio.microsoft.com\/vs\/mac\/preview\/\">Visual Studio 2022 for Mac<\/a>.<\/p>\n<p>To get setup with .NET MAUI &amp; Blazor for cross-platform native apps, see the latest instructions in the <a href=\"https:\/\/docs.microsoft.com\/dotnet\/maui\/get-started\/installation\">.NET MAUI getting started guide<\/a>. Be sure to also check out the <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-net-maui-preview-7\/\">Announcing .NET MAUI Preview 7<\/a> blog post for all the details on what&#8217;s new in .NET MAUI in this release.<\/p>\n<p>To install the latest .NET WebAssembly tools for ahead-of-time (AOT) compilation and runtime relinking, uninstall the earlier <code>microsoft-net-sdk-blazorwebassembly-aot<\/code> workload and install the new <code>wasm-tools<\/code> workload by running the following commands from an elevated command prompt:<\/p>\n<pre><code>dotnet workload uninstall microsoft-net-sdk-blazorwebassembly-aot\ndotnet workload install wasm-tools\n<\/code><\/pre>\n<h2>Upgrade an existing project<\/h2>\n<p>To upgrade an existing ASP.NET Core app from .NET 6 Preview 6 to .NET 6 Preview 7:<\/p>\n<ul>\n<li>Update all Microsoft.AspNetCore.* package references to <code>6.0.0-preview.7.*<\/code>.<\/li>\n<li>Update all Microsoft.Extensions.* package references to <code>6.0.0-preview.7.*<\/code>.<\/li>\n<\/ul>\n<p>To upgrade a .NET MAUI Blazor app from .NET 6 Preview 6 to .NET 6 Preview 7 we recommend starting from a new .NET MAUI Blazor project created with the .NET 6 Preview 7 SDK and then copying code over from your original project.<\/p>\n<p>See the full list of <a href=\"https:\/\/docs.microsoft.com\/dotnet\/core\/compatibility\/6.0#aspnet-core\">breaking changes<\/a> in ASP.NET Core for .NET 6.<\/p>\n<h2>What&#8217;s new with minimal APIs?<\/h2>\n<p>Since we <a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/asp-net-core-updates-in-net-6-preview-4\/#introducing-minimal-apis\">announced minimal APIs in .NET 6 Preview 4<\/a> we&#8217;ve been focused on enabling a more robust set of features. For .NET 6 Preview 7 we&#8217;re happy to announce that we&#8217;re lighting up more of your favorite ASP.NET experiences with a minimal twist. Let&#8217;s take a look at what you can expect.<\/p>\n<h3>Parity with existing experiences<\/h3>\n<p>Minimal APIs fundamentally change how the app startup code is structured. This meant that some of the tools and libraries we ship that interact with the app needed to be updated to handle this new pattern. The following tools and libraries have now been updated accordingly:<\/p>\n<ul>\n<li><a href=\"https:\/\/docs.microsoft.com\/en-us\/ef\/core\/managing-schemas\/migrations\/?tabs=dotnet-core-cli\">EF Migrations<\/a><\/li>\n<li><a href=\"https:\/\/docs.microsoft.com\/en-us\/ef\/core\/cli\/powershell#scaffold-dbcontext\">Scaffolding<\/a><\/li>\n<li><a href=\"https:\/\/docs.microsoft.com\/en-us\/aspnet\/core\/test\/integration-tests?view=aspnetcore-5.0\">WebApplicationFactory<\/a><\/li>\n<\/ul>\n<h3>Added <code>IResult<\/code> implementations for producing common HTTP responses<\/h3>\n<p>In earlier previews, we extended <code>IActionResult<\/code> implementations from MVC to support the new <code>IResult<\/code> type introduced for minimal APIs. In this release, we&#8217;ve removed the dependency between <code>IActionResult<\/code> and <code>IResult<\/code> and added a new <a href=\"https:\/\/github.com\/dotnet\/aspnetcore\/blob\/v6.0.0-preview.7.21378.6\/src\/Http\/Http.Results\/src\/Results.cs\">static <code>Results<\/code> utility class<\/a> for producing common HTTP responses. Here&#8217;s an example:<\/p>\n<pre><code class=\"csharp\">app.MapPut(\"\/todos\/{id}\", async (TodoDbContext db, int id, Todo todo) =&gt;\n{\n    if (id != todo.Id)\n    {\n        return Results.BadRequest();\n    }\n\n    if (!await db.Todos.AnyAsync(x =&gt; x.Id == id))\n    {\n        return Results.NotFound();\n    }\n\n    db.Update(todo);\n    await db.SaveChangesAsync();\n\n    return Results.Ok();\n});\n<\/code><\/pre>\n<p>Thank you <a href=\"https:\/\/github.com\/dotnet\/aspnetcore\/pull\/32647\">Juan Barahona<\/a> for contributing these <code>IResult<\/code> implementations!<\/p>\n<h3>Support Request, Response and User for minimal actions<\/h3>\n<p>In this preview, we added support for binding <code>HttpRequest<\/code>, <code>HttpResponse<\/code> and <code>ClaimsPrincipal<\/code> parameters in minimal actions. These parameters come from the <code>Request<\/code>, <code>Response<\/code> and <code>User<\/code> properties on <code>HttpContext<\/code> respectively. This is in addition to the pre-existing support for binding the <code>HttpContext<\/code> directly and a <code>CancellationToken<\/code> from <code>HttpContext.RequestAborted<\/code>.<\/p>\n<p>The example below accepts the current user directly into the request handler method.<\/p>\n<pre><code class=\"csharp\">app.MapGet(\"\/api\/items\", async (ITodoService service, ClaimsPrincipal user) =&gt;\n{\n    return await service.GetListAsync(user.GetUserId());\n})\n.RequireAuthorization();\n<\/code><\/pre>\n<p>Thank you <a href=\"https:\/\/github.com\/dotnet\/aspnetcore\/pull\/33883\">Martin Costello<\/a> for contributing this feature!<\/p>\n<h2>Minimal host and template improvements<\/h2>\n<p>Minimal APIs introduced new hosting APIs and, combined with new C# features like global usings and top-level statements, enabled us to streamline the app startup experience. In this preview, we&#8217;re extending these changes to the other ASP.NET Core project templates.<\/p>\n<p>For example, when you create a new ASP.NET Core Web API using the template you&#8217;ll now notice the following:<\/p>\n<ul>\n<li>No <code>Startup.cs<\/code><\/li>\n<li>Leveraging implicit <code>usings<\/code><\/li>\n<li>New hosting model using <code>WebApplication.CreateBuilder<\/code><\/li>\n<li>Top-level statements in <code>Program.cs<\/code> (no namespace, class, or method declarations)<\/li>\n<li>Nullable reference types<\/li>\n<\/ul>\n<p>These changes reduce the amount of boilerplate code required to configure and start a new app. Note that the existing hosting model and <code>Startup<\/code> pattern will continue to be supported for existing apps.<\/p>\n<p><strong>ASP.NET Core Web API in .NET 5<\/strong><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/user-images.githubusercontent.com\/2546640\/128652493-7ec47b9a-e4e0-4e94-ac75-a2119aec6117.png\" alt=\"image\" \/><\/p>\n<p><strong>ASP.NET Core Web API in .NET 6<\/strong><\/p>\n<pre><code class=\"csharp\">var builder = WebApplication.CreateBuilder(args);\n\nbuilder.Services.AddControllers();\nbuilder.Services.AddSwaggerGen(c =&gt;\n{\n    c.SwaggerDoc(\"v1\", new() { Title = \"WebApplication22\", Version = \"v1\" });\n});\n\nvar app = builder.Build();\n\nif (app.Environment.IsDevelopment())\n{\n    app.UseSwagger();\n    app.UseSwaggerUI(c =&gt; c.SwaggerEndpoint(\"\/swagger\/v1\/swagger.json\", \"WebApplication22 v1\"));\n}\n\napp.UseHttpsRedirection();\n\napp.UseAuthorization();\n\napp.MapControllers();\n\napp.Run();\n<\/code><\/pre>\n<p>Check out the the <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-net-6-preview-7#net-sdk-c-project-templates-modernized\">.NET blog<\/a> for more details on how we&#8217;re modernizing the project templates that ship with the .NET SDK.<\/p>\n<blockquote>\n<p><strong>Note about implicit using statements<\/strong>: Based on early feedback during implementation, <a href=\"https:\/\/github.com\/dotnet\/sdk\/issues\/19521\">changes to the implicit usings feature are being made as part of the next release<\/a>, including the requirement to opt-in to implicit <code>usings<\/code> in the project file, rather than them being included by default based on the project targeting .NET 6. This will ensure they don&#8217;t impact existing projects being migrated to .NET 6 until the author is ready to enable the feature.<\/p>\n<\/blockquote>\n<h2>Supply Blazor component parameters from the query string<\/h2>\n<p>Blazor components can now receive parameters from the query string. To specify that a component parameter of a routable component can come from the query string, apply the <code>[SupplyParameterFromQuery]<\/code> attribute in addition to the normal <code>[Parameter]<\/code> attribute:<\/p>\n<pre><code class=\"razor\">@page \"\/search\"\n\n&lt;h1&gt;Search&lt;\/h1&gt;\n\n&lt;p&gt;Filter: @Filter&lt;\/p&gt;\n\n&lt;p&gt;Page: @Page&lt;\/p&gt;\n\n&lt;p&gt;Assignees:&lt;\/p&gt;\n&lt;ul&gt;\n    @foreach (var assignee in Assignees)\n    {\n        &lt;li&gt;@assignee&lt;\/li&gt;\n    }\n&lt;\/ul&gt;\n\n@code {\n    \/\/ Handles URL patterns like \/search?filter=some+stuff&amp;page=3&amp;assignee=Monica&amp;assignee=Chandler\n\n    [Parameter]\n    [SupplyParameterFromQuery]\n    public string Filter { get; set; }\n\n    [Parameter]\n    [SupplyParameterFromQuery]\n    public int? Page { get; set; }\n\n    [Parameter]\n    [SupplyParameterFromQuery(Name = \"assignee\")]\n    public string[] Assignees { get; set; }\n}\n<\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/aspnet\/wp-content\/uploads\/sites\/16\/2021\/08\/blazor-query-search.png\" alt=\"Blazor search query\" \/><\/p>\n<p>Component parameters supplied from the query string may be of the following types:<\/p>\n<ul>\n<li><code>String<\/code>, <code>bool<\/code>, <code>DateTime<\/code>, <code>decimal<\/code>, <code>double<\/code>, <code>float<\/code>, <code>Guid<\/code>, <code>int<\/code>, <code>long<\/code>.<\/li>\n<li>Nullable variants of the above types (except <code>string<\/code> &#8211; not applicable).<\/li>\n<li>Arrays of the above types, nullable or not.<\/li>\n<\/ul>\n<h2>Replace the current URI in the browser history from Blazor<\/h2>\n<p>When calling <code>NavigationManager.NavigateTo<\/code> in a Blazor app, you can now specify that you want to replace the current URI in the browser history instead of pushing a new URI onto the history stack. To replace the current URI in the browser history, specify <code>true<\/code> for the new <code>replace<\/code> parameter:<\/p>\n<pre><code class=\"csharp\">@NavigationManager.NavigateTo(\"Other\", replace: true)\n<\/code><\/pre>\n<h2>New <code>DynamicComponent.Instance<\/code> property<\/h2>\n<p><code>DynamicComponent<\/code> now has an <code>Instance<\/code> property that provides a convenient way to get access to the dynamically created component instance:<\/p>\n<pre><code class=\"razor\">&lt;DynamicComponent Type=\"typeof(MyComponent)\" @ref=\"dc\" \/&gt;\n\n&lt;button @onclick=\"Refresh\"&gt;Refresh&lt;\/button&gt;\n\n@code {\n    DynamicComponent dc;\n    Task Refresh()\n    {\n        return (dc.Instance as IRefreshable)?.Refresh();\n    }\n}\n<\/code><\/pre>\n<h2>Blazor streaming interop from JavaScript to .NET<\/h2>\n<p>Blazor now supports streaming data directly from JavaScript to .NET. Streams are requested using the new <code>IJSStreamReference<\/code> interface:<\/p>\n<p><em>JavaScript<\/em><\/p>\n<pre><code class=\"js\">function jsToDotNetStreamReturnValue() {\n    return new Uint8Array(10000000);\n}\n<\/code><\/pre>\n<p><em>C#<\/em><\/p>\n<pre><code class=\"csharp\">  var dataReference = await JSRuntime.InvokeAsync&lt;IJSStreamReference&gt;(\"jsToDotNetStreamReturnValue\");\n  using var dataReferenceStream = await dataReference.OpenReadStreamAsync(maxAllowedSize: 10_000_000);\n\n  \/\/ Write JS Stream to disk\n  var outputPath = Path.Combine(Path.GetTempPath(), \"file.txt\");\n  using var outputFileStream = File.OpenWrite(outputPath);\n  await dataReferenceStream.CopyToAsync(outputFileStream); \n<\/code><\/pre>\n<h2>Large file upload &amp; faster file uploads with Blazor<\/h2>\n<p>Using the new Blazor streaming interop support mentioned above, we now support uploading files larger than 2GB using the <code>InputFile<\/code> component. The updated <code>InputFile<\/code> component is also much more efficient at uploading files thanks to native <code>byte[]<\/code> streaming, which avoids expensive Base64 encoding.<\/p>\n<h2>Modify HTML <code>&lt;head&gt;<\/code> content from Blazor components<\/h2>\n<p>Blazor now has built-in support for modifying HTML <code>&lt;head&gt;<\/code> element content from components, including setting the <code>&lt;title&gt;<\/code> and adding <code>&lt;meta&gt;<\/code> elements.<\/p>\n<p>To specify the page&#8217;s title from a component, use the new <code>PageTitle<\/code> component. The <code>HeadContent<\/code> component can be used to render other content to the <code>&lt;head&gt;<\/code>.<\/p>\n<pre><code class=\"razor\">&lt;PageTitle&gt;@title&lt;\/PageTitle&gt;\n\n&lt;HeadContent&gt;\n    &lt;meta name=\"description\" content=\"@description\"&gt;\n&lt;\/HeadContent&gt;\n\n@code {\n    private string description = \"Description set by component\";\n    private string title = \"Title set by component\";\n}\n<\/code><\/pre>\n<p>To enable the functionality provided by <code>PageTitle<\/code> and <code>HeadContent<\/code>, you need to add a <code>HeadOutlet<\/code> root component to your application. In Blazor WebAssembly, this can be done by adding the following line in <code>Program.Main<\/code>:<\/p>\n<pre><code class=\"csharp\">builder.RootComponents.Add&lt;HeadOutlet&gt;(\"head::after\");\n<\/code><\/pre>\n<p>In Blazor Server, the setup is slightly more involved. In order to support prerendering, the <code>App<\/code> root component needs to be rendered before the <code>HeadOutlet<\/code>. A convenient way to achieve this is to move most of the content in <code>_Host.cshtml<\/code> to <code>_Layout.cshtml<\/code>, as shown below.<\/p>\n<p><em>_Layout.cshtml<\/em><\/p>\n<pre><code class=\"cshtml\">@using Microsoft.AspNetCore.Components.Web\n@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers\n\n&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n&lt;head&gt;\n    &lt;meta charset=\"utf-8\" \/&gt;\n    &lt;title&gt;Blazor Server App&lt;\/title&gt;\n    &lt;base href=\"~\/\" \/&gt;\n    &lt;component type=\"typeof(HeadOutlet)\" render-mode=\"ServerPrerendered\" \/&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    @RenderBody()\n    &lt;script src=\"_framework\/blazor.server.js\"&gt;&lt;\/script&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;\n<\/code><\/pre>\n<p><em>_Host.cshtml<\/em><\/p>\n<pre><code class=\"cshtml\">@page \"\/\"\n@namespace BlazorServerWeb_CSharp.Pages\n@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers\n@{\n    Layout = \"_Layout\";\n}\n\n&lt;component type=\"typeof(App)\" render-mode=\"ServerPrerendered\" \/&gt;\n<\/code><\/pre>\n<p>A future release will include updated Blazor project templates, so performing these changes to enable <code>&lt;head&gt;<\/code> modification won&#8217;t be necessary for new projects.<\/p>\n<h2>Support for the <code>multiple<\/code> attribute on <code>&lt;select&gt;<\/code> elements in Blazor<\/h2>\n<p>If you specify the <code>multiple<\/code> attribute in a <code>&lt;select&gt;<\/code> elements from a Blazor component, the <code>onchange<\/code> event will now supply an array of the selected elements via <code>ChangeEventArgs<\/code>. Likewise, array values can be bound to the <code>value<\/code> attribute when <code>multiple<\/code> is specified.<\/p>\n<pre><code class=\"razor\">&lt;p&gt;\n    Select one or more cars: \n    &lt;select @onchange=\"SelectedCarsChanged\" multiple&gt;\n        &lt;option value=\"audi\"&gt;Audi&lt;\/option&gt;\n        &lt;option value=\"jeep\"&gt;Jeep&lt;\/option&gt;\n        &lt;option value=\"opel\"&gt;Opel&lt;\/option&gt;\n        &lt;option value=\"saab\"&gt;Saab&lt;\/option&gt;\n        &lt;option value=\"volvo\"&gt;Volvo&lt;\/option&gt;\n    &lt;\/select&gt;\n&lt;\/p&gt;\n\n&lt;p&gt;\n    Select one or more cities: \n    &lt;select @bind=\"SelectedCities\" multiple&gt;\n        &lt;option value=\"bal\"&gt;Baltimore&lt;\/option&gt;\n        &lt;option value=\"la\"&gt;Los Angeles&lt;\/option&gt;\n        &lt;option value=\"pdx\"&gt;Portland&lt;\/option&gt;\n        &lt;option value=\"sf\"&gt;San Francisco&lt;\/option&gt;\n        &lt;option value=\"sea\"&gt;Seattle&lt;\/option&gt;\n    &lt;\/select&gt;\n&lt;\/p&gt;\n\n@code {\n    public string[] SelectedCars { get; set; } = new string[] { };\n    public string[] SelectedCities { get; set; } = new[] { \"bal\", \"sea\" };\n\n    void SelectedCarsChanged(ChangeEventArgs e)\n    {\n        SelectedCars = (string[])e.Value;\n    }\n}\n<\/code><\/pre>\n<p>When using <code>&lt;InputSelect&gt;<\/code>, the <code>multiple<\/code> attribute is inferred if the bound value has an array type.<\/p>\n<pre><code class=\"razor\">&lt;EditForm EditContext=\"@editContext\"&gt;\n    Select one or more classifications (Minimum: 2, Maximum: 3):\n    &lt;InputSelect @bind-Value=\"starship.SelectedClassification\"&gt;\n        &lt;option value=\"@Classification.Exploration\"&gt;Exploration&lt;\/option&gt;\n        &lt;option value=\"@Classification.Diplomacy\"&gt;Diplomacy&lt;\/option&gt;\n        &lt;option value=\"@Classification.Defense\"&gt;Defense&lt;\/option&gt;\n        &lt;option value=\"@Classification.Research\"&gt;Research&lt;\/option&gt;\n    &lt;\/InputSelect&gt;\n&lt;\/EditForm&gt;\n\n@code {\n    private EditContext editContext;\n    private Starship starship = new();\n\n    protected override void OnInitialized()\n    {\n        editContext = new(starship);\n    }\n\n    private class Starship\n    {\n        [Required, MinLength(2), MaxLength(3)]\n        public Classification[] SelectedClassification { get; set; } =\n            new[] { Classification.Diplomacy };\n    }\n\n    private enum Classification { Exploration, Diplomacy, Defense, Research }\n}\n<\/code><\/pre>\n<h2>Preview support for HTTP\/3 in Kestrel<\/h2>\n<p>Preview 7 introduces early support for HTTP\/3 and QUIC in Kestrel to try out and give feedback on.<\/p>\n<p>HTTP\/3 is the third and upcoming major version of HTTP. HTTP\/3 uses the same semantics as HTTP\/1.1 and HTTP\/2: the same request methods, status codes, and message fields apply to all versions. The differences are in the underlying transport. Both HTTP\/1.1 and HTTP\/2 use TCP as their transport. HTTP\/3 uses a new transport technology developed alongside HTTP\/3 called QUIC.<\/p>\n<p>HTTP\/3 and QUIC have a number of benefits compared to older HTTP versions:<\/p>\n<ul>\n<li><strong>Faster response time of the first request.<\/strong> QUIC and HTTP\/3 negotiates the connection in fewer round-trips between the client and the server. The first request reaches the server faster.<\/li>\n<li><strong>Improved experience when there is connection packet loss.<\/strong> HTTP\/2 multiplexes multiple requests via one TCP connection. Packet loss on the connection would affect all requests. This problem is called &#8220;head-of-line blocking&#8221;. Because QUIC provides native multiplexing, lost packets only impact the requests where data has been lost.<\/li>\n<li><strong>Supports transitioning between networks.<\/strong> This feature is useful for mobile devices where it is common to switch between Wi-Fi and cellular networks as a mobile device changes location. Today HTTP\/1.1 and HTTP\/2 connections will fail with an error and force an app or web browser to retry. HTTP\/3 allows the app or web browser to seamlessly continue when a network changes. Kestrel doesn&#8217;t support network transitions in .NET 6, but we&#8217;ll explore adding it in a future .NET release.<\/li>\n<\/ul>\n<p>To start using HTTP\/3, configure the QUIC transport, and modify <code>ListenOptions<\/code> to add an HTTP\/3 binding. For use with browser-based clients, you&#8217;ll also need to enable sending the <code>alt-svc<\/code> header.<\/p>\n<pre><code class=\"csharp\">    var builder = WebApplication.CreateBuilder(args);\n    builder.WebHost.UseKestrel()\n    \/\/ Set up Quic options\n    .UseQuic(options =&gt;\n    {\n        options.Alpn = \"h3-29\";\n        options.IdleTimeout = TimeSpan.FromMinutes(1);\n    })\n    .ConfigureKestrel((context, options) =&gt;\n    {\n        options.EnableAltSvc = true;\n        options.Listen(IPAddress.Any, 5001, listenOptions =&gt;\n        {\n            \/\/ Use Http3\n            listenOptions.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;\n            listenOptions.UseHttps();\n        });\n    });\n<\/code><\/pre>\n<p>HTTP\/3 is not supported everywhere. See <a href=\"https:\/\/docs.microsoft.com\/aspnet\/core\/fundamentals\/servers\/kestrel\/http3\">use HTTP\/3 with the ASP.NET Core Kestrel web server<\/a> for information on getting started with HTTP\/3 in Kestrel.<\/p>\n<h2>QUIC support moved to the shared framework<\/h2>\n<p>We&#8217;re no longer shipping the <code>Microsoft.AspNetCore.Server.Kestrel.Transport.Quic<\/code> package, and are instead including the assembly in the ASP.NET Core shared framework. Customers with a <code>PackageReference<\/code> to <code>Microsoft.AspNetCore.Server.Kestrel.Transport.Quic<\/code> should remove the <code>PackageReference<\/code> from their project.<\/p>\n<h2>Allow control over <code>Activity<\/code> creation<\/h2>\n<p>We&#8217;ve added support for <code>DistributedContextPropagator<\/code>s in ASP.NET Core. Prior to this change, ASP.NET Core had knowledge of the W3C TraceContext and W3C Baggage specifications and we created an <code>Activity<\/code> only if the <code>tracestate<\/code> and <code>traceparent<\/code> HTTP headers were present on the incoming HTTP request. This made it impossible to support other tracing specifications. It&#8217;s now possible to support other distributed tracing specifications by implementing a custom <code>DistributedContextPropagator<\/code> and registering it in the DI container.<\/p>\n<h2>Support for non-ASCII characters in Kestrel response headers<\/h2>\n<p>Kestrel now has support for sending non-ASCII characters in HTTP response headers. To opt-in custom encoding on per-header basis, you can provide a <code>ResponseHeaderEncodingSelector<\/code>:<\/p>\n<pre><code class=\"csharp\">builder.WebHost.ConfigureKestrel(options =&gt;\n{\n    options.ResponseHeaderEncodingSelector = (_) =&gt; Encoding.ASCII;\n});\n<\/code><\/pre>\n<blockquote>\n<p>Note: While use of custom response header encoding may be needed in some cases, we discourage the use of non-ASCII encodings to avoid compatibility issues with other HTTP clients.<\/p>\n<\/blockquote>\n<h2>Add W3CLogger<\/h2>\n<p>ASP.NET Core is now capable of generating server access logs in the <a href=\"https:\/\/www.w3.org\/TR\/WD-logfile.html\">W3C Extended Log File Format<\/a>. To start emitting server access logs, you need to add the logger to DI and add the W3C logging middleware to your middleware pipeline:<\/p>\n<pre><code class=\"csharp\">var builder = WebApplication.CreateBuilder(args);\n\nbuilder.Services.AddW3CLogging(options =&gt;\n{\n    options.LogDirectory = @\"C:\\logs\";\n    options.LoggingFields = W3CLoggingFields.Request | W3CLoggingFields.ConnectionInfoFields;\n});\n\nvar app = builder.Build();\n\napp.UseW3CLogging();\nif (app.Environment.IsDevelopment())\n{\n    app.UseDeveloperExceptionPage();\n}\n\napp.MapGet(\"\/\", () =&gt; \"Hello World!\");\napp.Run();\n<\/code><\/pre>\n<p>This will produce a log file that resembles this output:<\/p>\n<pre><code>#Version: 1.0\n#Start-Date: 2021-08-10 01:07:40\n#Fields: c-ip s-ip s-port cs-method cs-uri-stem cs-uri-query cs-version cs-host cs(User-Agent) cs(Referer)\n::1 ::1 5001 GET \/ - HTTP\/2 localhost:5001 Mozilla\/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit\/537.36+(KHTML,+like+Gecko)+Chrome\/92.0.4515.131+Safari\/537.36+Edg\/92.0.902.67 -\n::1 ::1 5001 GET \/favicon.ico - HTTP\/2 localhost:5001 Mozilla\/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit\/537.36+(KHTML,+like+Gecko)+Chrome\/92.0.4515.131+Safari\/537.36+Edg\/92.0.902.67 https:\/\/localhost:5001\/\n::1 ::1 5001 GET \/ - HTTP\/2 localhost:5001 Mozilla\/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit\/537.36+(KHTML,+like+Gecko)+Chrome\/92.0.4515.131+Safari\/537.36+Edg\/92.0.902.67 -\n::1 ::1 5001 GET \/ - HTTP\/2 localhost:5001 Mozilla\/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit\/537.36+(KHTML,+like+Gecko)+Chrome\/92.0.4515.131+Safari\/537.36+Edg\/92.0.902.67 -\n::1 ::1 5001 GET \/ - HTTP\/2 localhost:5001 Mozilla\/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit\/537.36+(KHTML,+like+Gecko)+Chrome\/92.0.4515.131+Safari\/537.36+Edg\/92.0.902.67 -\n<\/code><\/pre>\n<h2>Add authentication expiration option to SignalR<\/h2>\n<p>There is a new option that will enable SignalR to track the expiration of an authentication token and close the connection if the token expires. This option can be enabled with <code>CloseOnAuthenticationExpiration<\/code> on <code>HttpConnectionDispatcherOptions<\/code> as shown below.<\/p>\n<pre><code class=\"csharp\">app.UseEndpoints(endpoints =&gt;\n{\n    endpoints.MapHub&lt;MyHub&gt;(\"\/hub\", options =&gt;\n    {\n        options.CloseOnAuthenticationExpiration = true;\n    });\n});\n<\/code><\/pre>\n<h2>Give feedback<\/h2>\n<p>We hope you enjoy this preview release of ASP.NET Core in .NET 6. We&#8217;re eager to hear about your experiences with this release. Let us know what you think by filing issues on <a href=\"https:\/\/github.com\/dotnet\/aspnetcore\/issues\">GitHub<\/a>.<\/p>\n<p>Thanks for trying out ASP.NET Core!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>.NET 6 Preview 7 is now available! Check out all the improvements in ASP.NET Core in this update.<\/p>\n","protected":false},"author":417,"featured_media":21379,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[197,7509,7251],"tags":[],"class_list":["post-25090","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-aspnet","category-aspnetcore","category-blazor"],"acf":[],"blog_post_summary":"<p>.NET 6 Preview 7 is now available! Check out all the improvements in ASP.NET Core in this update.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/25090","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/417"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=25090"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/25090\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/21379"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=25090"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=25090"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=25090"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}