ASP.NET Core updates in .NET 8 Preview 4

Daniel Roth

.NET 8 Preview 4 is now available and includes many great new improvements to ASP.NET Core.

Here’s a summary of what’s new in this preview release:

  • Blazor
    • Streaming rendering with Blazor components
    • Handling form posts with Blazor SSR
    • Route to named elements in Blazor
    • Webcil packaging for Blazor WebAssembly apps
  • API authoring
    • Expanded support for form binding in minimal APIs
    • API project template includes .http file
  • Native AOT
    • Logging and exception handling in compile-time generated minimal APIs
    • ASP.NET Core top-level APIs annotated for trim warnings
    • Reduced app size with configurable HTTPS support
    • Worker Service template updates
    • Additional default services configured in the slim builder
    • API template JSON configuration changes
    • Support for JSON serialization of compiler-generated IAsyncEnumerable unspeakable types
  • Authentication and authorization
    • Identity API endpoints
    • Improved support for custom authorization policies with IAuthorizationRequirementData
  • ASP.NET Core metrics

For more details on the ASP.NET Core work planned for .NET 8 see the full ASP.NET Core roadmap for .NET 8 on GitHub.

Get started

To get started with ASP.NET Core in .NET 8 Preview 4, install the .NET 8 SDK.

If you’re on Windows using Visual Studio, we recommend installing the latest Visual Studio 2022 preview. Visual Studio for Mac support for .NET 8 previews isn’t available at this time.

Upgrade an existing project

To upgrade an existing ASP.NET Core app from .NET 8 Preview 3 to .NET 8 Preview 4:

  • Update the target framework of your app to net8.0.
  • Update all Microsoft.AspNetCore.* package references to 8.0.0-preview.4.*.
  • Update all Microsoft.Extensions.* package references to 8.0.0-preview.4.*.

See also the full list of breaking changes in ASP.NET Core for .NET 8.

Blazor

Streaming rendering with Blazor components

You can now stream content updates on the response stream when using server-side rendering (SSR) with Blazor in .NET 8. Streaming rendering can improve the user experience for server-side rendered pages that need to perform long-running async tasks in order to render fully.

For example, to render a page you might need to make a long running database query or an API call. Normally all async tasks executed as part of rendering a page must complete before the rendered response can be sent, which can delay loading the page. Streaming rendering initially renders the entire page with placeholder content while async operations execute. Once the async operations completes, the updated content is sent to the client on the same response connection and then patched by Blazor into the DOM. The benefit of this approach is that the main layout of the app renders as quickly as possible and the page is updated as soon as the content is ready.

To enable streaming rendering, you’ll first need to add the new Blazor script.

<script src="_framework/blazor.web.js" suppress-error="BL9992"></script>

Note that if you’re adding this script to a Blazor component, like your layout component, you’ll need to add the suppress-error="BL9992" attribute to avoid getting an error about using script tags in components.

Then, to enable streaming rendering for a specific component, use the [StreamRendering(true)] attribute. Typically this is done using the @attribute Razor directive:

@page "/fetchdata"
@using BlazorSSR.Data
@inject WeatherForecastService ForecastService
@attribute [StreamRendering(true)]

<PageTitle>Weather forecast</PageTitle>

<h1>Weather forecast</h1>

@if (forecasts is null)
{
    <p><em>Loading...</em></p>
}
else
{
    // Render weather forecasts
}

@code {
    private string message;

    protected override async Task OnInitializedAsync()
    {
        forecasts = await ForecastService.GetForecastAsync(DateOnly.FromDateTime(DateTime.Now));
    }
}

The component will now initially render without waiting for any async tasks to complete using placeholder content (“Loading…”). As the async tasks complete, the updated content is streamed to the response and then patched by Blazor into the DOM.

Blazor streaming rendering

Handling form posts with Blazor SSR

You can now use Blazor components to handle form posts with server-side rendering.

To enable handling form submissions from the server, you first need to setup a model binding context using the CascadingModelBinder component. An easy way to do this is in the main layout of your app:

<CascadingModelBinder>
    @Body
</CascadingModelBinder>

To define a form in Blazor you use the existing EditForm component and the corresponding input components, like InputText, InputSelect, etc.

The EditForm component will render a standard HTML form element, so you can use the method attribute to specify if the form should send POST request. The EditForm event handlers are not supported with GET requests.

When the form is submitted, the request will be routed to the corresponding page and then handled by the form with the matching form handler name as specified by the handler query string parameter. You can specify the form handler name for an EditForm using the FormHandlerName attribute. If there’s only one form on the page, then you don’t need to specify a name. You can then handle the form submission using the EditForm events.

Support for model binding and validating the request data hasn’t been implemented yet (it’s coming!), but you can manually handle the request data using the FormDataProvider service. The FormDataProvider.Entries property provides access to the form data and the FormDataProvider.Name property specifies the intended form handler.

Here’s what a simple server-side rendered form in Blazor looks like:

@inject FormDataProvider FormData

<EditForm method="POST" Model="exampleModel" OnValidSubmit="HandleSubmit">
    <InputText @bind-Value="exampleModel.Name" />
    <button type="submit">Submit</button>
</EditForm>

