-
Notifications
You must be signed in to change notification settings - Fork 10k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ASP.NET Core Roadmap for .NET 9 #51834
Comments
Ability to run multiple Blazor server / Web assembly apps in the same document (micro-frontends) |
Add validator for Minimal APIs can be great! Something like this: |
I would love to see the ASP.NET session state provider work with InteractiveServer components in Blazor Web so we can share session state across RenderMode boundaries. |
I would like to be able to specify a "Static" RenderMode for a Blazor component/page. This is usefull when a global (higher level) RenderMode has been set to InteractiveServer. |
Do you mean that you don't want any interactivity for that specific component in an otherwise interactive component tree? What benefits or value would that bring to you? |
That would require to load multiple .NET runtimes within the browser or on the server. The server scenario seems more realistic. I just can't see how you could even make this a great developer experience. You are already able to host multiple components on a page, provided that they are in the same app. |
@thisisnabi We're discussing adding data annotations validation support to minimal APIs (via filters): #46349. For fluent validation, there are much better implementations (e.g.): |
Fair question; let me elaborate. This need has been requested frequently in the community as we are upgrading "classic" Blazor apps to the dotnet 8 "Blazor Web" model. There are several reasons one would want to do this, but the most pervasive today is when one has a Blazor Web application that is primarily an SPA, so one sets "global" interactivity (typically on the Routes component, as in the MS templates), but needs certain pages to render statically. A good example of this would be the authentication pages, which require access to the HttpContext, need to be static. This cannot currently be achieved (in a "global" interactive app) without having to intercept a path from the HttpContext in app.razor and setting the RenderMode based on the path. In fact, this "hack" is what is being used to force the authentication pages to render statically in the MS Blazor Web Global Interactive Sever template. There are many other scenarios where one would need to "overwrite" a "global RenderMode" to static. This is important now, because most UI libraries are currently incompatible with the SSR Blazor modes, and porting applications to the Blazor Web model typically requires one to set a global interactive RenderMode for them to continue to function. We would, however, like an easier way to set pages to uses the static mode in these scenarios. To your point, I think this is much more useful on a per page level component. Please see this GitHub issue from Daniel Roth... Hopefully this makes it into 9 (or sooner). I think it will really help porting applications and was surprised to find it wasn't included currently. :) |
@gabephudson Thanks for clarifying. I agree with you on the problems expressed. Static rendering did break a lot for me. I have been using MudBlazor, and this library is relying on interactivity, and doesn't work well with SSR. It is OK when you understand the problem and how to solve it. But I think that devs who are not into the mechanics of Blazor would get frustrated. The SSR story needs to be finished. And it in involves giving guidance to component library authors. |
Give us crystal clear answer if mvc will support aot or not |
Removal of jQuery (maybe bootstrap as well) and revamp of default templates for ASP.NET Core MVC |
Make full support for native aot would be nice |
Native AOT across the board! |
I read a lot of requests about making AOT available for the entire framework. MVC relies heavily on reflection so it is impossible to at least handle every case. Perhaps a source generator could take you a bit farther but there still are considerations, like with Minimal Endpoints. Perhaps this is something that has to be clarified. What the possible limitations would be. |
Facilitate porting from MVC and Endpoints. I have been porting from MVC controllers to Minimal API endpoints. It is a tedious process. Especially with many controllers and actions. Not forgetting that routing and so is slightly different. I have identified these points:
Not for me: There are requests for AOT in MVC too. But as I understand there are limitations. Giving devs a migration path would solve that. I also realize that custom MVC Filters is a potential problem when doing AOT. Especially if there is reflection involved. Types might get trimmed away. |
I'd love to see clarification on what the "modern web stack" is. If I were to create a greenfield Web API today, I'm assuming Minimal APIs are the way forward; If it weren't for backwards compat, would you have removed Controllers in Asp.Net Core 8¹, or is there still a reason for their continued existence? Same goes with Web Apps - I've seen some statements on the Blazor topic in particular (#50999 (comment)), but that's just some guy ², and even then it's only a recommendation. I've yet to see anything equivalent in the API world. ¹ The reason I say Asp.Net Core 8 is the fact that (I think) it added the last feature that was missing - forms - but I'm sure there are other minor features missing as well. ² I realize that he's the product manager for Blazor, but I can't tell my team to stop using MVC simply by pointing to a random comment in a GitHub issue - no matter how important the author is. |
I have to echo the need for fine-grained interactivity. A constant problem we're facing is we have components that really should only function client-side, like trigger a menu or something, and with ServerInteractive each one of these requires a roundtrip to the server. Switching them to WASM is not possible because then that entire page has to be WASM, and we simply don't have any pages that have zero interactivity. The other option is to forget about server interactivity and do the whole thing in WASM. But then we have to introduce Controllers/Minimal-Endpoints and manage those. One of the huge benefits of server interactivity is no longer needing to manage endpoints. And also if a button calls a function I can cmd+click that function and go directly to the code. Full WASM breaks all of that. Another issue is that the SignalR connection is simply not that reliable. Chrome shuts it off in the background, iOS shuts it off in the background. We constantly have to deal with the Server Reconnect screen. We can hide it, but then we have issues with a random button that's supposed to toggle a menu not working when really that doesn't even truly need a server roundtrip. |
Would love to know when the page is prerendering so we don't run database calls twice. Such an oversight with the way blazor works. |
@KonnectSalon Yes. That is probably something that you want out of the box: Knowing where and how the component is being rendered. However, I solve it with this simple service: There is a Client version, of course. |
The SignalR client source generator needs to be officially released. Also, we need to investigate what to do on server-side. Given the strongly-typed Hub Client interface: public interface ITodosClient
{
Task TodoCreated(TodoDto todo);
} This is what I currently do on server-side: public sealed class TodosClient(IHubContext<TodosHub, ITodosClient> hubContext) : ITodosClient
{
public async Task TodoCreated(TodoDto todo)
{
await hubContext.Clients.All.TodoCreated(todo);
}
} public sealed class TodoCreatedHandler(
ITodoRepository todoRepository, ITodosClient todosClient) : IDomainEventHandler<TodoCreated>
{
public async Task Handle(TodoCreated notification, CancellationToken cancellationToken)
{
var todo = await todoRepository.FindByIdAsync(notification.TodoId, cancellationToken);
if (todo is null)
{
throw new Exception();
}
await todosClient.TodoCreated(todo.ToDto());
}
} Although this is trivial to implement, I would suggest a source gen for this, but that would ignore the fact that you need to able to control what clients or groups will receive the call. You could perhaps control some of this through additional attributes. But is most likely not worth the effort. At least, there should be guidance on this. |
On InteractiveServer, I would love to see In Blazor InterctiveServer, a scoped service is tied to the user's SignalR lifetime. This causes grief for libraries like EFCore, where one often wants it tied to the razor page's (component) lifecycle, not SignalR. The result is a factory with extra code, extra disposal calls, and it feels only natural that DI could handle this a lot better with the right scope. |
@KennethHoff Blazor is now our recommended approach for building web UI with ASP.NET Core, but neither MVC nor Razor Pages are now obsolete. Both MVC & Razor Pages are mature, fully supported, and widely used frameworks that we plan to support for the foreseeable future. There is also no requirement or guidance to migrate existing MVC or Razor Pages apps to Blazor. For existing, well-established MVC-based projects, continuing to develop with MVC is a perfectly valid and reasonable approach. If you want to use Blazor components in your MVC or Razor Pages apps there are various approach to doing so. |
Thanks everyone for sharing your feedback so far on the ASP.NET Core Roadmap for .NET 9 (in spite of it being completely empty currently 😆). More details on the proposed roadmap will be coming soon! A couple of tips to make this discussion as productive as possible:
Thanks again for helping out with the .NET 9 release! Your feedback and insights are critical to ensure we keep moving web development with .NET forward in the best possible way. |
@gabephudson Could you please open a GitHub issue to propose this new functionality and provide details on your scenarios and requirements for this feature? |
@marinasundstrom It would be great if you could share what you see as the remaining work here! We're trying to make sure any remaining gaps in the Blazor state SSR support are tracked and prioritized.
I 100% agree we need to do a better job at providing guidance for component library authoring. I've opened dotnet/AspNetCore.Docs#31591 to track this. |
@KonnectSalon I believe this is tracked by #49401. |
@ssnseawolf You should probably open a GitHub issue to propose this API and clarify what you expect it to do and why.
@ssnseawolf Blazor does provide a number of DI utility features to help manage interactions with EF Core. If you haven't already, please take a look at the related docs and see if it helps: https://learn.microsoft.com/aspnet/core/blazor/fundamentals/dependency-injection#utility-base-component-classes-to-manage-a-di-scope |
@Johnhersh We are tracking a number of issues related to this problem with interactive server rendering connectivity management that you can express your support for: |
@marinasundstrom You might be able to automatic this by writing a .NET Upgrade Assistant extension. |
@sajjadarashhh @andrew-vdb @cindro We expect to make progress investigating Native AOT support for MVC & Blazor in the .NET 9 timeframe, but we don't expect to deliver production ready Native AOT support for .NET 9 given the large amount of work involved. Related issues: |
In this issue i described a simpler way to communicate with js in blazor projects |
Thanks for this, I upvoted those issues. I'm not sure if I'm maybe not asking the correct question. But I'm confused about why this is an issue at all. Making a web app in something like React you rely on http requests. Those have high reliability. From what I read though SignalR has an http request and long polling fallback. So I guess what I'm asking is for access to that, and I don't see a ticket that mentions this. But I'm probably misunderstanding this whole situation as I'm not too familiar with SignalR's internals, or why that mechanism was picked for Blazor instead of regular http calls. |
@marinasundstrom +1 to your proposal about analyzers/codefixers to aid with the migration process. Out of curiosity, with regard to grouping, do you find that route groups in minimal APIs are an insufficient alternative? |
@Johnhersh, this SignalR (websockets) connection only occurs in components that are configured as "InteractiveServer". In this mode, the shadow DOM is represented on the server, and changes are communicated in real-time to the browser. This requires a high-speed, low latency communication channel and uses websockets for this. While having some down sides (primary are the app must have a consistent internet connection and additional server resources), it is a dream for developers who can have all the interactivity of a SPA without the overhead of multiple sets of states and the need to create APIs for all server access. There is a fall-back mode that uses HTTPRequest (long polling), but it is extremely slow due to the amount of communication that occurs with the server (creates a lot of latency due to the multiple requests). The also have a server side render mode (which is kind of like Next.js) and InterActiveWebAssembly, which keeps the DOM on the browser. It allows one to code in C# instead of JS and it is the most similar to React.js. In WASM mode, you would use APIs and HTTPRequest in a very similar way to React to modify server state (DB). https://learn.microsoft.com/en-us/aspnet/core/blazor/components/render-modes?view=aspnetcore-8.0 The good news is with Blazor 8, we can choose the mode that works best for you and your situation on a per page and per component level. IMHO, it is a fantastic framework for building web apps. My client facing applications typically only have concurrent user counts in the thousands, so InteractiveServer mode in Blazor allows our team to be extremely productive. We don't see many issues with SignalR. Unlike a traditional web app, however, if you lose internet connection momentarily, there is a pop-up (connecting...) that will display (where a tradition web app would only show if the user was actively communicating to the sever at the time). If the user loses connection for more than a minute or so, then the websocket circuit will drop and they will (typically) be forced to re-login once they regain their connection. This is typically only an issue for mobile users. If you have an extremely high volume user count or primarily mobile users, this rendermode may not be the best choice for your application. |
My above comment got me thinking of an idea for Blazor 9 InteractiveServer. Perhaps if the user loses their internet connection momentarily, (less than 10-15 secs) or so, we can have the option to NOT display the "attempting connection" pop-up unless they actually try to interact? This might be a slightly better experience for users with a spotty connection. Obviously after a certain amount of time, the circuit will drop, and then the dialog can be displayed). So if connection drops and...
This may already be custom behavior we can code. I haven't looked in to it. |
@gabephudson Thank you for this thoughtful response!
This is a huge problem for my team. We've compared it to NextJS and the fact that all interactions there happen via regular http requests mean the consistent connection requirement is a non-issue. In addition users are already used to having wait times when pressing buttons, so this flow feels natural. But the entire site shutting down is extremely odd. From a DX perspective when the team saw that this is a layer we'll have to manage somehow it became a major point against it. There are other tickets here for this, but the web socket connection gets dropped on mobile and in chrome in the background. The entire site is not usable unless there's a connection. From a UX perspective the entire site not working until a reconnect happens is just really bad. And if they've been away long enough it's a complete page refresh which could also mean losing unsaved work in our case.
This is very true and why I was advocating for it. Plus the extra advantage of not having to manage endpoints (though Next does this via tRPC).
The WASM stuff is also problematic. If a component on a page needs interactivity then the page needs to be interactive. This means if I have a page where one button calls some function on the server, and another button just opens a dialog on the frontend, both of those require a server roundtrip. I couldn't find a way to have a WASM page, but with a server-interactive button for example. So this means if connectivity is dropped, then even stuff that only happens on the frontend still requires a server roundtrip and is therefore blocked.
This is a huge problem for us. Blocking the entire web app is not something any other framework forces on you. What I'm still very unclear on is why can't interactivity happen via regular http requests? I don't quite get why web sockets have to be the only transport. I'm not talking about http long polling. I mean whatever message is sent via SignalR to the backend is surely also able to be sent via a regular http request? If we had that feature then all these problems go away.
We do have a lot of mobile users. We can try making the entire app in pure WASM. But then we lose all of the advantages of Blazor as you've outlined above, and they're great advantages. In the end building it in Next meant the same architecture works across the board, and with tRPC (the t3 stack) we get similar advantages. I do think Blazor come out ahead in theory, but this websocket topic kills the whole thing for us unfortunately. |
This would indeed be a major step forward. I would like it per-component even so I could disable and grey out buttons while interactivity is down. However, what I think will solve this entirely is if there's no connectivity then it should be able to send the exact same message just via an http request instead. |
If there is no connectivity, the HTTPRequest will fail as well. :) As far as Chrome shutting down websockets, I have heard about this behavior, but haven't seen this issue on our InteractiveServer application. Perhaps Blazor/Signal R has enough traffic (even when not interacting) that the browser will keep it open? (Again, can't speak for what may happen if your phone goes to sleep and you re-awaken it). I think there are tradeoffs with any framework, but Blazor currently offers 3 different modes you can mix and match (typically at a page level, but also per component) depending on your needs. Maybe stating the obvious, but you have the following... Server Side Interactive Server - This is the mode we use. It allows full interactivity while also not needing APIs. It requires a persistent internet connection while app is in use and, while I don't work for MS and the engineering team, I don't believe an HTTPRequest model would be performant enough for the server-side shadow DOM model it uses. Perhaps in the future we would see an HTMX like mode added to compliment SSR mode above? Client Side |
I don't disagree with most of what you say 🙂 I love Blazor and think it has the potential to really streamline my workflow. But some things are not quite accurate.
This is not true. You're taking it as if the device doesn't have access to the internet. But that's not the issue, the issue is the browser terminating the web socket connection. On mobile you're guaranteed to have this happen if the screen is turned off or someone minimizes the browser. On Chrome there are tons of thread on stackoverflow (regardless of SignalR, just websockets in general) where it shuts down websocket connection after the tab being in the background for X amount of time. In our app we open multiple tabs so this is extremely likely. In both of those situations, if the websocket connection would have closed from being in the background, a regular http request would have worked just fine. The device hasn't lost connectivity. This is not mentioning how chatty web sockets are. If my app opens multiple tabs (which we do) that's a websocket connection for each tab. Eventually the browser will cleverly shut the connection. But then a full refresh is needed. This is also wasted bandwidth. And the final issue is that when these disconnects inevitably happen, it's also likely the server will terminate the circuit. So then you have a situation where our customer will return to the tab, find a screen saying there's no connection (because Chrome shut it down), try and reconnect for X seconds just to find that the server shut the circuit, then force the user to refresh the page anyway. This is terrible UX I'm afraid.
I would absolutely love this 🙂 All the advantages |
No worries. I hear you. Certainly, the fact that mobile devices close a websocket connection is very problematic. Short term fix is to increase the circuit timeout in your app (which will consume more server resources). It will be interesting to see if the team can come up with some new ways of communication to mitigate this. Interestingly enough, I did test this on my Android phone. If I power off the screen on my phone, as long as I'm back in a minute or two, the app just works. Did a 6-minute test and the app did the "reconnecting" but then worked fine after a few seconds. After 15 minutes, I lost the circuit and had to refresh the page. YMMV. |
Thanks for all the feedback here, everyone. We're finalizing our plans for .NET 9 already, so I'm going to lock this issue. Feel free to continue the discussion at #53665 |
This issue represents the list of major investments our team will focus on during the .NET 9 timeframe. It doesn't include all the features and bug fixes we'll be tackling during this time.
Note that this is an aspirational list of what we hope to get to. Many of these items will require thorough investigation and design, which can result in changes to our plans. We'll end up cutting some things and making changes as we go, but we'll try to keep this issue up to date to reflect on our progress and learnings.
There's a lot to discuss in the ASP.NET Core roadmap, and GitHub issue comments aren't great for multi-topic conversations, so we've set up the ASP.NET Core Roadmap for .NET 9 discussion to better handle these threaded conversations.
You can best express your support for specific GitHub issues by giving a 👍 reaction on the original post in the issue and by commenting with details about your scenarios and requirements. We try our best to prioritize work based on broad community support and feedback.
Servers/Scalability
Minimal APIs
Blazor
Static Web Assets improvements
Blazor Web improvements
Blazor Server improvements
Blazor WebAssembly improvements
General Blazor dev experience improvements
The text was updated successfully, but these errors were encountered: