ASP.NET Core updates in .NET 6 Preview 7
.NET 6 Preview 7 is now available and includes many great new improvements to ASP.NET Core.
Here’s what’s new in this preview release:
- Parity with existing experiences for minimal APIs
- Added
IResult
implementations for producing common HTTP responses - Support Request, Response and User for minimal actions
- Minimal host and template improvements
- Supply Blazor component parameters from the query string
- Replace the current URI in the browser history from Blazor
- New
DynamicComponent.Instance
property - Blazor streaming interop from JavaScript to .NET
- Large file upload & faster file uploads with Blazor
- Modify HTML
<head>
content from Blazor components - Support for the
multiple
attribute on<select>
elements in Blazor - Support for HTTP/3 in Kestrel
- QUIC support moved to the shared framework
- Allow control over
Activity
creation - Support for non-ASCII characters in Kestrel response headers
- Add W3CLogger
- Add authentication expiration option to SignalR
Get started
To get started with ASP.NET Core in .NET 6 Preview 7, install the .NET 6 SDK.
If you’re on Windows using Visual Studio, install the latest preview of Visual Studio 2022. .NET 6 will be supported in a future public release of Visual Studio 2022 for Mac.
To get setup with .NET MAUI & Blazor for cross-platform native apps, see the latest instructions in the .NET MAUI getting started guide. Be sure to also check out the Announcing .NET MAUI Preview 7 blog post for all the details on what’s new in .NET MAUI in this release.
To install the latest .NET WebAssembly tools for ahead-of-time (AOT) compilation and runtime relinking, uninstall the earlier microsoft-net-sdk-blazorwebassembly-aot
workload and install the new wasm-tools
workload by running the following commands from an elevated command prompt:
dotnet workload uninstall microsoft-net-sdk-blazorwebassembly-aot
dotnet workload install wasm-tools
Upgrade an existing project
To upgrade an existing ASP.NET Core app from .NET 6 Preview 6 to .NET 6 Preview 7:
- Update all Microsoft.AspNetCore.* package references to
6.0.0-preview.7.*
. - Update all Microsoft.Extensions.* package references to
6.0.0-preview.7.*
.
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.
See the full list of breaking changes in ASP.NET Core for .NET 6.
What’s new with minimal APIs?
Since we announced minimal APIs in .NET 6 Preview 4 we’ve been focused on enabling a more robust set of features. For .NET 6 Preview 7 we’re happy to announce that we’re lighting up more of your favorite ASP.NET experiences with a minimal twist. Let’s take a look at what you can expect.
Parity with existing experiences
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:
Added IResult
implementations for producing common HTTP responses
In earlier previews, we extended IActionResult
implementations from MVC to support the new IResult
type introduced for minimal APIs. In this release, we’ve removed the dependency between IActionResult
and IResult
and added a new static Results
utility class for producing common HTTP responses. Here’s an example:
app.MapPut("/todos/{id}", async (TodoDbContext db, int id, Todo todo) =>
{
if (id != todo.Id)
{
return Results.BadRequest();
}
if (!await db.Todos.AnyAsync(x => x.Id == id))
{
return Results.NotFound();
}
db.Update(todo);
await db.SaveChangesAsync();
return Results.Ok();
});
Thank you Juan Barahona for contributing these IResult
implementations!
Support Request, Response and User for minimal actions
In this preview, we added support for binding HttpRequest
, HttpResponse
and ClaimsPrincipal
parameters in minimal actions. These parameters come from the Request
, Response
and User
properties on HttpContext
respectively. This is in addition to the pre-existing support for binding the HttpContext
directly and a CancellationToken
from HttpContext.RequestAborted
.
The example below accepts the current user directly into the request handler method.
app.MapGet("/api/items", async (ITodoService service, ClaimsPrincipal user) =>
{
return await service.GetListAsync(user.GetUserId());
})
.RequireAuthorization();
Thank you Martin Costello for contributing this feature!
Minimal host and template improvements
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’re extending these changes to the other ASP.NET Core project templates.
For example, when you create a new ASP.NET Core Web API using the template you’ll now notice the following:
- No
Startup.cs
- Leveraging implicit
usings
- New hosting model using
WebApplication.CreateBuilder
- Top-level statements in
Program.cs
(no namespace, class, or method declarations) - Nullable reference types
These changes reduce the amount of boilerplate code required to configure and start a new app. Note that the existing hosting model and Startup
pattern will continue to be supported for existing apps.
ASP.NET Core Web API in .NET 5
ASP.NET Core Web API in .NET 6
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new() { Title = "WebApplication22", Version = "v1" });
});
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "WebApplication22 v1"));
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Check out the the .NET blog for more details on how we’re modernizing the project templates that ship with the .NET SDK.
Note about implicit using statements: Based on early feedback during implementation, changes to the implicit usings feature are being made as part of the next release, including the requirement to opt-in to implicit
usings
in the project file, rather than them being included by default based on the project targeting .NET 6. This will ensure they don’t impact existing projects being migrated to .NET 6 until the author is ready to enable the feature.
Supply Blazor component parameters from the query string
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 [SupplyParameterFromQuery]
attribute in addition to the normal [Parameter]
attribute:
@page "/search"
<h1>Search</h1>
<p>Filter: @Filter</p>
<p>Page: @Page</p>
<p>Assignees:</p>
<ul>
@foreach (var assignee in Assignees)
{
<li>@assignee</li>
}
</ul>
@code {
// Handles URL patterns like /search?filter=some+stuff&page=3&assignee=Monica&assignee=Chandler
[Parameter]
[SupplyParameterFromQuery]
public string Filter { get; set; }
[Parameter]
[SupplyParameterFromQuery]
public int? Page { get; set; }
[Parameter]
[SupplyParameterFromQuery(Name = "assignee")]
public string[] Assignees { get; set; }
}
Component parameters supplied from the query string may be of the following types:
String
,bool
,DateTime
,decimal
,double
,float
,Guid
,int
,long
.- Nullable variants of the above types (except
string
– not applicable). - Arrays of the above types, nullable or not.
Replace the current URI in the browser history from Blazor
When calling NavigationManager.NavigateTo
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 true
for the new replace
parameter:
@NavigationManager.NavigateTo("Other", replace: true)
New DynamicComponent.Instance
property
DynamicComponent
now has an Instance
property that provides a convenient way to get access to the dynamically created component instance:
<DynamicComponent Type="typeof(MyComponent)" @ref="dc" />
<button @onclick="Refresh">Refresh</button>
@code {
DynamicComponent dc;
Task Refresh()
{
return (dc.Instance as IRefreshable)?.Refresh();
}
}
Blazor streaming interop from JavaScript to .NET
Blazor now supports streaming data directly from JavaScript to .NET. Streams are requested using the new IJSStreamReference
interface:
JavaScript
function jsToDotNetStreamReturnValue() {
return new Uint8Array(10000000);
}
C#
var dataReference = await JSRuntime.InvokeAsync<IJSStreamReference>("jsToDotNetStreamReturnValue");
using var dataReferenceStream = await dataReference.OpenReadStreamAsync(maxAllowedSize: 10_000_000);
// Write JS Stream to disk
var outputPath = Path.Combine(Path.GetTempPath(), "file.txt");
using var outputFileStream = File.OpenWrite(outputPath);
await dataReferenceStream.CopyToAsync(outputFileStream);
Large file upload & faster file uploads with Blazor
Using the new Blazor streaming interop support mentioned above, we now support uploading files larger than 2GB using the InputFile
component. The updated InputFile
component is also much more efficient at uploading files thanks to native byte[]
streaming, which avoids expensive Base64 encoding.
Modify HTML <head>
content from Blazor components
Blazor now has built-in support for modifying HTML <head>
element content from components, including setting the <title>
and adding <meta>
elements.
To specify the page’s title from a component, use the new PageTitle
component. The HeadContent
component can be used to render other content to the <head>
.
<PageTitle>@title</PageTitle>
<HeadContent>
<meta name="description" content="@description">
</HeadContent>
@code {
private string description = "Description set by component";
private string title = "Title set by component";
}
To enable the functionality provided by PageTitle
and HeadContent
, you need to add a HeadOutlet
root component to your application. In Blazor WebAssembly, this can be done by adding the following line in Program.Main
:
builder.RootComponents.Add<HeadOutlet>("head::after");
In Blazor Server, the setup is slightly more involved. In order to support prerendering, the App
root component needs to be rendered before the HeadOutlet
. A convenient way to achieve this is to move most of the content in _Host.cshtml
to _Layout.cshtml
, as shown below.
_Layout.cshtml
@using Microsoft.AspNetCore.Components.Web
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Blazor Server App</title>
<base href="~/" />
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
</head>
<body>
@RenderBody()
<script src="_framework/blazor.server.js"></script>
</body>
</html>
_Host.cshtml
@page "/"
@namespace BlazorServerWeb_CSharp.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
Layout = "_Layout";
}
<component type="typeof(App)" render-mode="ServerPrerendered" />
A future release will include updated Blazor project templates, so performing these changes to enable <head>
modification won’t be necessary for new projects.
Support for the multiple
attribute on <select>
elements in Blazor
If you specify the multiple
attribute in a <select>
elements from a Blazor component, the onchange
event will now supply an array of the selected elements via ChangeEventArgs
. Likewise, array values can be bound to the value
attribute when multiple
is specified.
<p>
Select one or more cars:
<select @onchange="SelectedCarsChanged" multiple>
<option value="audi">Audi</option>
<option value="jeep">Jeep</option>
<option value="opel">Opel</option>
<option value="saab">Saab</option>
<option value="volvo">Volvo</option>
</select>
</p>
<p>
Select one or more cities:
<select @bind="SelectedCities" multiple>
<option value="bal">Baltimore</option>
<option value="la">Los Angeles</option>
<option value="pdx">Portland</option>
<option value="sf">San Francisco</option>
<option value="sea">Seattle</option>
</select>
</p>
@code {
public string[] SelectedCars { get; set; } = new string[] { };
public string[] SelectedCities { get; set; } = new[] { "bal", "sea" };
void SelectedCarsChanged(ChangeEventArgs e)
{
SelectedCars = (string[])e.Value;
}
}
When using <InputSelect>
, the multiple
attribute is inferred if the bound value has an array type.
<EditForm EditContext="@editContext">
Select one or more classifications (Minimum: 2, Maximum: 3):
<InputSelect @bind-Value="starship.SelectedClassification">
<option value="@Classification.Exploration">Exploration</option>
<option value="@Classification.Diplomacy">Diplomacy</option>
<option value="@Classification.Defense">Defense</option>
<option value="@Classification.Research">Research</option>
</InputSelect>
</EditForm>
@code {
private EditContext editContext;
private Starship starship = new();
protected override void OnInitialized()
{
editContext = new(starship);
}
private class Starship
{
[Required, MinLength(2), MaxLength(3)]
public Classification[] SelectedClassification { get; set; } =
new[] { Classification.Diplomacy };
}
private enum Classification { Exploration, Diplomacy, Defense, Research }
}
Preview support for HTTP/3 in Kestrel
Preview 7 introduces early support for HTTP/3 and QUIC in Kestrel to try out and give feedback on.
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.
HTTP/3 and QUIC have a number of benefits compared to older HTTP versions:
- Faster response time of the first request. QUIC and HTTP/3 negotiates the connection in fewer round-trips between the client and the server. The first request reaches the server faster.
- Improved experience when there is connection packet loss. HTTP/2 multiplexes multiple requests via one TCP connection. Packet loss on the connection would affect all requests. This problem is called “head-of-line blocking”. Because QUIC provides native multiplexing, lost packets only impact the requests where data has been lost.
- Supports transitioning between networks. 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’t support network transitions in .NET 6, but we’ll explore adding it in a future .NET release.
To start using HTTP/3, configure the QUIC transport, and modify ListenOptions
to add an HTTP/3 binding. For use with browser-based clients, you’ll also need to enable sending the alt-svc
header.
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseKestrel()
// Set up Quic options
.UseQuic(options =>
{
options.Alpn = "h3-29";
options.IdleTimeout = TimeSpan.FromMinutes(1);
})
.ConfigureKestrel((context, options) =>
{
options.EnableAltSvc = true;
options.Listen(IPAddress.Any, 5001, listenOptions =>
{
// Use Http3
listenOptions.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
listenOptions.UseHttps();
});
});
HTTP/3 is not supported everywhere. See use HTTP/3 with the ASP.NET Core Kestrel web server for information on getting started with HTTP/3 in Kestrel.
QUIC support moved to the shared framework
We’re no longer shipping the Microsoft.AspNetCore.Server.Kestrel.Transport.Quic
package, and are instead including the assembly in the ASP.NET Core shared framework. Customers with a PackageReference
to Microsoft.AspNetCore.Server.Kestrel.Transport.Quic
should remove the PackageReference
from their project.
Allow control over Activity
creation
We’ve added support for DistributedContextPropagator
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 Activity
only if the tracestate
and traceparent
HTTP headers were present on the incoming HTTP request. This made it impossible to support other tracing specifications. It’s now possible to support other distributed tracing specifications by implementing a custom DistributedContextPropagator
and registering it in the DI container.
Support for non-ASCII characters in Kestrel response headers
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 ResponseHeaderEncodingSelector
:
builder.WebHost.ConfigureKestrel(options =>
{
options.ResponseHeaderEncodingSelector = (_) => Encoding.ASCII;
});
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.
Add W3CLogger
ASP.NET Core is now capable of generating server access logs in the W3C Extended Log File Format. To start emitting server access logs, you need to add the logger to DI and add the W3C logging middleware to your middleware pipeline:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddW3CLogging(options =>
{
options.LogDirectory = @"C:\logs";
options.LoggingFields = W3CLoggingFields.Request | W3CLoggingFields.ConnectionInfoFields;
});
var app = builder.Build();
app.UseW3CLogging();
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.MapGet("/", () => "Hello World!");
app.Run();
This will produce a log file that resembles this output:
#Version: 1.0
#Start-Date: 2021-08-10 01:07:40
#Fields: c-ip s-ip s-port cs-method cs-uri-stem cs-uri-query cs-version cs-host cs(User-Agent) cs(Referer)
::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 -
::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/
::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 -
::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 -
::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 -
Add authentication expiration option to SignalR
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 CloseOnAuthenticationExpiration
on HttpConnectionDispatcherOptions
as shown below.
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<MyHub>("/hub", options =>
{
options.CloseOnAuthenticationExpiration = true;
});
});
Give feedback
We hope you enjoy this preview release of ASP.NET Core in .NET 6. We’re eager to hear about your experiences with this release. Let us know what you think by filing issues on GitHub.
Thanks for trying out ASP.NET Core!
83 comments
.NET 6 is looking awesome! Took about 20 minutes to migrate our app to it and then another few minutes to wire up ErrorBoundary and replace our home-grown DynamicComponent. Looking forward to the go-live!!
Awesome, that’s great to hear, Craig! Thanks for trying out the .NET 6 previews.
wasm-tools installation fails.
“Workload installation failed: microsoft.ios.sdk::15.0.100-preview.7182 is not found in NuGet feeds https://api.nuget.org/v3/index.json;C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\”.”
Hi George. Thanks for trying out the new .NET 6 preview! What workload install command are you running exactly? This is a known issue when installing the
maui
workload, but shouldn’t happen with thewasm-tools
workload. To install .NET MAUI, you’ll need to use themaui-check
tool for this preview release.Awesome stuff. .NET 6 is definitely living up to it’s promise
Hi, I have the same error message when i execute “dotnet workload install wasm-tools”
Thanks for reporting this, Walid! Could you please open a GitHub issue for this with details on the specific .NET versions and workloads you have installed so that we can try to reproduce this? https://github.com/dotnet/aspnetcore/issues/new.
One thing you can try to work around this issue is to first make sure you only have the official NuGet feed configured, and then rename your dotnet/metadata folder to something else before trying to install the workload again.
Hi,
I’d like to take my existing Blazor WASM app and publish it as an Android app using .NET MAUI Blazor. Is there any official/unofficial documentation on how to proceed?
Thanks!
Hi Daniel. We don’t have docs for this yet, but basically what you do is move your components into a common Razor class library, and then reference that library from your Blazor WebAssembly app and the .NET MAUI Blazor app. The same components should work in both.
Hi Danial, BlazorWebView looks really promising as a C#-only alternative to Electron, but as of .NET 6 RC1 it has serious keyboard/focus issues, at least on Windows Desktop. It really doesn’t feel usable at this stage: https://github.com/dotnet/maui/issues/2341. Is there a chance it could be fixed for .NET 6 release?
Thanks for reporting this issue! We’ll take a look.
He Daniel,
Seems awesome, any updates on HotReload?
Hi Yasser. Things are starting to come together for .NET Hot Reload in Visual Studio 2022. The experience is only partially implemented in Visual Studio 2022 Preview 3, but expect more .NET Hot Reload updates soon.
Hi Daniel Roth,
Why
[SupplyParameterFromQuery]
instead of just[FromQuery]
?[SupplyParameterFromQuery]
looks weird to read.Hi Tanvir. Thanks for this feedback! It’s tempting to use the existing
[FromQuery]
attribute but problematic because it has dependencies that we don’t want in Blazor and we can’t guarantee that it’s parameters will always make sense for Blazor apps. So we introduced a new attribute with a new name to avoid name collisions with the existing attribute. If you have suggestions for a better name please let us know!Brainstorming a bit,
[QueryStringParameter]
makes sense to me – could be used with or without[Parameter]
:[QueryStringParameter]
without[Parameter]
means it can only come from the query string, stacking them means it could come from either the query string or original[Parameter]
passing.Hello there, just giving some suggestions to name:
[QueryParameter]
[UrlQueryParameter]
[FromUrlQuery]
[BindFromQuery]
[QueryBind]
If you have to write [Parameter] already, why not simply add another not required bool to Parameter?
For example:
[Parameter(fromQuery: true)]
Default is false. No need to learn a new attribute and no conflicts with existing projects
I like this idea.
or
Thanks
I tried “Modify HTML content from Blazor components” and it works, so now I’m trying (for the first time) to modify the head content from regular Blazor WASM pages, but can’t find any info on how to do that except for some 3rd party JS libraries. I’ve searched the Internet and read the previous Dev Blogs ASP.NET Core Updates and I found Influencing the HTML head in Blazor apps ( .NET 5 Preview 8) but that Nuget package isn’t updated anymore. I think I missed something?
Hi J. Kramer. The instructions above should have everything you need to setup modifying the
<head>
contents from a Blazor WebAssembly app. To modify the title use the newPageTitle
component. To modify the head content use theHeadContent
component. To set this up in a Blazor WebAssembly app you need to add theHeadOutlet
component as a root component:builder.RootComponents.Add<HeadOutlet>("head::after");
. We had tried to introduce a mechanism in .NET 5 for modifying the head, but it ended up having issues, so we’re going with a different approach in .NET 6.Thank you for your reply, At first I thought there was different code needed for normal ‘Blazor WASM Pages’ and ‘Blazor WASM Components’. But everything is a component in Blazor. Why it didn’t work in the beginning is because (in my case) I needed to put:
before/above
Ah, good point! The order does matter. Otherwise the PageTitle components don’t have a chance to render before the HeadOutput component tries to add to the HTML head.
Actually, hold on. You’ve got it backwards. You need the order to be like this:
minimal APIs ??
Toy project then Toy language and toy platform future ?
I don’t get why MS is doing this , does it because Azure Function ?
As the community leader , that MS not lead us to better design pattern , better compose pattern , better isolation pattern, better project separation pattern ,
instead, that MS now tech us to use bad design with less code, bad compose pattern with hand writing more code or use template (you have to write your template and with more code) , bad isolation pattern (no asp.net core app’s have a plugin system we use in .net 4.x) , project separation always kick our ass.
And everything is rush to be release :
blazor ? I interesting it as a devloper , and I will never choose it for business , because Angualr/React/Vue is better , and JS is design for web, why we need WASM, because we need fast algorithms for image/video, we do not need a slower WASM for web ! and the normal/right for .net in WASM , is to support library(algorithms) compile to native WASM, and let JS to call it , then develop Blazor to have better intergation for the compiled native WASM .
And there no GPU standard, everyone is pain with the Image /Graphic in .net (I want to thanks for ImageSharp team to bring us CPU image )
There are no WASM compile standard, you can not mapping C# class / method in a library to expose to js runtime.
I feel MS is really rush at something, and really love to create new things (but not better and less pain in the new things ) it’s not innovate , instead , it split us from one big community into smaller community , and that means less nuget package can be use in our scenario (they are not universal for different scenario)
Hi John. Thanks for raising your concerns with us.
The simplifications to API development and ASP.NET Core hosting are to help new users onboard to ASP.NET Core more easily. The existing ASP.NET Core patterns, while still valid, require a significant number of files and lines of code to create even a single endpoints. This additional complexity isn’t needed if you’re just trying to get started or build something simple. The new minimal patterns provide a much easier onramp. But these new patterns also aren’t toys. They offer superior performance and sufficient flexibility to scale up to large app development.
We do our best to encourage best practices needed for the most demanding of workloads, but we also need to balance that with providing sufficient flexibility for a variety of app scenarios. What might be considered good design and factoring for one scenario can also be excessive complexity for a different scenario.
Blazor is all about giving developers the choices to use the languages, tools, and frameworks that work best for them. If you prefer using existing JS frameworks, that’s great! ASP.NET Core works great with existing JS frameworks. But for many developers, being able to use .NET & C# for client web UI development is liberating and empowering. Using Blazor does come with certain tradeoffs, but it is more than sufficient for many scenarios.
I think that’s a valid criticism. There are parts of the .NET ecosystem today that are fragmented, and any new efforts need to be carefully considered to avoid further fragmentation. For the past couple of releases we’ve been working towards a unification strategy (One .NET) to get all of .NET onto a common runtime and set of libraries. ASP.NET Core is built to be a unified web framework. .NET MAUI unifies xplat mobile and desktop scenarios into .NET 6. We’re not there yet, but we’re making progress on multiple fronts.
don’t get me wrong, that your team are doing really good on .net , but in some scenario, you’r doing for simple usage (which may only be used as a demo ). the truth is less is more , you can do some helper methods like the
WebHost.CreateDefaultBuilder
, but then a lots of new developer also do not know what does it do for you. I come from Asp.Net Core 1.0 so I know what it do for me , setup loging, IIS, args etc. but what about new developers ? where do they lean what does it did for you ? after all : Less code is more work/leanand I’m really upset that Asp.Net Core team do not give us a prop way to compose/organize our project. Yes , today many of us start to working micro service, but look at JAVA’s Spring and ABP for .Net, they also service for micro services and they can do single application too , but they give you a really good pattern to organize and share your code/nuget packages ! Do you still know why we create a separated DLL after all those yeas using nuget ? Share and DRY (do not repeat your self) , but can you say asp.net core is doing a good job on this ? ABP organize your code to a shareable module and you can install to your app with 1 simple line code to enable it. and Ask you self , What will you choose [a simple way or a better organize way] to develop your business app/services for your complex company business ? And MVC still have many issue that not been solved and do not provide a good project separate pattern (different area in different project), and your team just goes to blazer anyway.
IMO, the project system need a virtual file system and it should be access-able from code , then we can use it to make it work for develop mode and release mod easier (think about the
wwwroot
folder in different project). the multi-plugin app also can use it to simplify the work to run the plugin.It sounds like this deserves a more in depth conversation than what we can really do in these blog post comments. Do you want to create a GitHub issue to start discussion on this? https://github.com/dotnet/aspnetcore/issues/new.
This is actually the first I’ve heard of ABP, so thanks for brining it to my attention!
https://github.com/dotnet/aspnetcore/issues/35367
Hi Ricardo, I agree with you that it would be great to have “.NET WebAssembly library” project that compiles to native WASM and has debugging support. But what is excellent about Blazor now is that you can reuse existing .NET code, and I appreciate the work done by the Blazor team. One of the most significant limitations is threading support until the WebAssembly threads will be widely adopted.
I think minimal api will be useful in an intranet environment. In my case, I had several independent monitoring systems, each running a client and had to run a server program separately. Imagine how a minimal api could improve this case. and that is i wanted
Very happy to see .Net improving the command line install experience. But most of the users in enterprise will not have admin rights. Is there way to install these workloads without elevated permission?
Workloads for an admin SDK install need to be installed with elevated permissions. Workloads for non-admin SDK installs do not need elevated positions.
Often, admin installs are done via the SDK installer and non-admin installs are done via scripts, although the key thing is that workloads are in the same file location as the SDK and that determines elevation.
In the last couple of months, I’ve developed a couple of internal applications using Blazor mostly as a way to show my colleagues some of the things I like in dotnet. And from my experience, I can tell you a couple of things that I would need to be comfortable using in our products and external projects:
– Better IDE Support. VS Mac is horribly slow, and VsCode simply doesn’t work with Blazor. 99% of the time I have no IntelliSense or the pages show squiggly lines everywhere.
– Better performance (it’s very easy to make mistakes that make the applications very show, and it’s hard and time-consuming to fix it, if at all possible)
– A good component library officially supported by MS, like Angular Material is supported by the angular team. There are a couple of component projects out there, but they are just too young/unstable to be used in large projects/products.
– Better ecosystem. Since blazor is still relatively new, and the community small, the number of packages available is minuscule when comparing with Angular, React, or even Vue.
– Better guidance and realistic example applications using it. The template projects are just too basic, and the pizza delivery apps are not much better.
Don’t get me wrong, I really enjoy Blazor. But it still has ways to go until it can compete with other technologies, and I’m not sure how sure/committed MS is with it (will it be the next SilverLight?)
Hi Ricardo. Thanks for this thoughtful feedback!
Better IDE support for working with Razor is one of our top priorities. Right now we are focused on revamping the Razor editing support in Visual Studio 2022, but the goal is to have consistently good Razor editing across the Visual Studio family of editors.
I’d love to hear more about the performance pit falls your ran into. Would you be willing to file a GitHub issue with some more details? We do have some performance guidance in the Blazor docs. It would be great to verify if the issues you hit are covered in our guidance, or if we could improve the framework to avoid the pitfalls altogether.
We have avoided building our own component library into Blazor because we want to leave space for the community to innovate and instead focus our efforts on improving the framework. There are component library offerings from a variety of component vendors including Telerik, DevExpress, Syncfusion, Infragistics, GrapeCity, and jQWidgets. There are also a variety of free open source offerings including Radzen, MudBlazor, MatBlazor, Blazorise, Blazored, and others.
There are now also Blazor component wrappers for the official Fluent UI web components.
For realistic example apps, can you point me to some examples of sample apps that exhibit the level of complexity and scenarios that you are interested (yes, I did just ask for an example example app 😆).
Hey Mr. Roth and team: I am finally upgrading to Visual Studio 2022 and my Blazor Server-side experience is SO MUCH BETTER! Thank you SO MUCH for putting this all together, as well as putting up with my kicking and screaming over the past several months re: performance and sluggishness in Visual Studio.
It appears all the memory-related problems have been addressed and things are so much better in VS2022. Looking forward to stretching its legs once I get everything upgraded to net6.0.
Speaking of which. 😁 I did try to upgrade a Razor component library to the latest .net6.0 on VS2022 Preview 3.0 and I am getting the following warning:
I wanted to point it out to see if there’s an easy fix and/or if I should report it to a repository somewhere. Thanks again for all your great work out there. You have no idea how much you impact the lives of developers such as myself who dream to build a business on Microsoft technology. 👍
EDIT: I knew I would figure this on my own if I posted something here. 😁 I got the grand idea of searching on GitHub repository and sure enough was reported yesterday: https://github.com/dotnet/aspnetcore/issues/35283
FWIW I fixed that issue but ran into another one. Apparently, there is a very obvious NuGet versioning issue that is keeping Razor projects from being upgraded to Preview 7. I am surprised that I haven’t seen anything mentioned here in the comments about this yet:
https://github.com/dotnet/aspnetcore/issues/35300#issuecomment-897877459
Hi Mike-E. Thanks for kicking the tires with Visual Studio 2022. It’s great to hear that things are working better! Hopefully we’ll get https://github.com/dotnet/aspnetcore/issues/35300 resolved soon. Sorry about the frustration!