@code {
    ExampleModel exampleModel = new();

    protected override void OnInitialized()
    {
        // Manually model bind the form data using the FormDataProvider service
        if (FormData.Entries.TryGetValue("Name", out var nameValues))
        {
            exampleModel.Name = nameValues.First();
        }
    }

    void HandleSubmit()
    {
        // Handle the submitted form data
    }

    public class ExampleModel
    {
        public string? Name { get; set; }
    }
}

Route to named elements in Blazor

Blazor now supports using client-side routing to navigate to a specific HTML element on a page using standard URL fragments. If you specify an identifier for an HTML element using the standard id attribute, Blazor will correctly scroll to that element when the URL fragment matches the element identifier.

Webcil packaging for Blazor WebAssembly apps

You can now try out the new Webcil package with Blazor WebAssembly apps. Webcil is web-friendly packaging of .NET assemblies that removes any content specific to native Windows execution to avoid issues when deploying to environments that block the download or use of .dll files.

To enable use of Webcil for your Blazor WebAssembly apps, add the WasmEnableWebcil property to your project file:

<PropertyGroup>
    <WasmEnableWebcil>true</WasmEnableWebcil>
</PropertyGroup>

If you encounter issues with using .webcil files in your environment, please let us know by creating an issue on GitHub.

API authoring

Expanded support for form binding in minimal APIs

This preview introduces expanded support for binding to form types in minimal APIs. Form-based parameters are now inferred without the need of the FromForm attribute. Support for form-based parameters includes: IFormCollection, IFormFile, and IFormFileCollection. OpenAPI metadata is inferred for form parameters to support integration with Swagger UI.

The code sample below showcases implementing a minimal API that handles file uploads by leveraging inferred binding from the IFormFile type.

var app = WebApplication.Create();

string GetOrCreateFilePath(string fileName, string filesDirectory = "uploadFiles")
{
    var directoryPath = Path.Combine(app.Environment.ContentRootPath, filesDirectory);
    Directory.CreateDirectory(directoryPath);
    return Path.Combine(directoryPath, fileName);
}

async Task UploadFileWithName(IFormFile file, string fileSaveName)
{
    var filePath = GetOrCreateFilePath(fileSaveName);
    await using var fileStream = new FileStream(filePath, FileMode.Create);
    await file.CopyToAsync(fileStream);
}

app.MapPost("/upload", async (IFormFile file) => {
    var fileSaveName = Guid.NewGuid().ToString("N") + Path.GetExtension(file.FileName);
    await UploadFileWithName(file, fileSaveName);
    return TypedResults.Ok("File uploaded successfully!");
});

app.Run();

This feature is supported in minimal APIs that use runtime-based code generation and in minimal APIs leveraging the new compile-time code generation for Native AOT scenarios.

Note: It’s important to be defensive against XSRF attacks when implementing forms in an application. This code sample outlines how to use the anti-forgery services in ASP.NET to support the generation and validation of anti-forgery tokens in minimal APIs.

API project template includes .http file

The API project template (generated via dotnet new api) now includes an .http file that can be used to send requests to the endpoints defined within the application from the new HTTP editor in Visual Studio.

@MyApi_HostAddress = http://localhost:5233

GET {{MyApi_HostAddress}}/todos/
Accept: application/json

###

GET {{MyApi_HostAddress}}/todos/1
Accept: application/json

###

Native AOT

Logging and exception handling in compile-time generated minimal APIs

Minimal APIs generated at runtime support automatically logging (or throwing exceptions in Development environments) when parameter binding fails. In this preview, we introduce the same support for APIs generated at compile-time via the Request Delegate Generator (RDG).

Consider the following API endpoints where we’ve enabled using the RDG by setting <EnableRequestDelegateGenerator>true</EnableRequestDelegateGenerator>:

var app = WebApplication.Create();

app.MapGet("/hello/{name}", (string name)
    => $"Hello {name}!");
app.MapGet("/age", (DateTime birthDate)
    => $"You're about {DateTime.Now.Year - birthDate.Year} years old!");

app.Run();

Sending the following request will throw a BadHttpRequestException since the required name parameter is not provided in the route or query string.

curl "http://localhost:5056/hello"
Microsoft.AspNetCore.Http.BadHttpRequestException: Required parameter "string name" was not provided from route or query string.
   ....
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

Similarly, sending a request to the /age endpoint with an unparsable birthDate value will throw an exception.

curl "http://localhost:5056/age?birthDate=invalidDate"
Microsoft.AspNetCore.Http.BadHttpRequestException: Failed to bind parameter "DateTime birthDate" from "invalidDate".
   ...
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

ASP.NET Core top-level APIs annotated for trim warnings

To help developers understand which features are incompatible with Native AOT, we’ve annotated the main entry points to subsystems that do not work reliably with Native AOT. When these methods are called from an application with Native AOT enabled, developers will get a warning. For example, the following code snippet will produce a warning at the invocation of AddControllers to indicate that this API is not trim-safe.

Native AOT warnings for top-level APIs

Reduced app size with configurable HTTPS support

In Preview 4, we’ve further reduced Native AOT binary size for apps that don’t need HTTPS or HTTP/3 support. This is quite common for apps that run behind a TLS termination proxy (e.g. hosted on Azure).

