Full stack web UI with Blazor
danroth27 opened this issue ยท 129 comments
In ASP.NET Core today, we have a couple of different ways to build web UI:
- MVC & Razor Pages: These frameworks use server-side rendering (SSR) to dynamically generate HTML from the server in response to requests. Rendering from the server helps apps to load fast ๐ because all of the hard work of fetching the data and deciding how to display it has already been done on the server - the client just has to display the already rendered HTML. They can take advantage of powerful server hardware and directly access backend data and services.
- Blazor: Blazor's component model is focused on handling UI interactions from the client. Server-side rendering requires every UI interaction be sent to the server, so it isn't great for richly interactive UI. For rich interactivity ๐ฎ you want to use client-side rendering (CSR), which has much lower latency and can readily access client capabilities.
Many modern web apps need to use a combination of these approaches, both server-side rendering and client-side rendering. Maybe your home page or blog is best handled with server-side rendering so that it loads fast and is easily indexed, while the more elaborate functionality of your app needs the responsiveness of running from the client. Currently, with .NET, this requires using multiple different frameworks together: MVC, Razor Pages, and Blazor.
This issue proposes to combine the benefits of server-side and client-side rendering into a single consistent model based on Blazor , that we're currently calling Blazor United (name subject to change). Blazor in .NET 8 will enable you to use a single Blazor-based architecture for all your web UI scenarios. You can use Blazor components to render HTML directly from the server and also enable full client-side interactivity with Blazor Server or WebAssembly. That's all within a single project with the ability to easily switch between different rendering modes and even mix them in the same page. Blazor in .NET 8 will also enable new rendering capabilities like streaming rendering and progressive enhancement of navigations and form posts.
@SteveSandersonMS put together a video of an early prototype that demonstrates many of the intended capabilities.
Related issues:
If we use MudBlazor components and then use RenderMode.Auto, it loads first the page server side then after download the MudBlazor components and other wasm dll load and work on client side browser? We only want to increase the startup speed.
What will the programming experience be when authoring components? Will we need platform checks to decide if were running on WASM or Server and then decide to call an API or a local service?
Blazor United brings a lot of functionality to a table, but I'm curious how it will handle the following scenarios:
- RenderMode.Auto is used and for some reason the Websocket connection is cancelled because of a new build deployment. Will the data the client sees survive this? Or will the user have to re-enter any data they may have provided? (This assumes no major changes to the underlying parameters).
- If I update a Razor component, will it be smart enough to only download the changed assembly and not the entire wasm framework on a new deployment?
How will HttpContext be handled by Blazor United, as it is available in Blazor Wasm but not in Blazor Server?
If we use MudBlazor components and then use RenderMode.Auto, it loads first the page server side then after download the MudBlazor components and other wasm dll load and work on client side browser? We only want to increase the startup speed.
@mammadkoma With the Auto render mode the app loads first using Blazor Server. The .NET WebAssembly runtime is downloaded in the background and cached so that it can be used on subsequent navigations to that page. The idea is to ensure the app always loads fast while pushing load off of the server as soon as possible.
What will the programming experience be when authoring components? Will we need platform checks to decide if were running on WASM or Server and then decide to call an API or a local service?
@chrissainty The expectation is that the vast majority of components should be authored to function with all rendering modes. Otherwise, you dilute the value of component reusability! But we do want to enable scenarios where you need to platform specific things. That's where the normal .NET tricks of using cross-compilation and runtime checks come in to play.
If we use MudBlazor components and then use RenderMode.Auto, it loads first the page server side then after download the MudBlazor components and other wasm dll load and work on client side browser? We only want to increase the startup speed.
@mammadkoma With the Auto render mode the app loads first using Blazor Server. The .NET WebAssembly runtime is downloaded in the background and cached so that it can be used on subsequent navigations to that page. The idea is to ensure the app always loads fast while pushing load off of the server as soon as possible.
So we can use MudBlazor wasm components. But what about if the user doesn't change the page? All requests are blazor server mode until the user change the navigation? Or after the dlls are downloaded in background the wasm mode work?
How will HttpContext be handled by Blazor United, as it is available in Blazor Wasm but not in Blazor Server?
@marcoatribeiro Great question. I don't think we have a clear answer for this yet. The related work is tracked by #46393. Proposals on how you think should work are welcome!
So we can use MudBlazor wasm components. But what about if the user doesn't change the page? All requests are blazor server mode until the user change the navigation? Or after the dlls are downloaded in background the wasm mode work?
@mammadkoma Right, the page would continue to use Blazor Server initially and would only transition to use Blazor WebAssembly on a subsequent page load. This avoids a bunch of complexity with trying to transition from Blazor Server to Blazor WebAssembly while the page is still active. It does mean that if the user stays on the page for a long time the circuit might be long lived.
What about dlls being blocked by some antiviruses, even renaming the extension from .dll to something else doesn't help. This will make the transition to Wasm impossible.
Before we start, very good work! I appreciate the work you provide for the .NET platform. I have a question related to rendering. Let's say I have a page that is rendered by WebAssembly, in this page I have a component that is rendered by the server, can I share data with the components that do not share the same rendering mode? Are the cascaded values still functional even if the parent and child don't share the same rendering mode?
What about dlls being blocked by some antiviruses, even renaming the extension from .dll to something else doesn't help. This will make the transition to Wasm impossible.
@mihaimyh See dotnet/runtime#80807 for our effort to address this.
Regarding naming, while I do like Blazor United, as @danroth27 kind of eluded to in that latest community stand up (link to YT timestamp), perhaps "Blazor Web" is more appropriate to avoid confusion with Blazor MAUI/Hybrid. Kind of a toss up. ๐คทโโ๏ธ
Only other thing I wanted to add was that we probably should be thinking about what sort of code analyzers can be added so that if we render a SSR-only component and don't have stream rendering enabled for a particular component that requires it to function properly, then from VS we can show some warnings that the coded behavior may differ from the actual runtime behavior (or can be optimized by enabling stream rendering). And a similar analyzer would also apply to when we are using a component that ties to Blazor WASM/Server specific interactivity (i.e. button clicks) when we're not using Server, WASM, or Auto render modes.
I have no clue on what would be the best way to implement such an analyzer, but I think you'd want the warning to be shown where the component is being consumed IF the render mode is specified inline (i.e. <MyComponent rendemode=server />
), otherwise show it within the component itself if the rendermode attribute is specified in its .razor file. Might have to walk the tree of consumed components to determine the render mode of a N-level nested component. Would need to be mindful of components coming from RCL's & 3rd party component vendors.
Amazing work guys! Love all the new stuff coming out :)
I feel like the name should just be Blazor SSR (server-side rendering). This is what other front-end frameworks call it when the app is rendered on the server, sent to the client, and then the client hydrates the SPA to allow for a seamless transition. I see no reason to make up a new name. ^_^
Will RenderMode.Auto detect that user is using an old browser (without support webassembly) and will keep ServerMode (no switch to webassembly) ?
So we can use MudBlazor wasm components. But what about if the user doesn't change the page? All requests are blazor server mode until the user change the navigation? Or after the dlls are downloaded in background the wasm mode work?
As things stand, it's likely we'd only start newly-added component instances on WebAssembly, and leave existing Server components running until they go away naturally (e.g., when a user navigates to a different page). Migrating a running component instance would require your application to transfer its live state from server to client, and that would introduce many more difficulties for the application developer. You'd have to guarantee that all state is serializable (which is not the default in .NET) and you never reference large chunks of data, and you'd have to guarantee the user doesn't change the state while it's being transferred, and there's never any data you forgot to include, and so many other things. You probably don't want to deal with all that except in extreme cases, given the alternative is just waiting for the user to navigate (easy) or prompting them to let you refresh the page (also easy).
What will the programming experience be when authoring components? Will we need platform checks to decide if were running on WASM or Server and then decide to call an API or a local service?
That's a great question and one we've spent some time thinking about. In the BestForYou demo, we had an interface abstracting over the "save recipe" operation, with a server implementation that hits EF directly and a wasm implementation that calls a minimal API. For .NET 8 this sort of "abstract it yourself" approach might be where we land, but longer term we're considering ways to automate the creation of the abstraction at compile time. The challenges are with things like auth, logging, or other cross-cutting concerns: when the call comes from an external untrusted client, you actually want to handle it differently than when the call comes from trusted server-side code. If the abstraction is too powerful and too automatic, developers will be prone to forgetting they are exposing sensitive server-side operations to untrusted clients, so careful design is needed.
RenderMode.Auto is used and for some reason the Websocket connection is cancelled because of a new build deployment. Will the data the client sees survive this? Or will the user have to re-enter any data they may have provided? (This assumes no major changes to the underlying parameters).
One of the advantages of Blazor United is that it encourages an architecture where as many pages as possible are stateless and don't even involve a circuit, so a large percentage of your users are indifferent to changes of server. However, when a component is running interactively on the server, you should assume it has the same behaviors as Blazor Server today. There isn't automatically some new way to preserve state across server restarts (see all the commentary about serialization etc above). We could introduce manual ways to persist selected pieces of data, but all the responsibility for actually doing that and providing a backing store would still fall on the app developer.
If I update a Razor component, will it be smart enough to only download the changed assembly and not the entire wasm framework on a new deployment?
When a component is running interactively on WebAssembly, you should assume it has the same behaviors as Blazor WebAssembly today. We already have a caching system that causes the client to only fetch files it doesn't already have cached locally (so if some framework library is already cached, it doesn't refetch the same version of that file).
How will HttpContext be handled by Blazor United, as it is available in Blazor Wasm but not in Blazor Server?
When doing passive SSR, we expect to provide ways of accessing all the data you need from the request/response, but haven't confirmed the API shapes yet. Hopefully we will not expose HttpContext
directly as that would lead to inconsistencies across platforms (note that HttpContext is not available in WebAssembly because there's no request/response).
What about dlls being blocked by some antiviruses, even renaming the extension from .dll to something else doesn't help. This will make the transition to Wasm impossible.
That's not specific to anything in Blazor United, but as it happens we do have work ongoing to address that. For further discussion please see dotnet/runtime#79416
Regarding naming
If you don't mind, I'm going to ignore any naming discussions - it not in the scope of what's being planned/investigated here.
I have a question related to rendering. Let's say I have a page that is rendered by WebAssembly, in this page I have a component that is rendered by the server, can I share data with the components that do not share the same rendering mode? Are the cascaded values still functional even if the parent and child don't share the same rendering mode?
It's not fully prototyped yet (we've done it but only partially). The expectation is that you should be able to nest passive/server/client components in any combination. When there's a seam between different rendering modes, any parameters have to be serialized of course. Support for RenderFragment
parameters may be limited and callbacks (e.g., for events) may not be possible across seams, at least not initially. One design challenge in this area is that the scenarios aren't totally clear - the idea of passive->client->server->passive->client nesting exists in theory but in practice who would ever do this and why? What specific scenarios would guide prioritisation for what features would be important to make cross seams?
And a similar analyzer would also apply to when we are using a component that ties to Blazor WASM/Server specific interactivity (i.e. button clicks) when we're not using Server, WASM, or Auto render modes. ... Might have to walk the tree of consumed components to determine the render mode of a N-level nested component.
You're right that this is potentially useful but also that it's potentially difficult, given the fact that components themselves are usually agnostic to render mode, can have dynamically chosen children, and we would have to know about all descendant components transitively. Runtime checks are far more straightforwards for this kind of thing. For compile-time checks, it's totally possible we might be able to provide some helpful hints, but it's nontrivial to solve in general.
Will RenderMode.Auto detect that user is using an old browser (without support webassembly) and will keep ServerMode (no switch to webassembly) ?
Interesting idea. TBH, throughout the lifetime of Blazor WebAssembly, we've had little to no feedback that people are troubled by very old browsers that don't support WebAssembly. That's a very niche scenario at this point. However it would be really simple for us to include that rule in the client-side logic that resolves Auto to a specific render mode!
So one thing that was demo'd was the ability to enable Auto mode and the browser will first establish a signal-R connection for a "Blazor Server"-like interaction, and then silently download the WASM runtime and corresponding DLL's to then switch to "Blazor WASM"-like interaction on next page load. However, unless I missed something, if I first load a SSR page, then neither of the above operations occur, is that correct? What would be nice would be the option to opt-in to when loading a SSR page, to also silently begin downloading the WASM runtime and DLL's. The key part being the ability to opt-in/out of this "WASM pre-fetch" behavior depending on the loaded route. For example:
Scenario 1: (This should be similar to what y'all demo'd I think)
I have a SSR (probably w/ streaming) product listing page as my "landing page" with no Blazor interactivity needed (i.e. button event clicks), just pure navigation (show a list of pictures, pricing, and a linked anchor tag to get to a product detail page). When I open the product page is when I need some Blazor interactivity (i.e. button event clicks).
In this scenario (again based on y'alls demo), if Auto render mode was enabled, the product listing page (landing page) is rendered with SSR. Once the user navigates to the product detail page THEN a signal-R connection is created and WASM runtime/DLL's are downloaded in the background. However, what would be preferred in this scenario is that on the SSR product listing page, having the WASM dependencies download already initiated in the background, therefore avoiding the signal-R connection all together (unless the user navigates that fast or connection is that slow).
So in summary, in this scenario, I would want all the WASM dependencies to be downloaded in the background of my SSR landing page. Having the ability to opt-in to this "WASM pre-fetch" feature would be preferred in this example.
Scenario 2:
I have a SSR login page as my "landing page" with no Blazor interactivity needed (i.e. button event clicks). I use typical form submission to POST to the server. On successful login, the server responds with a auth cookie and a redirect to the user's profile page, which does require Blazor interactivity (i.e. button event clicks).
In this scenario, if Auto render mode was enabled, the login page is rendered with SSR. Once the user authenticates and the browser redirects to the profile page THEN a signal-R connection is created and the WASM runtime/DLL's are downloaded in the background. In this scenario, the default behavior (assuming I understood it correctly from the demo) is exactly what would be preferred, the goal being don't download any WASM dependencies until we have an authenticated session. This wouldn't necessarily be for security reasons since any DLL downloaded to the browser at any point should be considered insecure, however this would be more along the lines of "trying" to ONLY allow our software to be obtained by authenticated user's (i.e. a customer who has paid for our software and therefore is allowed to download the software package).
So in summary, in this scenario, I would NOT want any WASM dependencies to be downloaded in the background of my SSR landing page, but rather wait until an authenticated navigation has occurred. Having the ability to opt-out of this "WASM pre-fetch" feature would be preferred in this example.
Hope this makes sense. The end goal would be to have the ability to opt-in/out of pre-fetching WASM dependencies from a SSR landing page while still using the Auto render mode.
@gerneio yeah, I'd love for this scenario as well where I can basically pre-fetch the wasm runtime on the SSR pages so it's already ready the moment you navigate to a page that needs it, ideally from a service worker (so it doesn't get cancelled between browser nagivations). Maybe from an attribute so I can control which route initiates the wasm pre-fetch.
@SteveSandersonMS I'm not sure if this has been discussed somewhere already, but it would be super useful if a Component could say "my only supported mode is client". I could drill into this in a lot of depth if you'd like, but the short version is that this would be exceptionally useful.
I hope blazor united will setup a clear path to auth, and in particular it seems it will be well suited to a BFF type security setup (cookies sent from the fornt end to a dedicated server).
I really think that given the shift in the auth specs that it is wise to target BFF back-end-front-end strucutures with cookies.
@SteveSandersonMS thanks for the expanatory thread above. I have a couple of questions/observations:
Seams - you mention that there may be issues with callbacks across seams. My interest here is for component libraries (there's been some mention of MudBlazor above and I'm an author of Material.Blazor). It makes a lot of sense for component libraries to use the Auto mode, especially if they make use of JS Interop, thereby minimising latency. Some Material.Blazor components use callbacks to facilitate back end/database functionality to feed datasets to components. It would therefore be great for Auto or WASM rendered components to have the ability to issue callbacks across a seam into their server rendered app.
Static hosting - If I have a WASM static hosted app, will components libraries with render mode of "auto" still work? If not how should one approach this? Either (i) will an RCL consumer have the ability to specify the render mode for an entire library (specifying this at compile time rather than run time feels most natural), or (ii) will the RCL need to be published in multiple variants, i.e. WASM variant, Auto variant etc?
Blazor United is a stunning prototype and will dramatically improve my business's app. Thank you.
@simonziegler I would generally expect RCLs not to declare a specific render mode. That's the default and is the situation already for all existing RCLs. The application developer consuming a component from an RCL will either (1) specify a render mode at the location where they use that component, or (2) allow the component instance to inherit the render mode that's already in effect at that location.
I don't think RCL authors will generally want to specify a render mode because they have no way to know what render modes the hosting application will want to support. We are letting app developers choose whether their app supports Server, WebAssembly, both, or neither (i.e., passive SSR only), and there are legit cases for all four of these combinations.
I know people will say they want to indicate that a component "requires" interactive rendering but we may yet find it's better to leave the app developer in control of that. There are legit cases for passively rendering anything, even components whose full functionality only takes effect with interactive rendering. We can allow app developers to make that choice, especially if it's clear and obvious to them what choice they are making.
Static hosting - If I have a WASM static hosted app, will components libraries with render mode of "auto" still work?
Again, I don't think the RCL component should generally specify any render mode. But the answer to your question is yes. If a component is being used in an interactive context - Server or WebAssembly (including a statically-hosted wasm app) - then specifying the "auto" render mode has no effect since the component will just be rendered in the enclosing Server/WebAssembly context.
@SteveSandersonMS that makes sense and I can see that an RCL should be agnostic to its render mode. One thing I would like as an app developer/RCL consumer though is to say "the default for this RCL, or namespace maybe is Auto/WASM etc" so that I don't need to specify this on each and every component (of which I have thousands). Is this something that might be manageable?
@SteveSandersonMS I'd encourage you to consider letting a component force it's rendering mode to client at least, not necessarily forcing to server, even if it drives WASM being required.
Needing to support server mode makes certain classes of components really onerous to produce and maintain for Blazor. The problem of interactivity and latency can be addressed by having more of the interaction logic be JavaScript rather than C# (even if this rankles a bit when it could have been WASM) but the really insidious issue is that this JS logic cannot synchronously interact with the C# logic since it may be running on the server.
This forced asynchrony between JS logic and C# logic makes whole classes of problems much more intractable. A scenario that could have been handled imperatively with an event instead MUST be handled declaratively to that it can execute entirely in JS with the rest of the interactive logic.
Instead, if we were able to indicate "this component always runs on the client, and all event handlers, etc, attached to it also run client side (WASM)" this would immediately make Blazor 1000% easier to work with.
I appreciate that this is a significant challenge to implement, but it sounds like you are addressing it if you are considering letting the developer select the rendering mode of a component. But I'd implore you to consider also allowing a component to force it's mode to client.
I understand forcing to server would complicate the hosting on behalf of the consumer of the component, but isn't forcing client mostly complicating the build process?
As it stands, if we are adapting an existing web component to Blazor, for example, we actually need to alter large portions of it's API to have declarative options rather than the simple event based hooks it had originally. And invariably some capability is lost even so, necessitating consumers of the component sometimes needing to provide an event handlers using JS instead of C#. Again, I can go into the challenges the forced asynchrony bridge impose in super fine detail if you'd like. But suffice it to say it would be my favorite Blazor feature ever if you could force all interaction with a component to be client side and able to bridge synchronously.
In the prototype it is already possible for a component to specify a particular default render mode for itself. I was only suggesting that most RCL components shouldn't do that (assuming their goal is to maximise flexibility for the user), even though technically they can.
If a component explicitly demands a render mode that isn't supported on the host, based on what the app developer has configured, that will just result in an error.
@SteveSandersonMS that sounds excellent, actually. What are the scenarios where forcing client wouldn't function? If they have configured their app to be ssr only with no script payloads? Disabled WASM building?
If they have configured their app to be ssr only with no script payloads? Disabled WASM building?
Correct
I'm building a UI library on top of Blazor specifically IComponent
and ComponentBase
, does this mean I should update all of my component to support this new model? it might be too early to comment on breaking changes and how do we migrate into this model but do you guys expect any sort of fundamental changes? I hope you will keep the name Blazor for simplicity and add Blazor United model as an addition and a choice because having to think about Blazor the old and Blazor the new might be confusing.
If we use MudBlazor components and then use RenderMode.Auto, it loads first the page server side then after download the MudBlazor components and other wasm dll load and work on client side browser? We only want to increase the startup speed.
@mammadkoma With the Auto render mode the app loads first using Blazor Server. The .NET WebAssembly runtime is downloaded in the background and cached so that it can be used on subsequent navigations to that page. The idea is to ensure the app always loads fast while pushing load off of the server as soon as possible.
How about if you publish and serve the blazor wasm app from a CDN (that purely serves up static files for speed of delivery) and the api that the wasm app talks to is your aspnet core api hosted somewhere else - I'm struggling to conceptualise where or if server side pre-rendering or blazor United has any relevance in this model?
does this mean I should update all of my component to support this new model
You should not have to do anything different. If you already support Server and WebAssembly hosting models then your component will already work when rendered in those modes. If you already support prerendering, your component will already work when rendered passively (i.e., SSR only). Of course, things like event handlers only work with interactive rendering so you may consider interactive rendering a prerequisite for your component, depending on what it does.
How about if you publish and serve the blazor wasm app from a CDN (that purely serves up static files for speed of delivery)
In this hosting scenario you're doing exactly what Blazor WebAssembly apps have always done and nothing changes in terms of capabilities or data access. You can't do any server-side rendering if you're hosting on a static-files CDN because you don't have a server that can run your code.
Does Blazor United bring any advantages to a Blazor WASM app that must be indexable by search engines?
It gives you the option to implement parts of your app with pure server-side rendering. For the parts you continue to render interactively with WebAssembly, it's just equivalent to the existing prerendering support.
What are some reasons I might want to implement parts of the app with pure server-side rendering?
Thanks
For general info, I'd recommend web searching for something like "server-side rendering vs client-side rendering". Eventually we'll publish Blazor-specific guidance but it's too early for that right now.
How about if you publish and serve the blazor wasm app from a CDN (that purely serves up static files for speed of delivery)
In this hosting scenario you're doing exactly what Blazor WebAssembly apps have always done and nothing changes in terms of capabilities or data access. You can't do any server-side rendering if you're hosting on a static-files CDN because you don't have a server that can run your code.
Thanks!
Just to explore avenues on this front, suppose you want SSR, and to serve static files up from a CDN predominantly (as downloading these static files can be closer to the user and served up quicker, and not consume app server bandwidth) is there some sort of approach that will allow this i.e initial request hits aspnet core server, it responds with something that causes the browser to download the wasm files from an external CDN somewhere (e.g some custom index.html?) - but once that completes and the spa loads in the browser, the spa's blazor components can still connect back to the aspnet core server again rather than their point of origin (the cdn) in order to use SSR ? I don't think I'd want to go down this road, but there are attractive qualities of being able to offload serving of static files to CDN's, and also attractive qualities of SSR within an app for certain use cases - so it begs a question.
@dazinator Yup same question from me. Would be useful to keep the SSR "super light" and offload all downloading to a separate CDN. Is this possible ?
That sounds not specific to Blazor United but would be applicable to any Blazor WebAssembly app. If you want to follow up about that, could you post a separate issue? Thanks.
one thing I'm curious about is what will happen in Balzor United when a component is rendered as a server-side page(as in Razor Pages now),but a component with the server-side mode is also used as part of the page to add interactivity.Will then the whole page go blank,as is the case currently,if the user doesn't interact with the page for a few minutes?
Is the following scenario going to be supported by Blazor United?
Simple HTML landing (marketing) page of a product with a login/register button at the top. As soon as this HTML page is loaded, all WASM resources start downloading and when finished, user will be able to click the two buttons and the corresponding WASM page will be rendered instantaneously.
The landing/marketing page is really just static HTML and I don't want to do any pre-rendering or server side Blazor at all. I watched the introductory video a few days ago and if I remember correctly something like that is being considered?
This particular use case is what I've been looking for since day one.
Thanks!
a component with the server-side mode is also used as part of the page to add interactivity.Will then the whole page go blank,as is the case currently,if the user doesn't interact with the page for a few minutes
I assume you're referring to the situation where a user's websocket connection is lost (which isn't normally caused by a few mins of idleness, but it certainly can happen). We haven't made a design for the connection-lost scenario yet, but by default, it would be the same as Blazor Server's existing handling for this (i.e., a full-screen "reconnecting..." overlay). I'm not sure what else you could do since it would be hard to communicate to a user that some parts of the page are frozen but other parts will work. Technically you can already customize this as much as you want - I'm just talking about the built-in default.
Is the following scenario going to be supported by Blazor United?
Yes, but you can already do that today. Just have your Blazor WebAssembly app's index.html
contain all this static HTML you're describing, and that's what will show up until the runtime is downloaded and started (at which point you can render the same UI except now your buttons work).
But once the runtime is downloaded isn't the index.html
page completely replaced? Wouldn't things like scrolling position etc be lost?
But once the runtime is downloaded isn't the index.html page completely replaced? Wouldn't things like scrolling position etc be lost?
The DOM is completely replaced today, but I don't think that will result in scroll position being lost as long as the new content matches the old. The DOM update is performed synchronously. I just checked that setting document.body.outerHTML = document.body.outerHTML
doesn't lose a page's scroll position despite replacing all of the DOM elements.
With Blazor United, we plan to enhance things and retain the original server-rendered DOM elements when performing enhanced navigation and form posts, but we are not planning to retain the original server-rendered DOM elements when activating an interactive component, as this is expensive to implement and leads to other problems with the DOM being out of sync (e.g., if a user has already started typing into a textbox that has a per-keystroke event handler). So I don't think anything specifically will change for the Blazor WebAssembly scenario.
We haven't made a design for the connection-lost scenario yet, but by default, it would be the same as Blazor Server's existing handling for this (i.e., a full-screen "reconnecting..." overlay)
Actually, It'd be pretty counter-innovative to stick with the existing handling of Bazor-Server's connection-lost scenario. I think you could make it possible for the developer to set the idle time, and also provide a customizable component to be displayed when the connection is lost. Better yet, It would be awesome if you could write a JavaScript that would automatically reconnect without even the user realizing that the connection was lost as he/she moved the mouse wheel.
@SteveSandersonMS In .NET 8 or later versions, will the project model (in Visual Studio) be changed? i.e., will Blazor Server project and Blazor WebAssmbly project be both remained? Or single unified project system (#46398) would be offered?
I think that blazor united is very innovative, but developing Blazor apps which can work both in SSR/CSR mode would require additional efforts and careful development. So it would be happy to keep the Blazor Server project and Blazor WebAssmbly project models.
@nakamacchi That's listed as one of the open questions at #46395. If you want to add any feedback about scenarios, that would be a great place for it. Thanks!
The concepts for Blazor United are interesting. I'm trying to understand if/how there will be any possibilities to do something like Turbo Frames, without needing a component (or the whole page) set to server render mode, that in turn would need a WebSocket connection?
That is, within a scoped element, like a div tag, would it be possible to make a HTTP Get request by clicking a link (or enhancing any element to trigger a request in various ways, in the style of Htmx), that updates just the contents of that scoped div or another named element on the page?
So we can use MudBlazor wasm components. But what about if the user doesn't change the page? All requests are blazor server mode until the user change the navigation? Or after the dlls are downloaded in background the wasm mode work?
As things stand, it's likely we'd only start newly-added component instances on WebAssembly, and leave existing Server components running until they go away naturally (e.g., when a user navigates to a different page). Migrating a running component instance would require your application to transfer its live state from server to client, and that would introduce many more difficulties for the application developer. You'd have to guarantee that all state is serializable (which is not the default in .NET) and you never reference large chunks of data, and you'd have to guarantee the user doesn't change the state while it's being transferred, and there's never any data you forgot to include, and so many other things. You probably don't want to deal with all that except in extreme cases, given the alternative is just waiting for the user to navigate (easy) or prompting them to let you refresh the page (also easy).
This is a little bit disappointing - I definitely hoped that it'd replace the connection altogether. However the reasoning you're giving is understandable. But just to clarify - does it mean that once a new component on the same page is rendered after WASM loads, that specific component will be handled by WASM while older ones will still live on circuit? Or will a full page refresh to reload application be needed?
And as an another question - currently one of issues that Google PageSpeed points out, but also is noticeable on mobile phones, is the CPU-bound application startup time. What I mean by this - assume user already visited the page in past and has all assemblies already cached, the page will still take a noticeable while to become interactive because the application still takes a fair amount of time to start-up.
How will the Auto mode tackle this, if at all?
Will you also consider adding support for MVC controllers to directly render a razor component?
public sealed class HomeController : Controller
{
public IActionResult Home()
{
return Component(new HomeComponent { Param1 = ... }, RenderMode.Static);
}
}
We would benefit from
- type safety we don't have with the
ViewResult
,ViewComponent
andComponentTagHelper
- make things more unified and less confusing
.razor vs .cshtml
But just to clarify - does it mean that once a new component on the same page is rendered after WASM loads, that specific component will be handled by WASM while older ones will still live on circuit? Or will a full page refresh to reload application be needed?
The intention is that Auto works on a per-component-instance basis. So once wasm is available, newly instantiated auto components can use it, regardless of there being a remaining circuit. The goal is to get that circuit to go away, so we don't want new components to hang onto it.
What I mean by this - assume user already visited the page in past and has all assemblies already cached, the page will still take a noticeable while to become interactive because the application still takes a fair amount of time to start-up.
The United approach helps if the user initially lands on a non-wasm page because then they aren't waiting for interactivity to start. But if they do land on a page that is primarily composed of wasm components, nothing changes vs the existing setup (assuming you already prerender your wasm components on the server).
Will you also consider adding support for MVC controllers to directly render a razor component?
Yes, that's in the prototype already. I think we called it ComponentResult
but the final API isn't decided yet.
I downloaded .net 8 preview 1 (8.0.100-preview.1.23115.2) and create a blazor project by "dotnet new blazorwasm" but it doesn't build and run !
@SteveSandersonMS has some thought been given to making Blazor wasm compatible with the wasm you might get from a .net 8 vanilla wasm project, if you were to create a "library"?
Also is the vision for Blazor United to be a vnext? or a parallel option?
has some thought been given to making Blazor wasm compatible with the wasm you might get from a .net 8 vanilla wasm project, if you were to create a "library"
If you want to discuss that further please file a separate issue since it seems unrelated to this one. Hope that's OK.
Also is the vision for Blazor United to be a vnext? or a parallel option?
It's all intended just to be part of Blazor as of .NET 8.
@SteveSandersonMS ah nuts, I was hoping for just a yes :) I need to collect my thoughts a bit more to phrase a new issue around it.
I can't find any document for blazor united but based on this video : https://www.youtube.com/watch?v=48G_CEGXZZM
I added "@Attribute [ComponentRenderMode(WebComponentRenderMode.Auto)]" to the Index.razor page but it get error :
@mammadkoma As mentioned in the video, that is only a prototype currently and is not yet part of the product. You can't do this yet, I'm afraid!
So why this issue #46636 exists?
This issue is to describe the concept and provide links to other issues with more information. We are also using it as a place to collect feedback about it.
I just wanted to jump in and add some feedback on one of the pain points I have had in trying to blend client side speed and functionality with server side rendering functionality. Iโm not sure if this is really the right place for it. It is possible to do today, just the hoops you have to jump through to implement it are slightly tedious.
One of my main wishes is that there was a simple way to have a client side JavaScript function on DOM events for things like OnClick that can cancel the event when it happens so it is not called on the server side. Like a before-onclick=โvalidateStateโ that would call the JavaScript function and return true/undefined to continue or false to cancel and not call the server side function. I often want to do some minor client side validation or state checking before the request hits the server event handler, reducing unnecessary round trips when possible.
Do you have any sense of when a prototype of this will make it into the VS Preview channel? (I know that's not something that any developer ever wants to commit to, and that plans change, but an idea of what kind of timeframe you're shooting for would be nice!)
Do you have any sense of when a prototype of this will make it into the VS Preview channel? (I know that's not something that any developer ever wants to commit to, and that plans change, but an idea of what kind of timeframe you're shooting for would be nice!)
I think I heard somewhere that this is likely to make it to .net 8 preview 2.
Preview 3 is the earliest possibility, and at that stage it will have only the most foundational behaviors (just some improvements to SSR, not most of the features we've shown in the prototype).
To me, the biggest disadvantage of Blazor WebAssembly connections is that the application DLL's and dependencies are downloaded to the browser. (Obviously this is a right tool for the job situation, so this isn't a bad thing unless you put sensitive information in the portion of your app that uses the WebAssembly connection).
Having said that, I have used WebAssembly enough to realize how powerful of a tool it is. What would be nice is to leave "confidential portions of the application", (parts of the web application developers wouldn't want to be included in the DLL's sent to the browser in the web assembly connection), as strictly accessible via the web socket connection using the server side style rendering.
Is this something that could be explored in the future of Blazor United?
On another note, I see the "Blazor United" as the future of this framework. Deciding "Server" vs. "WebAssembly" has sent me in loops, and I still have to go back to pros and cons list when determining which is the better tool. This is best of both worlds. I have seen two other suggestions in this thread that provide a lot of value.
Suggestion 1 came from @gerneio comment regarding the ability to have the WebAssembly rendering started silently even if the first component/page rendered doesn't need a webassembly connection. Then, when it does, the application dynamically switches over.
Suggestion 2 came from @krzychacz1 question "Will RenderMode.Auto detect that user is using an old browser (without support webassembly) and will keep ServerMode (no switch to webassembly)?" This is a great suggestion. It only improves the frameworks adaptability.
Just to recap,
- I am curious to know if restricting parts of a blazor app to use server side rendering while also omitting that portion from the applications DLL that is sent to browser is something that could be explored. (I realize this might sound a little crazy...)
- I would like to emphasize the suggestion from @gerneio regarding timing on WebAssembly connection for components that don't need it/dynamically switching to WebAssembly when it is needed. (Basically enhancements on the "let the framework decide for you")
- I would like to emphasize the suggestion from @krzychacz1 about autodetecting browsers and establishing supported connections for those that are not.
Really nice write up Ben! Please have all those above implemented if possible.
It would be nice for server-side rendered static pages/components to respond to events like click events that causes the site to update without SignalR/WebSocket
Of course, some events would inevitably require some socket-like functionality.
But at least we could be smarter about using it.
Very excited to hear about this future functionality. We are very interested in re-implementing our website in Blazor, mainly to take advantage of componentization. However, since our data model for each page is very large, and we do not want to have the server hold all the data model in memory, we have resorted to Server-mode rendering, without any interactions. That said, we do want to have some interactive components on the page for mostly paging/sorting.
Happy to test out the solution when it's ready.
- I am curious to know if restricting parts of a blazor app to use server side rendering while also omitting that portion from the applications DLL that is sent to browser is something that could be explored. (I realize this might sound a little crazy...)
Wouldn't the easiest way to do this be to just not 'trust' the project with information you don't want to get leaked?
Would be really interested to hear about things you might do in your server-side project that you wouldn't do in your wasm project.
I for one, always do API requests, server-sided or not, but like I said, would love to hear what kind of "confidential portions of the application" you're talking about.
@marinasundstrom: kind of vaguely analogous to situation of loading / reloading a partial razor view into a an higher order view via f.i. a JS fetch on certain events.
Authentication, is this going to be improved, I know there has been plenty of discussions about this in various posts, specifically, Blazor server and having to either scaffold .cshtml files or create a middleware component, is a bit of a mess, once you use frameworks like MudBlazor, I do have this working with a middleware component that is a bit of a fudge. It would be nice to see the built in identity system work properly with .razor pages.
Specifically SignInManager working in razor pages would be a big improvement for me.
In auto render mode. Is it possible to switch to wasm as soon as the binaries are downloaded rather than the whole page refresh?
@syedqutub In the prototype, the page will default to Blazor Server the first time while downloading the WASM files in the background. It will only use WASM the second time your hit the page and in subsequent visit.
Even if it is possible, I think that doing a "hot switch" would be impossible since you need to transfer the state from the server to the browser. That might be a potential security risk.
Yeah it's tough challenge to not only safely transfer the state but also to ensure consistancy.
Let's say if some one is clicking the increament count rapidly and at the time of "hot switch" what will happen?.
I feel even if this idea is possible to implement, it will require few years to graduate the "experimental" title.
Just curious if Blazor United apps can be deployed to Azure static web apps. Is it possible? Or is there no advantage here?
Just curious if Blazor United apps can be deployed to Azure static web apps. Is it possible? Or is there no advantage here?
@ray440 No, Blazor United requires an ASP.NET Core server. If you want a purely static site, you can still use Blazor WebAssembly.
Are there any plans to support "RuntimeCompilation" for Razor Components (*.razor files) the same we already have for Razor Views (*.cshtml files) ?
@alienwareone No, that's completely unrelated to Blazor United.
Is there any consideration for Blazor Hybrid with United? I want to use Blazor Hybrid with MAUI to rewrite my app to make it crossplatform, but I hit a big wall with image editing with Skia: Blazor Hybrid in essence is Blazor Server, just without websockets.
I need some components to run in WebAssembly, where I can use for example SkiaSharp.View to allows user to draw things. Then, I need to get back the image for the "server" logic to pass it around.
In dotnet 7 it's quite easy to do, but not as easy as it could: you export your component as custom HTML component and do some workarounds for two-way communication and it works.
It would be great to be able to just drop a component, mark it as Mode.WebAssembly and hook up an event handler that, in my case, would just pass base64 encoded image.
I am convinced that people would be "happy enough" when forced to pass around only serializable values, but hooking up event handlers and binding parameters is a must to work between render modes.
And I hope all of this gets its way into Blazor Hybrid.
Great job so far!
@qrzychu The โBlazor Unitedโ initiative just deals with Blazor as it runs on top of the ASP.NET Core stack. And I think @SteveSandersonMS was clear about that when he was talking to Carl Franklin.
I believe that it is possible run .NET on WebAssembly in the WebView - just not Blazor WebAssembly with the version hosted in MAUI.
@marinasundstrom I just finished watching the episode, MAUI was mentioned at the end as "not a really special case" and "problems that United solves don't exist in hybrid" - but they do.
That's why I wonder - if setting render mode will work in hybrid. In principle it should, and according to what Steve said in the episode, I still think that. I just wonder at what level of abstraction are the websockets replaced with just a string encodind for the BlazorWebView - and whether it will inherit all the goodies from United.
@qrzychu Blazor MAUI Hybrid and Blazor WASM are two different environments. I don't think Microsoft sees it as a common use case mixing in-process Blazor MAUI with Blazor WASM. They are not using the same shared infrastructure under the hood.
There are ways to build components that work in both environments.
@marinasundstrom that's why I ask :)
Blazor Hybrid being "in process" is just a semantic for "Blazor Server in WPF" or MAUI or whatever, with shortcuts to make it faster.
Maybe if this lands a spot on a to-do list early enough, it will be easy to implement, I hope so
@qrzychu But Blazor Hybrid has no Web server. It is much slimmer than Blazor Server since there is no HTTP.
It renders directly into the WebView. So no way for Blazor Hybrid and Blazor WASM to communicate as one - since they both literally run in different execution environments. Hybrid renders components in-process in the MAUI app process. WASM is entirely rendered in the browser. The only way to communicate is via JavaScript.
"Blazor United" is about uniting the rendering modes so they with a common infrastructure on the Web server.
The best case is to build components so that they work across all Blazor models that target the web. As said, you can still load WASM in Blazor hybrid - I believe - using interop. It is just not the same execution environment.
I do however sympathize with wanting a universal Blazor platform that maximize code sharing - incl. components. I just don't believe that this scenario of seamlessly putting Blazor WASM components in Blazor Hybrid apps is valid or that great for that matter. It confuses people.
@marinasundstrom by "render directly into WebView" as far as I know you mean that there is a base64 "context" (or maybe it contains the whole DOM? don't know the details) passed into the web view to render, right?
And case for using WASM component in hybrid is easy to make: https://github.com/mono/SkiaSharp
It has a Blazor component that allows you to do high performance drawing, like animating a point moving on a canvas at 60fps or more. It only works in WebAssembly.
Doing anything like this in Blazor hybrid is way too slow. Consider following Blazor component:
<img src="@Image" style="width: 50%; height: auto"/>
@code {
[Parameter] public string Image { get; set; }
}
Image has to be base64 string to be displayed in Blazor Hybrid. If I wanted to draw a dot under user cursor on onMove
event, I get 5fps at best if the image is big (1000x1000 px). Funny enough, it's not because of the base64 conversion - BlazorWebView is just too slow to pass down the long string, there is even github issue for that somewhere. Doing exactly that in WPF/Avalonia/MAUI - drawing new bitmap after every onMove event and refreshing the display - works perfectly fine, I've used it in the past.
Easiest solution would be to do it all in WebAssembly, or use SkiaSharp view, but it also runs in WebAssembly. Setting RenderMode.WebAssembly
on a component in this context would be GREAT.
I asked for Blazor United in this context, because I don't really know how events are passed from DOM (which runs in separate proces) back to the Blazor component running natively.
My guts tell me that this is Blazor Server, but without websockets - there must be some JS injected to pass the events back to the native process. If so, it could easily pass events form WASM component.
I am also fully aware that I would be embeding a dotnet runtime inside of a web view running in a dotnet runtime, but that sounds like fun :)
I can prepare the drawing thing reproduction repository if you want, I did some experiments with it, after some clean up I could show it to you.
Is this something that could be explored in the future of Blazor United?
I noticed the above question hasn't been addressed by the Blazor team. Can we get a comment on this, please?
Blazor United sounds promising, but anything involving WASM means downloading code to the client where it may be decompiled by potentially harmful actors. This is an obvious security concern.
It would be valuable to know how this is being addressed, especially with how seamlessly WASM is now being introduced in the rendering process with Blazor United. Organizations may be unintentionally leaking code to nefarious actors under such circumstances, and this should be properly recognized and handled.
Thank you for any comment that you can provide.
Anything client-side will be susceptible to bad actors. That's why you put all your key business logic serverside behind authenticated APIs. If your client-side business logic is storing or doing stuff that could result in a vulnerability, then your app is probably designed wrong. I don't think blazor United is really going to change that, since all it's doing is allowing some of the blazor wasm content to be rendered serverside, and only running client-side UI code when a more dynamic user interaction is required.
What scenario do you forsee where Blazor United will result in sensitive code or data being exposed to the client side inadvertently? The only one I can envisage is if you have sensitive business logic in a razor file; and if that's the case your app could probably do with being restructured regardless of the hosting model....
since all it's doing is allowing some of the blazor wasm content to be rendered serverside
What does this look like, exactly? I am under the impression that it's not some but the entire codebase is downloaded to the client. Regardless of the amount of code, it's a security consideration that is not encountered with the server-side model, which is why it's a preference to those who use it.
What scenario do you forsee where Blazor United will result in sensitive code or data being exposed to the client side inadvertently
Any code that is downloaded to the client that isn't already open-sourced. This code can then be decompiled and studied for vulnerabilities, regardless of the amount. This simply does not occur server-side which is why it is the preferred choice for developers who are presented with the two design options. The primary concern is that (according to the videos) this happens transparently without much effort. How does an organization know which code is downloaded to the client in such circumstances?
The only one I can envisage is if you have sensitive business logic in a razor file; and if that's the case your app could probably do with being restructured regardless of the hosting model....
Be that as it may, many organizations are guilty of such practices and now are being exposed to risks (and subsequent costs) that they were not before this was introduced, which is the concern.
I noticed the above question hasn't been addressed by the Blazor team. Can we get a comment on this, please?
@Mike-E-angelo Currently with Blazor WebAssembly apps any code and dependencies that will get downloaded to the browser are managed in a separate project. If you're operating within the Blazor WebAssembly project then you know the code is effectively public and you should manage it accordingly, just like you would with JavaScript.
With Blazor United we're planning to enable building the entire app within a single project, but we still want a clear separation between code that will be downloaded to the browser and code that is server specific. We're planning to handle this by introducing a new browser specific target framework moniker (net8.0-browser) and then multi targeting the project. You can then control which parts of the project are for the client, server, or both with reasonable defaults. Only the build output targeting net8.0-browser will downloaded to the browser.
We're planning to handle this by introducing a dotnet/designs#289 and then multi targeting the project
Thank you @danroth27 that is most informative and valuable to know. ๐๐
Hey All! Not sure if this is discussed / requested anywhere, but is it possible to have both the API layer and the frontend glue code calling the API layer auto generated?
What I am thinking here is to have methods defined with data attributes like: "[ServerOnly] [API]" or something which will ensure these methods are only run on the server and the framework can auto generate the API layer for these methods and also generate the frontend glue code ( potentially using source generators? )
This way we can have a single component work in both server render mode ( any action calls the method directly ) and client render mode ( any action calls the auto generated API client )
I am not sure if it was discussed before (sorry if it was), it would be great to have option to recognize if the user agent is mobile or desktop and then choose to render via server or WASM accordingly.
We have a number of Blazor apps in prod now across server, wasm and hosted in Electron. One issue that seems to catch out devs building shared components and services is the scoping for DI services, in particular the behavioural subtelty between singleton and scoped when in server or wasm deployments.
It would be useful to be able to attribute a service that might be injected into a component that relies on a cross-user singleton state, such that the runtime knows it canโt be executed in wasm even if the component that calls it wants to.
For example, imagine a component that shows the number of currently online users. This might have very simple UI but injects a service that handles counting the users, so is registered as singleton. Obviously if the system transitions this to wasm it will still technically function, but will only ever have a count of one since โsingletonโ means different things in wasm and server modes.
@richardhauer From my understanding, I don't think this would be an issue. In "auto" mode, which I think is the mode you're concerned about, the app would render using Blazor Server on the first visit, on a subsequent visit, it would render using Blazor WebAssembly. It wouldn't transition from server to WebAssembly during a single visit.
Based on what's been discussed so far, we'd be able to use multi targeting to setup the service registrations. Which would allow us to correctly scope a service based on where the app was running.
@chrissainty my reading of the thread is that the connection will change between pages, rather than between visits, and that a single page can mix both server and wasm components at the same time. Plausible then that a single service may be injected thatโs running in two different โscopesโ simultaneously in different components on the one page, insofar as a singleton service in wasm is really just scooped to the current user, even though itโs technically singleton
Hello Blazor United Team!
A few questions :)
Will Blazor .NET 8 provide the option to render server-side for web assembly applications using pages only in the client project?
I have a project that uses a Client Pages Service to API Controller to Server Repository architecture. With the release of .NET 8, I'm curious if there are any significant performance gains or new features that could benefit this type of architecture. Additionally, would I need to make any changes to my project in order to take advantage of these benefits and if so would any of them break any existing code?
I'm wondering if it's possible to build a server-side component and include it in a Blazor WebAssembly application. With the improvements in .NET 6, it seems like supporting HTTP/2 should be feasible if the architecture is in place?
(Is this what is being worked on here: #46353)
I've been hoping for the ability to load page content and maintain the theme on the server for over a decade now using .NET, so I'm thrilled to hear about these improvements. This release provides clarity on how the architecture for .NET should work and aligns with my expectations. As a developer who transitioned from a LAMP stack to .NET Framework, I've found it challenging at times, but being a C/C++ developer, I decided to give .NET C# a try.
I'm preparing to scale out a significant project that will use Maui, Server, Client, and Shared projects. As .NET 8 is more web-focused, I'm curious about what new steps are being made towards the ultimate goal of hybrid apps, specifically in terms of what can be shared with the Maui project. Aside from obvious components like models, what other elements should I consider including in the shared project to prepare for the future and create an efficient and organized project layout?
Sorry to hit with so many questions I am they all relate and are clear enough to understand. I am hearing a lot of Server-Side improvements for web which I look forward to using for future projects!
Thank you!
(P.S. Not sure if this was asked or discussed but will we be able to pick the priority of what gets loaded first or last? Does Blazor United choose or will developers set this when creating a page that uses both?)
Following up on some of the security concerns in this thread, I thought I'd chime in with my own scenario. I use Blazor Server to serve several websites running as applications atop Service Fabric. Each website retrieves its data using Fluxor state management via service remoting from adjacent microservices and as a result, I don't directly utilize HttpClient anywhere for lack of any internal HTTP calls. Authentication is handled by AAD B2C and resource-based authorization is performed by another microservice that runs before every other microservice call to validate that users are allowed to access what they're attempting to.
While I'm eager to see anything that means I don't have to maintain perpetual connections between clients and my server and speeds up responsiveness locally for data that's already retrieved and available, I'm mildly concerned about how the "automatic" mode will determine what's safe to put in the WASM build and keep server-side only. For example, while it'd be safe to shuffle the Fluxor state features out to the client as they're more local caches of already-retrieved data, if Blazor attempted to shuffle the remoting logic in the effects out to the WASM client (e.g. because there's no obvious HttpClient request boundary), all these requests will fail because the WASM client itself would access to the backing microservices outside of the cluster.
Similarly, the retrieved objects from the backend frequently have far more properties available on them than I intend to display in the user-facing website. Having some sort of differential on the data sent by the server to the client here to limit the potential for accidental disclosure of secrets would be useful.
In other words, just as there's an attribute in the demo to explicitly mark components as rendering in the server or the client, I would like to similarly mark methods in the code-behind/@code section to ensure that some of the logic remains strictly on the server and retrievable only through a SignalR circuit without ever being available for potential decompilation on the client-side.
Being able to benefit from the security and first-launch responsiveness guarantees of Blazor Server, but the reduced server load and local responsiveness of WASM would be an enormous improvement to Blazor, but please keep some of these less-common security considerations in mind while designing it. Thank you!
- The demo blew my head clean off! I want this yesterday.
- The name โBlazor Unitedโ would work equally well for MSโs soccer/football team.
In all seriousness, I tend to prefer the page-driven/SSR model because it better matches the semantics of HTTP itself and because it makes security concerns easier to manage. The ability to fluently re-use components in my pages will be a game changer.