Skip to content
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

Full stack web UI with Blazor #46636

Closed
danroth27 opened this issue Feb 14, 2023 · 129 comments
Closed

Full stack web UI with Blazor #46636

danroth27 opened this issue Feb 14, 2023 · 129 comments
Labels
area-blazor Includes: Blazor, Razor Components Epic Groups multiple user stories. Can be grouped under a theme. feature-full-stack-web-ui Full stack web UI with Blazor
Milestone

Comments

@danroth27
Copy link
Member

danroth27 commented Feb 14, 2023

In ASP.NET Core today, we have a couple of different ways to build web UI:

  1. 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.
  2. 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:

@danroth27 danroth27 added the feature-full-stack-web-ui Full stack web UI with Blazor label Feb 14, 2023
@mkArtakMSFT mkArtakMSFT added the area-blazor Includes: Blazor, Razor Components label Feb 14, 2023
@mammadkoma
Copy link

mammadkoma commented Feb 14, 2023

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.

@chrissainty
Copy link
Contributor

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?

@ahazelwood
Copy link

Blazor United brings a lot of functionality to a table, but I'm curious how it will handle the following scenarios:

  1. 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).
  2. 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?

@marcoatribeiro
Copy link

How will HttpContext be handled by Blazor United, as it is available in Blazor Wasm but not in Blazor Server?

@danroth27
Copy link
Member Author

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.

@danroth27
Copy link
Member Author

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.

@mammadkoma
Copy link

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?

@danroth27
Copy link
Member Author

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!

@danroth27
Copy link
Member Author

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.

@mihaimyh
Copy link

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.

@bub-bl
Copy link

bub-bl commented Feb 14, 2023

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?

@danroth27
Copy link
Member Author

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.

@gerneio
Copy link

gerneio commented Feb 15, 2023

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.

@ChristopherHaws
Copy link
Contributor

ChristopherHaws commented Feb 15, 2023

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. ^_^

@krzychacz1
Copy link

Will RenderMode.Auto detect that user is using an old browser (without support webassembly) and will keep ServerMode (no switch to webassembly) ?

@SteveSandersonMS
Copy link
Member

SteveSandersonMS commented Feb 15, 2023

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!

@gerneio
Copy link

gerneio commented Feb 15, 2023

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.

@RyoukoKonpaku
Copy link
Contributor

@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.

@gmurray81
Copy link

@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.

@Ponant
Copy link
Contributor

Ponant commented Feb 15, 2023

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).

@Ponant
Copy link
Contributor

Ponant commented Feb 15, 2023

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.

@simonziegler
Copy link

@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.

@SteveSandersonMS
Copy link
Member

SteveSandersonMS commented Feb 16, 2023

@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.

@simonziegler
Copy link

@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?

@gmurray81
Copy link

@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?

@gmurray81
Copy link

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.

@Xyncgas
Copy link

Xyncgas commented May 27, 2023

Just took a quick look for the progress microsoft has made on this we are almost there ey

@sushant-choudhary
Copy link

I'd love it if it's just called Blazor in .NET 8, after that we don't even need Blazor Server and Blazor Wasm to be thought of as 2 different frameworks, whether people employ Server/signalR or webassembly or SSR or any 2 or all 3 modes in their app is their discretion - the full feature set is called, simply, Blazor!

@michaelongithub
Copy link

@sushant-choudhary : completely support that

@andrewwilkin
Copy link

Would different pages and components be broken up into separate DLLs (code splitting similar to NextJS) to reduce the size of downloads in the background?

The bundle size of my WASM app is not particularly small :(

@andrewwilkin
Copy link

One thing I can't get my head around is how data and client side caching.

The app I have is data heavy and makes heavy use of an in memory cache. Was considering giving SQL Lite a go based on the demo sometime last year. How would this work in this new world?

@marinasundstrom
Copy link

marinasundstrom commented Jul 2, 2023

@andrewwilkin In any of the options there will essentially be 2 apps.

Single-project (A & B) affects developer experience while doing magic extracting files into their own projects at build-time - to produce 2 entirely different apps: Server (Host) and Client WASM (Browser).

The client app will not be able to access server app stuff. Not even loading it since it is not included in the client project. And the Blazor team will have to come up with the conventions for what file goes where.

The issue is in what experience makes most sense for developers.

Since it is a bit different from MAUI that essentially multi-targets platforms and builds excluding certain platform folders.

But C is transparent since it doesn’t hide the fact that there will be 2 apps. And it is more familiar to devs.

@WhitWaldo
Copy link

WhitWaldo commented Jul 2, 2023

I'm curious what the story looks like with regards to connecting to the back-end API. When developing a Blazor Server application, I don't have to spend a moment thinking about how to secure the connection between the front-end and the server as it's all handled for me. I simply inject the backend service that retrieves what it retrieves and it's ready to emit to the front-end. But in a Blaozr WASM application, I have to develop against a web API and intentionally utilize HttpClient.

In this hybrid model, what will this look like? If WASM were to just fall back to the SignalR route, it seems that persistent connection would negate the dependency on the persistent connections front, but any use of HttpClient isn't typical of a server-side API (assuming it's not contacting still another API). Is anyone able to speak to the idea of how this might be handled here?