When you use the new WebApplication.CreateSlimBuilder, by default this functionality won’t be included. It can be re-added by calling builder.WebHost.UseKestrelHttpsConfiguration() or builder.WebHost.UseQuic(), respectively.

As a result of these and other changes, we can update our table from Preview 3:

We ran a simple ASP.NET Core API app in our benchmarking lab to compare the differences in app size, memory use, startup time, and CPU load, published with and without native AOT:

Publish kind Startup time (ms) App size (MB)
Default 169 88.5
Native AOT – Preview 3 34 11.3
Native AOT – Preview 4 32 9.3

Note the 2 MB drop in app size.

You can explore these and more metrics on our public benchmarks dashboard.

Worker Service template updates

The Worker Service templates in ASP.NET Core (available via dotnet new worker) now include support for the --aot flag to enable creating a worker service project with AOT publishing enabled.

dotnet new worker -o WorkerWithAot --aot

The templates have also been updated to leverage the simplified HostApplicationBuilder for configuring the application host.

using WorkerWithAot;

var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<Worker>();

var host = builder.Build();
host.Run();

Additional default services configured in the slim builder

The WebApplication.CreateSlimBuilder API, introduced in .NET 8 Preview 3, initializes the essential features in an app to minimize its deployed size. In .NET 8 Preview 4, we’ve update the SlimBuilder to include the following features for an improved development experience, while still maintaining a total app size below 10 MB.

  • JSON file configuration for appsettings.json and appsettings.{EnvironmentName}.json
  • User secrets configuration
  • Console logging
  • Logging configuration

API template JSON configuration changes

We introduced the new API project template in .NET 8 Preview 3. In Preview 4, projects created with this template using the --aot option, have changed to insert the app’s source-generated JsonSerializationContext into the beginning of the JsonSerializerOptions.TypeInfoResolverChain. The previously generated code used the now-obsolete JsonSerializerOptions.AddContext<T> API and any project created with the Preview 3 version of the template should be updated to call the new API.

You can read more about the new JsonSerializerOptions.TypeInfoResolverChain API in the .NET 8 Preview 4 blog post.

Support for JSON serialization of compiler-generated IAsyncEnumerable<T> unspeakable types

Support for JSON serialization of IAsyncEnumerable<T> implementations implemented by the C# compiler is now supported, opening up their use in ASP.NET Core projects configured to publish native AOT. This is useful in scenarios where your route handler returns the result of calling an API that utilizes IAsyncEnumerable<T> and yield return to asynchonously return an enumeration, e.g. materializing rows from a database query (example).

You can read more about the JSON serializer support for unspeakable types in the .NET 8 Preview 4 blog post.

Authentication and Authorization

Identity API endpoints

We’re excited to introduce MapIdentityApi<TUser>() which is an extension method that adds two new API endpoints (/register and /login). The main goal of the MapIdentityApi is to make it easy for developers to use ASP.NET Core Identity for authentication in JavaScript-based single page apps (SPA) or Blazor apps. Instead of using the default UI provided by ASP.NET Core Identity, which is based on Razor Pages, MapIdentityApi adds JSON API endpoints that are more suitable for SPA apps and non-browser apps.

In addition to user registration and login, the identity API endpoints will support features like two-factor authentication and email verification in upcoming previews. You can find a list of planned features in the issues labeled feature-token-identity on the ASP.NET Core GitHub repository.

The following shows the Program.cs of an ASP.NET Core app that uses MapIdentityApi to enable both opaque bearer token and cookie authentication. To individually enable cookie or token authentication, you can call the existing AddCookie or the new AddBearerToken AuthenticationBuilder extension methods directly. Both are done for you by the AddIdentityApiEndpoints method below:

// usings ... 

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthorization();

builder.Services.AddDbContext<ApplicationDbContext>(
    options => options.UseSqlite(builder.Configuration["ConnectionString"]));

builder.Services.AddIdentityApiEndpoints<IdentityUser>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

var app = builder.Build();

app.MapGroup("/identity").MapIdentityApi<IdentityUser>();

app.MapGet("/requires-auth", (ClaimsPrincipal user) => $"Hello, {user.Identity?.Name}!").RequireAuthorization();

app.Run();

// public class ApplicationDbContext : IdentityDbContext<IdentityUser> ...

On the client, you can call the /register endpoint as follows assuming httpClient, username and password are already initialized in a .NET console app:

// Email confirmation will be added later.
// The request body is: { "username": "<username>", "password": "<password>" }
await httpClient.PostAsJsonAsync("/identity/register", new { username, password });

And you can sign in and get an opaque bearer token using the /login endpoint:

// 2fa flow will be added later.
// The request body is: { "username": "<username>", "password": "<password>" }
var loginResponse = await httpClient.PostAsJsonAsync("/identity/login", new { username, password });

// loginResponse is similar to the "Access Token Response" defined in the OAuth 2 spec
// {
//   "token_type": "Bearer",
//   "access_token": "...",
//   "expires_in": 3600
// }
// refresh token is likely to be added later
var loginContent = await loginResponse.Content.ReadFromJsonAsync<JsonElement>();
var accessToken = loginContent.GetProperty("access_token").GetString();

httpClient.DefaultRequestHeaders.Authorization = new("Bearer", accessToken);
Console.WriteLine(await httpClient.GetStringAsync("/requires-auth"));

