Here are some of the improvements in Preview 6.
Visual Basic users are used to enforce that their applications are single-instanced (one instance launched at a time).
WindowsFormsApplicationBase.IsSingleInstance
.ListViewGroup
, and this change makes it easier to manage a form with multiple ListViewGroups
.You can see the result shown below.
The RyuJIT team continues to add important improvements in each preview, specially with Preview 6. Let’s take a look:
The team has continuously improved the support of Single-File Apps in .NET 5. The goal was to enable publishing an app as one file for Windows, macOS, and Linux.
Over the years, you have seen a variety of hosting models for .NET in native applications. @rseanhall proposed and implemented a novel new model for doing that.
Windows Runtime (WinRT) is the technology and ABI that new APIs are exposed within Windows. You can call those APIs via .NET code, similar to how you would with C++.
The benefits are called out in Support WinRT APIs in .NET 5:
For more details, see the official docs issue at https://github.com/dotnet/docs/issues/18875.
The .NET 5 – Supported OS versions page is updated to capture the latest plans for platform support for .NET 5.0.
The package manager and container support aren't listed on that page. This information will be added before the release of .NET 5.0.
The Blazor WebAssembly template is now included in the .NET 5 SDK along with the Blazor Server template. To create a Blazor WebAssembly project, simply run the dotnet new blazorwasm
command.
You can now easily read and write JSON data from an HttpRequest
and HttpResponse
using the new ReadFromJsonAsync
and WriteAsJsonAsync
extension methods.
System.Text.Json
serializer to handle the JSON data.HasJsonContentType
extension method.The JSON extension methods can be combined with endpoint routing to create JSON APIs in a programming style we call route to code. It is a new option for developers who want to create basic JSON APIs in a lightweight way.
For example, a web app with only a handful of endpoints might choose to use a route to code rather than the full functionality of ASP.NET Core MVC.
endpoints.MapGet("/weather/{city:alpha}", async context =>
{
var city = (string)context.Request.RouteValues["city"];
var weather = GetFromDatabase(city);
await context.Response.WriteAsJsonAsync(weather);
});
You can now allow anonymous access to an endpoint using the simpler AllowAnonymous
extension method when using endpoint routing.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
})
.AllowAnonymous();
});
}
Custom handling of authorization failures is now easier with the new IAuthorizationMiddlewareResultHandler
interface that is invoked by the AuthorizationMiddleware
.
The default implementation remains the same, but a custom handler can be registered in DI allowing things like custom HTTP responses based on why authorization failed.
The following example demonstrates the usage of the IAuthorizationMiddlewareResultHandler
.
using System;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using CustomAuthorizationFailureResponse.Authorization.Requirements;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization.Policy;
using Microsoft.AspNetCore.Http;
namespace CustomAuthorizationFailureResponse.Authorization
{
public class SampleAuthorizationMiddlewareResultHandler : IAuthorizationMiddlewareResultHandler
{
private readonly IAuthorizationMiddlewareResultHandler _handler;
public SampleAuthorizationMiddlewareResultHandler()
{
_handler = new AuthorizationMiddlewareResultHandler();
}
public async Task HandleAsync(
RequestDelegate requestDelegate,
HttpContext httpContext,
AuthorizationPolicy authorizationPolicy,
PolicyAuthorizationResult policyAuthorizationResult)
{
// if the authorization was forbidden, let's use custom logic to handle that.
if (policyAuthorizationResult.Forbidden && policyAuthorizationResult.AuthorizationFailure != null)
{
// as an example, let's return 404 if specific requirement has failed
if (policyAuthorizationResult.AuthorizationFailure.FailedRequirements.Any(requirement => requirement is SampleRequirement))
{
httpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
await httpContext.Response.WriteAsync(Startup.CustomForbiddenMessage);
// return right away as the default implementation would overwrite the status code
return;
}
else if (policyAuthorizationResult.AuthorizationFailure.FailedRequirements.Any(requirement => requirement is SampleWithCustomMessageRequirement))
{
// if other requirements failed, let's just use a custom message
// but we have to use OnStarting callback because the default handlers will want to modify i.e. status code of the response
// and modifications of the response are not allowed once the writing has started
var message = Startup.CustomForbiddenMessage;
httpContext.Response.OnStarting(() => httpContext.Response.BodyWriter.WriteAsync(Encoding.UTF8.GetBytes(message)).AsTask());
}
}
await _handler.HandleAsync(requestDelegate, httpContext, authorizationPolicy, policyAuthorizationResult);
}
}
}
Hub filters, called Hub pipelines in ASP.NET SignalR, is a feature that allows you to run code before and after Hub methods are called, similar to how middleware lets you run code before and after an HTTP request. Common uses include logging, error handling, and argument validation.
You can read more about these Hub filters on the official documentation page.