@SteveSandersonMS
Copy link
Member

Would different pages and components be broken up into separate DLLs (code splitting similar to NextJS) to reduce the size of downloads in the background?

No, the benefit would be negligible. 80%+ of the size of your app is likely to be the core .NET runtime which would be required in all cases. And if you have some massive dependencies that are only needed in certain pages, you can already use the lazy loading feature to avoid downloading those in other cases.

The app I have is data heavy and makes heavy use of an in memory cache. Was considering giving SQL Lite a go based on the demo sometime last year. How would this work in this new world?

You're certainly free to do that if it makes sense for your app (e.g., if you perform a lot of complex queries over data that's constrained and safe enough to transfer entirely into the browser).

I'm curious what the story looks like with regards to connecting to the back-end API.

One very mainstream use case will be having different pages using different hosting models. In that case, you use whichever data access strategy matches the page you're working on. In the case where parts of your site should work on both Server and WebAssembly models, I'd recommend implementing an abstraction over them, such as an ICustomerRepository interface with implementations for each of the hosting models.

@WhitWaldo
Copy link

I'm curious what the story looks like with regards to connecting to the back-end API.

One very mainstream use case will be having different pages using different hosting models. In that case, you use whichever data access strategy matches the page you're working on. In the case where parts of your site should work on both Server and WebAssembly models, I'd recommend implementing an abstraction over them, such as an ICustomerRepository interface with implementations for each of the hosting models.

Would the data access strategy be component- or page-specific? I'd much rather retain the current Blazor Server data access model as much as possible since 1) it takes a significant attack/vulnerability surface off the plate to not have a public API and 2) it eliminates a considerable amount of work to build the API abstraction on top of the backend (and to maintain public/private shapes of objects and the mapping between each).

If I were able to configure that all data access explicitly use the Blazor Server model (e.g. indicate that there is no API fallback) but that the connections should be done sparingly (e.g. for data retrieval/posting or cache refreshes) and the app otherwise run locally via WASM, that would be an incredible capability.

@Webreaper
Copy link

Maybe I'm missing something, but why do people repeatedly keep saying that Blazor Server is more secure because it doesn't have APIs. Can somebody explain why a well designed back-end-for-the-front-end API server is any less secure than Server rendered pages that show identical data?

@LuohuaRain
Copy link

Maybe I'm missing something, but why do people repeatedly keep saying that Blazor Server is more secure because it doesn't have APIs. Can somebody explain why a well designed back-end-for-the-front-end API server is any less secure than Server rendered pages that show identical data?

APIs can be replayed or manually constructed, which can lead to security vulnerabilities. In contrast, Blazor Server uses server-side rendering and does not expose APIs, which can better protect data security easily.

@Webreaper
Copy link

Webreaper commented Jul 3, 2023

APIs can be replayed or manually constructed, which can lead to security vulnerabilities. In contrast, Blazor Server uses server-side rendering and does not expose APIs, which can better protect data security easily.

Still not getting it. If you encrypt your APIs and only expose the data you're going to be rendering on the UI anyway, what difference does it make? The implication is that APIs can't be secured easily - which is a fallacy with modern frameworks like ASP.net.

And if you're choosing Blazor Server because you think it'll implicitly make the data you're rendering on the UI secure without you having to think about the design or the security, then you're already in trouble.

@WhitWaldo
Copy link

WhitWaldo commented Jul 3, 2023

Maybe I'm missing something, but why do people repeatedly keep saying that Blazor Server is more secure because it doesn't have APIs. Can somebody explain why a well designed back-end-for-the-front-end API server is any less secure than Server rendered pages that show identical data?

If you encrypt your APIs and only expose the data you're going to be rendering on the UI anyway, what difference does it make?

Security is one part of it. Assuming you're using Blazor WASM, you have to carefully consider what information you provide back to the client, knowing that even if the connection to the user is as secure as you can make it, they can potentially peek inside anything that runs on their end and read anything you've sent externally. As a result, you have to maintain separate records for internal vs external access and the mapping between the two to prevent accidental disclosure. Perhaps you also do client-side as well as server-side validation of user data necessitating a few round trips to prevent malicious data from being submitted.

With the Blazor Server model, I can skip this API layer entirely which provides me with some significant benefits. I don't need to maintain a separate record for internal vs external data because if I don't explicitly reference the member value in a page/component, it's not included in the HTML diff to the client. Who cares if the user peeks inside the data coming their way? The only thing sent their way is exactly what's going to show up on their rendered page and nothing more. All client-side validation is server-side validation, so unless I want to do something fancy with JavaScript, I needn't have duplicate validation logic.