Or, if you want to get a cookie instead, you can set ?cookieMode=true in the /login query string:

// HttpClientHandler.UseCookies is true by default on supported platforms.
// The request body is: { "username": "<username>", "password": "<password>" }
await httpClient.PostAsJsonAsync("/identity/login?cookieMode=true", new { username, password });

Console.WriteLine(await httpClient.GetStringAsync("/requires-auth"));

We’re looking forward to getting your feedback on our early work to improve the identity experience for SPA and mobile applications.

Improved support for custom authorization policies with IAuthorizationRequirementData

Prior to this preview, adding a parameterized authorization policy to an endpoint required writing a lot of code.

  • Implementing an AuthorizeAttribute for each policy
  • Implementing an AuthorizationPolicyProvider to process a custom policy from a string-based contract
  • Implementing an AuthorizationRequirement for the policy
  • Implementing an AuthorizationHandler for each requirement

A partial implementation of a custom parameterized policy is below. The unabbreviated version contains the complete code.

var builder = WebApplication.CreateBuilder();

builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization();
builder.Services.AddSingleton<IAuthorizationPolicyProvider, MinimumAgePolicyProvider>();
builder.Services.AddSingleton<IAuthorizationHandler, MinimumAgeAuthorizationHandler>();

var app = builder.Build();

app.MapControllers();

app.Run();

[ApiController]
[Route("api/[controller]")]
public class GreetingsController : Controller
{
    [MinimumAgeAuthorize(16)]
    [HttpGet("hello")]
    public string Hello(ClaimsPrincipal user) => $"Hello {(user.Identity?.Name ?? "world")}!";
}

class MinimumAgeAuthorizeAttribute : AuthorizeAttribute { }

class MinimumAgePolicyProvider : IAuthorizationPolicyProvider { }

class MinimumAgeRequirement : IAuthorizationRequirement { }

class MinimumAgeAuthorizationHandler : AuthorizationHandler<MinimumAgeRequirement> { }

This preview introduces the IAuthorizationRequirementData interface which allows the attribute definition to also specify the requirements associated with the authorization policy. By leveraging this change, we can reimplement our custom authorization policy with fewer lines of code. The unabbreviated version contains the complete code.

var builder = WebApplication.CreateBuilder();

builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization();
builder.Services.AddSingleton<IAuthorizationHandler, MinimumAgeAuthorizationHandler>();

var app = builder.Build();

app.MapControllers();

app.Run();

[ApiController]
[Route("api/[controller]")]
public class GreetingsController : Controller
{
    [MinimumAgeAuthorize(16)]
    [HttpGet("hello")]
    public string Hello(ClaimsPrincipal user) => $"Hello {(user.Identity?.Name ?? "world")}!";
}

class MinimumAgeAuthorizeAttribute : AuthorizeAttribute, IAuthorizationRequirement, IAuthorizationRequirementData
{
    public MinimumAgeAuthorizeAttribute(int age) => Age =age;
    public int Age { get; }

    public IEnumerable<IAuthorizationRequirement> GetRequirements()
    {
        yield return this;
    }
}

class MinimumAgeAuthorizationHandler : AuthorizationHandler<MinimumAgeAuthorizeAttribute>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MinimumAgeAuthorizeAttribute requirement) { ... }
}

ASP.NET Core metrics

Metrics are measurements reported over time and are most often used to monitor the health of an app and to generate alerts. For example, a counter that reports failed HTTP requests could be displayed in dashboards or generate alerts when failures pass a threshold.

This preview adds new metrics throughout ASP.NET Core using System.Diagnostics.Metrics. Metrics is a modern API for reporting and collecting information about your apps.

Metrics offers a number of improvements compared to existing event counters:

  • New kinds of measurements with counters, gauges and histograms
  • Powerful reporting with multi-dimensional values
  • Integration into the wider cloud native eco-system by aligning with OpenTelemetry standards

Metrics have been added for ASP.NET Core hosting, Kestrel and SignalR. Expect more APIs across .NET to get metrics in the future.

If you’re interested in trying out metrics, we’ve put together Grafana dashboards that report ASP.NET Core metrics collected by Prometheus. You can get the dashboards at the aspnetcore-grafana repository and import them into your own Grafana environment.

ASP.NET Core Grafana dashboard

Give feedback

We hope you enjoy this preview release of ASP.NET Core in .NET 8. Let us know what you think about these new improvements by filing issues on GitHub.

Thanks for trying out ASP.NET Core!

69 comments