And a minor point - where Blazor WASM is agnostic about what the backend is written in because it's just interfacing with a REST API, it's awfully convenient being able to work with the same objects on my backend and front-end; again, no mapping to a public variation, much less between languages.

But further, I personally assign significant value to the development time I haven't had to spend writing and maintaining the API abstraction between my back-end services and the front-end client. I'll cede you that ASP.NET Core makes it fairly easy to secure an API today, but there's nothing quite as freeing as not having to write it at all.

@sajjadarashhh
Copy link

sajjadarashhh commented Jul 19, 2023

we can hope can be choose whole Wasm project in Maui Application in future and remove unnecessary seperated projects for razor components and etc...?

@marinasundstrom
Copy link

@sajjadarashhh The unification is about Blazor on the Server, and not MAUI Blazor.

MAUI Blazor is rendered directly by the MAUI app. MAUI doesn't use WebAssembly since it is sandboxed in a browser, and can't access the native platform.

I was talking to a person yesterday who asked me how to access MAUI APIs from Razor Class Libraries. That is not as simple since the RCL has no reference to MAUI.

Is that what you have problems with?

@sajjadarashhh
Copy link

I know this issue is about blazor on the server and wasm
But it can be very nice if we have a one project that release Android, ios, web, desktop and etc...
Past year when i try to migrate my pages and project to maui blazor that have been breaking changes thats need hard working on project, some issues is about threads in webView that freezed my project

@WhitWaldo
Copy link

@sajjadarashhh I would suggest raising that in a separate issue

@nvmkpk
Copy link

nvmkpk commented Jul 20, 2023

The whole idea of using separate projects is to reuse the components in MAUI and web projects. If that is not needed, then razor components can reside in the same MAUI project and these components can access MAUI API directly. If not, then it is best to separate MAUI dependent code into another MAUI class library and inject them to the razor class library through DI.

@Xyncgas
Copy link

Xyncgas commented Jul 20, 2023

we can hope can be choose whole Wasm project in Maui Application in future and remove unnecessary seperated projects for razor components and etc...?

MAUI.Blazor is a way to run Blazor, .NET talks to browser instead of MAUI, allowing you to use api not supported on browser + other stuffs.

People's projects are so big, a company got fourty fivety sixty hundreds of projects. They organize it nicely in solution folders to use it in Blazor. You can make sure they know about blazor / MAUI by writing them in a {blazor class library} or {MAUI class library}

@qrzychu
Copy link

qrzychu commented Jul 21, 2023

The whole idea of using separate projects is to reuse the components in MAUI and web projects. If that is not needed, then razor components can reside in the same MAUI project and these components can access MAUI API directly. If not, then it is best to separate MAUI dependent code into another MAUI class library and inject them to the razor class library through DI.

You can always make use of Dependency Injection, you define an interface in a shared project, inject it into the blazer component. Then you implement it in the Maui project, make use of android API, then register the implementation in the services collection.

@sajjadarashhh
Copy link

sajjadarashhh commented Jul 22, 2023

All of them just a ways to solved that problems i tell above
But why theres issue exist on migrating from wasm to maui?
for example InProccessJsRuntime not working in maui
And we cant call js methods at synchronous methods because when we call Task.Result Maui project is freezed

@CrahunGit
Copy link

CrahunGit commented Aug 5, 2023

Would different pages and components be broken up into separate DLLs (code splitting similar to NextJS) to reduce the size of downloads in the background?

No, the benefit would be negligible. 80%+ of the size of your app is likely to be the core .NET runtime which would be required in all cases. And if you have some massive dependencies that are only needed in certain pages, you can already use the lazy loading feature to avoid downloading those in other cases.

The app I have is data heavy and makes heavy use of an in memory cache. Was considering giving SQL Lite a go based on the demo sometime last year. How would this work in this new world?

You're certainly free to do that if it makes sense for your app (e.g., if you perform a lot of complex queries over data that's constrained and safe enough to transfer entirely into the browser).

I'm curious what the story looks like with regards to connecting to the back-end API.

One very mainstream use case will be having different pages using different hosting models. In that case, you use whichever data access strategy matches the page you're working on. In the case where parts of your site should work on both Server and WebAssembly models, I'd recommend implementing an abstraction over them, such as an ICustomerRepository interface with implementations for each of the hosting models.

For different loading strategies I use mediatr with different handlers on different projects. I confirm it works fine.

@wtgodbe wtgodbe modified the milestones: 8.0, 8.0.0 Oct 3, 2023
@mkArtakMSFT
Copy link
Member

Closing as the work we've planned to do for .NET 8 is done at this point. Any remaining items will be considered for a future release.

@ghost ghost locked as resolved and limited conversation to collaborators Nov 3, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-blazor Includes: Blazor, Razor Components Epic Groups multiple user stories. Can be grouped under a theme. feature-full-stack-web-ui Full stack web UI with Blazor
Projects
None yet
Development

No branches or pull requests