Discussion is closed. Login to edit/delete existing comments.

  • Michael Taylor 6

    I am so disappointed in the ASP.NET Core team these days. .NET 7/8 is all about Blazor and minimal APIs. Outside of MS I don’t see anybody using any of this.

    Blazor is for teams that don’t want to learn a real web-development framework. Angular/React/Vue are the client frameworks for web development. I don’t see any job posts listing Blazor as a desired skill. Web developers are using existing client frameworks like those listed above for client apps and REST APIs (or perhaps GRPC) for server side code. Blazor isn’t viable because nobody is asking for running C# on the client side, there is no benefit. If all you know is C# then maybe but that’s like saying you can use C# in SQL instead of just learning SQL. I really wish the ASP.NET team would stop focusing so much on it and instead provide better support for client-libraries.

    You could argue that is what the minimal API is for. But, again, I don’t see it. I’m not replacing controllers with lambdas defined in program startup code. Lambdas themselves were considered bad once local functions were introduced to the language. The happy medium of endpoint routing is really where things are going but my understanding (I haven’t looked since .NET 6) is that endpoint routing via minimal APIs isn’t viable yet because of DI issues and controllers are too much overhead. I think of CQS here. I want to define an endpoint that contains the route URL and code to handle a single request and the program startup doesn’t require any changes. This is what controllers bring today but what minimal APIs seem like they should solve. Maybe I’m missing some cool new .NET 7/8 feature but until .NET 8 is RTM I can’t upgrade anyway. We do not support .NET STS releases because our apps have to run for years without updates. We haven’t even fully migrated all our apps to .NET 6 yet because there isn’t sufficient value add.

    • Daniel RothMicrosoft employee 27

      Hi Michael. ASP.NET Core attempts to cover pretty much every aspect of web development, so our investments are pretty broad, and our user audience is quite varied. We are investing in Blazor and minimal APIs in part due to larger trends in the web development industry that require a richer frontend development experience and more streamlined backend development. But we’re also investing in many other areas, including new middleware, support for Native AOT, new server protocols, better diagnostics & observability, improved authentication, better integration with JavaScript libraries & tooling, and much more. You can see our full roadmap for .NET 8 at https://aka.ms/aspnet/roadmap. If there are specific issues that you think we should be investing more in, please let us know by opening issues on GitHub and giving a 👍 reaction to the issues you care most about.

    • Ahmed Mohamed Abdel-Razek 3

      i agree with some disagree with others
      Microsoft can afford to focus on more than one area they just choose not to for some reason or another
      most people outside of microsoft dev eco don’t know and don’t care what microsoft do and blazor not trendy enough for them to ask for just blazor devs like asking for reactjs or angular devs they don’t want to write c# or can’t and don’t care
      but for people like me that refuse to write javascript blazor is awesome and i don’t think blazor was made for them in the first place or to replace js spa it was made for people like me backend desktop wpf devs anyway

      also about minimal api and top level statement and such i feel like microsoft saw the meme about print hello world in different languages and they draw the line in the sand and said now we need to fix this we are like one line code python now which add now real value it’s not like some new -student- going to see that and choose c# because “it’s one line easy language” he is going to search online and will not find anything that say c# is “easy” because of this

    • d3c0d3d 28

      Not everyone wants to use trendy frameworks like React/Angular/Vue and many others that have an expiration date due to the evolving nature of the JavaScript API. I firmly believe that there are thousands of C# developers who want to write C# code on the frontend as well, and this is not a new desire, considering that ASP.NET itself was born for this purpose back in the day. I see that Blazor with WebAssembly is the best opportunity Microsoft has ever had to achieve this. I am very satisfied now, especially with the latest updates of Blazor and what’s to come. They are on the right track now, please don’t stop.

    • Phil D 27

      I disagree that Blazor is for teams that don’t want to learn ‘real’ web-development frameworks. I’ve learnt them and have the scars from it. The Javascript ecosystem is a complete mess and has been for over a decade now.

      For folks like myself I’m happy Microsoft is investing it’s time and resources in a productive framework that will be supported for years to come without constantly changing or becoming unsupported. I’ve experienced how unproductive teams are with React and Angular and I think anyone who views those as the only options are going to miss out.

    • Glaser, Thomas 9

      I can understand frustration if there’s not sufficient investment in the areas that affect you, but that’s a lot of claims that aren’t backed up by any data.

      Outside of MS I don’t see anybody using any of this.

      I imagine Microsoft has a lot of telemetry, as well as feedback from their customers, to drive their decision making.

      Blazor is for teams that don’t want to learn a real web-development framework

      What makes them “real” frameworks as opposed to Blazor? Yes, Blazor comes with certain downsides (depends on whether you use Blazor Server or Blazor WASM), which need to be considered before using it. But you can build fully functional, large web applications with it.

      Blazor isn’t viable because nobody is asking for running C# on the client side

      How do you know that? Full-stack web development has become needlessly complicated once server-side rendered applications with no client-side interactivity became a thing of the past. SO many libraries, tools and languages that we need to learn to get productive. Having a single technology stack and language to cover the frontend and backend needs is a nice change.

      If all you know is C# then maybe but that’s like saying you can use C# in SQL instead of just learning SQL.

      But that’s what ORM wrappers are for.. like Entity Framework. It’s already a pretty common practice nowadays. A nice layer of abstraction so we can spend less time dealing with database intricacies. What’s so wrong with having something similar for web development, that takes away the need to build an entire separate stack for the frontend?

      • Michael Taylor 0

        but that’s a lot of claims that aren’t backed up by any data.

        You can google for the data to back what I’m saying. For example take a look at the annual Stack Overflow tech survey.
        – JS developers – 65%
        – C# developers – 28%
        – React.js – 43%
        – Angular – 20%
        – Vue.js – 19%
        – ASP.NET Core – 19%
        – ASP.NET – 15%
        – Angularjs – 9%
        – Blazor – 5%

        Clearly Blazor isn’t popular and this is from usage around the world. Angularjs which was deprecated a decade ago has twice the usage. ASP.NET (MVC I assume) is 3x. Also, check popular job search sites and see how many companies are looking for Blazor experience vs Angular, React, Vue.js. The usage is very, very clear.

        Yes, I understand that if you don’t use a feature then it is frustrating when there are updates. But the ASP.NET team has been overwhelmingly focused on Blazor based upon the posts and code changes to support it. I think there are far more impactful areas to focus on rather than putting so much time into Blazor which does not yet have sufficient demand to warrant it.

        • Daniel RothMicrosoft employee 13

          Hi Michael. It’s certainly true that there are significantly more JavaScript developers than Blazor developers, or really any other type of developer. This really speaks to the success of the web platform as the world’s most popular software development platform, which for many years only supported running JavaScript. Many of the frameworks listed on the StackOverflow survey have been around for over a decade and originated when JavaScript was the only option in browsers. It’s only recently that new web standards like WebAssembly made running anything else in a browser possible.

          We do our best to evolve the .NET platform based on community feedback. We decided to invest in Blazor in part due to the enthusiastic support from the .NET community, and since then Blazor related issues have continued to be some of the most top upvoted (👍) issues in the ASP.NET Core GitHub repo. We released Blazor for the first time a little over three years ago, and it’s now one of the fastest growing parts of the .NET platform. With the new full stack web UI support in .NET 8 we hope that Blazor will prove useful for even more scenarios.

          This doesn’t mean we think frontend JavaScript development with .NET isn’t important too. In addition to building and supporting .NET, Microsoft is also heavily invested in the JavaScript ecosystem with TypeScript, NPM, Visual Studio Code, Playwright, React Native for Windows, etc. Many .NET web devs use JavaScript for their web frontends and we expect them to continue to do so. The new ASP.NET Core Identity endpoints in .NET 8 mentioned in this post provide a better authentication story for apps built using frontend JavaScript frameworks, and we continue to invest in our SPA based templates and JavaScript integration and tooling.

          There are also lots of other areas in ASP.NET Core that we invest in besides Blazor, including servers, protocols, middleware, APIs, gRPC, SignalR, MVC & Razor Pages, SPA integration, worker services, container integration, diagnostics, security, and performance. Blazor is just one part of a much broader web framework that seeks to provide everything you need to build modern web apps from the frontend to the backend. We’re always looking to make ASP.NET Core better, so if you have ideas on areas that need improvement we of course would love to hear about them. Let us know on GitHub!

        • Stilgar Naib 4

          You think 5% of devs in the world using certain technology is not popular? Lol…

          • Ahmed Mohamed Abdel-Razek 0

            5% is not nothing and popular is relative term it might be a lot of people but mean nothing in the grand job market
            bing is like 3% everybody heard of bing millions use it would you say it’s popular
            edge is like 5% almost every windows device have it would you say it’s popular
            linux is like 3% on the desktop

          • Stilgar Naib 1

            5% is the opposite of nothing, it means it is insanely popular, has like a million users and is used in thousands of projects, certainly means you can get a job working with it and means the company that develops it can break even.

        • Marian F 5

          Man, I remember a time when it seemed like all job listings wanted Angular, now Blazor is already 1/4 of its adoption. You’re not thinking in perspective. JS frameworks gained popularity only because people were stuck with JS. Now we have Web Assembly and we can write in any language we want, so if you think about the share each language will get in a few years, you can imagine how small each percentage will be. It’s clear WASM is the future, and people actually want to write in whatever language they want. So no, the “real” web is not one where there’s only JS. That is a long gone time (thankfully). We can now write in better-designed languages and we love it. So if you’re actually thinking a few years ahead, and imagining like 50 new different frameworks in 20 programming languages, then the 5% head-start Blazor has seems pretty cool actually. It’s even a big number when compared to Angular or Vue which are only decreasing in popularity, but let’s stop comparing it with JS frameworks. It’s a relatively new framework competing with already old ones (again established in a time when there was no competition and no actual alternatives). But most of all, who cares what it’s share is today, when there are lots of people (including me) who use it since day 1, and wouldn’t even dream of returning to JS. And the number is only growing as people actually using it see how helpful it is right now, not to mention it’s huge potential and lots of cool things coming.

        • Sergey Ivanov 1

          The demand in technology is driven by developers and not by businesses. Businesses simply hire what’s easier to hire. There are more JS devs because the threshold was low to get in and browsers are everywhere. Things can change. Especially if more devs turn away from JS. WASM is a new tech that didn’t get much traction yet and browsers update their spec for it as we speak.

    • Ibro . 20

      “Blazor is for teams that don’t want to learn a real web-development framework. Angular/React/Vue are the client frameworks for web development. I don’t see any job posts listing Blazor as a desired skill. Web developers are using existing client frameworks like those listed above for client apps and REST APIs (or perhaps GRPC) for server side code. Blazor isn’t viable because nobody is asking for running C# on the client side, there is no benefit.”

      Let me express a completely different viewpoint here.

      I don’t share the same sentiment. I used AngularJS several years ago, learned React, and even explored the new Angular version. I have utilized them in multiple projects.

      Blazor is the preferred choice for me and my team. We have no desire to develop applications with Angular or React; instead, we want to leverage Blazor.

      Moreover, I have come across job postings specifically looking for Blazor skills. While the number might not be as high as those for React, I have seen job listings seeking Blazor expertise.

      I have been experimenting with Blazor for years, and over the last two years, I have used it extensively on real projects (not just side projects). Given the choice, I would never go back to Angular or React.

      I do hope that the ASP.NET team continues to enhance both Blazor Server and Blazor Client, as I thoroughly enjoy developing applications with Blazor.

    • J. Kramer 1

      SQL?

      LINQ!

    • Hamed 6

      I think dotnet and asp is on the right track: simplifying developer experience and improving performance.
      The minimal api is not suitable for all scenarios, but it simplifies many enterprise ones. For example, we have used it a lot in our new microservice codebases along with other dotnet new features since last year.
      Blazor has a much bigger story, it’s planned to fill an area that previously was filled by js/jQuery/angular/react… and that’s a potential source of complexity, where two different env needs to talk to each other. Another example is SQL and C#, where EF handles most of the complexity, but frontend lacks such a tool and has been a place that things may begin to become complex, especially if you don’t mind your code structure carefully. And that’s where Blazor is aimed to fill. It needs more time to be adapted by wide range of developers, but if it will become feature rich enough, it will be a bold change.

    • Stilgar Naib 4

      I am asking them to work on Blazor (though admittedly I find minimal APIs completely useless), and yes, I don’t want to use the popular client frameworks, I’d rather not do programming than work with those full time, I’d rather herd sheep or something. Besides that I don’t know what you want from the ASP.NET team. They don’t own Angular, React and Vue, these libraries have teams that develop them, you should go ask them for features and whatever you need.

    • Ian Marteens 5

      I develop with Angular and Svelte, so I think I already know “a real web-development framework”. Svelte is great, but when the decision is on my side, I wouldn’t touch Angular with a ten-feet pole. Sluggish, unnecessarily complicated, full of vulnerabilities, and plagued by a very opinionated design.

      Blazor is a gust of fresh air in web side development, and from .NET 6 ahead, is a very mature product. There are enough third-party controls in the market. Is easy to learn, so I can expand my team when I need it. It runs in circles around Angular.

    • John King 0

      Totally agree. asp.net team spend most time on demo api (eg. minimal API) and toy web UI framework(Blazor).
      devs need a way to orginize their rest api and mvc is better than minimal API ,and also need a way for team work instead all the work done by 1 developer.
      and for blazor ,

      1) blazor server now lack of local state support , so every time it lose connection , the entire page need to be refresh, and that’s not acceptable for a form app,
      2) blazor webassembly : the purpose of webassembly is to provide a faster algorithms for javascript for example: video decoding or image manipulate , not for another language to replace javascript . and dynamic object and object proxy is better in javascript than csharp.

      that why that blazor is powerfull but not many company touch it.

      and for NativeAOT ,
      it’s hard to use because now C# and .net is natually in Jit level dynamic(eg. type system and reflection and emit), what if we start by native ,
      if we need a type that work for reflaction, then we need put [ExportType] or resuse the [Serializeable] to the class first (also add a assembly level ). replace “emit” with “Generators” or “Metalama” language.

    • David Taylor 2

      Michael, I for one have never been happier with the ASP.NET Core team. I am more productive than I have been at any point over the past 20 years and enjoying architecting new systems with much of their hard work.

    • Gabe Hudson 2

      Michael Taylor, I couldn’t disagree more. Blazor, with its component model (DRY) and state handling is a revolution in the asp.net development space. I’ve been coding web application (full stack) on many platforms for almost 25 years, and I can say that Blazor is the most innovative platform ASP.NET has seen since webforms (revolutionary for its time).

      Perhaps you have some suggestions on where the team should focus efforts? What are your pain points?

      To your point, if you are ASP.net developer, IMHO, there has not been a large shift on how you develop since 2008 and MVC. This is not to say there haven’t been substantial improvements (Core, RazorPages, Minimal APIs), but from a web developer’s standpoint, these have all been evolutions of the MVC platform. Blazor, on the other hand, is something completely new and refreshing. It really is a great to build with.

      I encourage you to give Blazor a try by building a simple crud app, and I think you will start to see it’s power, elegance, and huge productivity gains. I love MS seems to be returning to the days of building frameworks that empower the developers, so they don’t have to do all the heavy lifting, while at the same time engineering them on the back of ASP.NET, which allows one to modularize and get as low level as needed for their projects. I want to focus on accomplishing my application’s goals and not spend time on low level platform stuff if I don’t have to.

      Thank you ASP.NET/Blazor team! Keep rocking on with improvements. So looking forward to Blazor SS rendering in dotnet 8! I also am glad to hear about improvements in Authentication. Not everyone needs the complexity of identity server and “simple” auth is more complicated than it needs to be today.

    • Radim Vajchr 1

      After 13 years of real web-development, jQuery, AngularJS, React, Vue, Angular 2+, Backbone, Svelte and respective metaframeworks(sveltekit, nextjs, nuxtjs). I’m seriously considering Blazor. With all the new features coming, it seems like a really viable option for a lot of use cases. Real types, good performance, lots of built in stuff.

    • Jon Miller 0

      Client frameworks in general are total hype and completely unnecessary. I will take ASP.NET Web Forms from 2003 over that garbage, or even CGI. Scott whats-his-face did a better job with this stuff 20 years ago.

  • Jon Hilton 0

    Great to see these changes coming through in the preview releases.

    From speaking to lots of developers I know people find Blazor really productive for building web apps, but are often not so taken with the requirement for an open SignalR connection (and are often building apps where WASM isn’t the preferred option).

    The promise of being able to use Blazor’s component model but for server rendered apps opens up a lot of possibilities. Interesting to note similar developments around SSR and client-side rendering hybrid apps happening in React/Svelte circles at the moment as well.

    Congrats to the team for getting these features in the previews early on, so they can be battle-tested prior to the official release.

    Just a small note, there seems to be some missing code in the post, after this line:

    To enable streaming rendering, you’ll first need to add the new Blazor script.

    • Daniel RothMicrosoft employee 0

      Just a small note, there seems to be some missing code in the post

      Ah, thanks for catching that. Should be fixed now.

  • Lee Minh 1

    Dear Mr. Daniel

    I have an idea why we don’t add .NET framework into browsers like Edge, Chrome or Opera so that we are able to program directly use web client WinForm on .Net Framework library instead.
    I know it is possible but right now I see Blazor is doing the same thing but very slow on loading startup page.
    Advantage:
    Developers doen’t need learn new keywords cause it use .NET library.
    WinForm old style for faster developerment web client projects.
    With .Net Framework integrated for those browsers so that don’t need to download DLL . It might very good performance when start the web app.

    Thank you and regards.

    • Stilgar Naib 3

      Yeah, great idea. We already tried that, it was called Silverlight, it was great and Apple banned it so it died.

      • Lee Minh 1

        Silver light is not already integrated. It must download and install by users. Also SilverLight definition is confused to everyone.

  • George Sofianos 1

    I feel there is a breaking change I’m missing or maybe a bug with the MSBuild because my Blazor WASM project is not building any more. It works fine with preview 3.

      • George Sofianos 0

        Hi Daniel, thanks. It looks like someone else reported it with a reproducible open source example so I’ll monitor the issue. Thanks for the release as well!

        • Daniel RothMicrosoft employee 0

          To make sure we’re tracking this appropriately, could you please share the link to the corresponding GitHub issue that you’re monitoring?

          • George Sofianos 0

            Sure, it has been transfered to the razor repository at: https://github.com/dotnet/razor/issues/8718

            It looks like it affects both .NET 7 and .NET 8 preview

          • Daniel RothMicrosoft employee 1

            Thanks. This is an unfortunate regression in the updated SDK. We’re working on getting it addressed.

  • 旭 鲁 1

    Does Blazor SSR now support event binding, Like click event?

    • Daniel RothMicrosoft employee 3

      Not yet, but we’re working right now on enabling interactivity right now. It should become available in one of the upcoming .NET 8 previews.

  • Meshal Saleh 1

    OOB Sass support in Blazor when?

    • Daniel RothMicrosoft employee 3

      Hi Meshal. We don’t have any immediate plans to enable Sass support directly in Blazor, but we are working on making it easier to integrate a JavaScript based build pipeline into any ASP.NET Core app, including Blazor apps. We should have more to share about that in the months ahead.

  • Stilgar Naib 1

    When doing server-side web the usual pattern for handling forms is POST > Process > Redirect. Can you show how we do the Redirect part in Blazor and even more interesting how will it work if we want the server blazor form to be replaced on second load by blazor wasm when using auto mode.

    • Daniel RothMicrosoft employee 1

      Hi Stilgar. Great question! You can redirect using the NavigationManager by calling its NavigateTo method. If this executes during server-side rendering it will become a 302. If the app has already started streaming rendering, then calling NavigateTo will send a special fragment to the browser that tells the Blazor JavaScript code to update location.href.

      • Stilgar Naib 0

        That’s great, sounds like it is completely transparent, I was scared that I’d had to add ifs and check where the code is running. The streaming rendering support is unexpected bonus

      • Marian F 0

        I was also trying to wrap my mind around how it would work. Thanks for the crystal clear explanation! I can’t believe how well thought and seamless this all Blazor “United” already proves to be!

  • Julio Casal 1

    This is awesome, can’t wait to try the new Identity API endpoints!

  • Jiří Zídek 0

    Anything helping with OAuth2/OIDC in web and in desktop apps as well is greatly appreciated ! MSAL is awful.

    • Den DelimarskyMicrosoft employee 0

      Hey – thanks so much for the note. I am a PM on the MSAL team and would be curious to know what the issues are that you ran into with MSAL so that we can continuously improve the library.

  • Kumima Z 0

    Does the Streaming Rendering Demo really demonstrate how it works? Since the behavior is the same as before without Streaming Rendering. The demo works because it will call StateHasChanged when meet the first async task during OnInitializedAsync You can realize the same effect with .NET7. Please tell me if I’m wrong or provide another demo.

    • Daniel RothMicrosoft employee 0

      Hi Kumima. The big difference with streaming rendering from what you can do today with Blazor is that streaming rendering is based on server-side rendering without the need for a stateful WebSocket connection. The UI experience is handled over a single request/response interaction with the server.

      • anonymous 0

        this comment has been deleted.

      • anonymous 0

        this comment has been deleted.

Feedback usabilla icon