Blazor Webassembly Project

I have been playing around with blazor webassembly generated from Vs2022 and then from Radzen Blazor tools.
I noticed vs2022 generates a index.html file under the wwwroot/css folder in the client; Radzen generates a _Host.cshtml under the server. Both of course work. Just wondering if any benefit to either.

Hi @Mark_Harned,

Unlike VS where you can create plain Blazor WebAssembly app, in Radzen, Blazor WebAssembly applications are always hosted since there will be no way otherwise to have database access through the OData service.

Thank you very much :grinning:

There is another reason - Blazor WebAssembly applications created with Radzen Blazor Studio come with prerendering enabled by default as opposed to ones created from VS.

Hi,
with prerendering, there are some problems (for me), if you redirect to the login page first (login page is loaded, but before you can insert the account/passwort there is a switch to the index.razor and then back to the login.razor). Is there a way to change the default behavior or any 'cookbook' what's to do to change it manually?

Thanks for help

Patric

Have you tried changing the rendering mode in _Host.cshtml ?

<component type="typeof(Admin.Client.App)" render-mode="WebAssembly" />

Hi Atanas,

i try your tip; and is also changed

<component type="typeof(HeadOutlet)" render-mode="WebAssembly" /> in the head part.

But the result was not optimal!

Please see the sreen capture in the attached file (i zipped the mp4).

First an empty sreen is shown, then the index.razor. Next the redirection to the login.razor; but first an empty screen.

After 'login' a redirection to the index.razor; also with an empty screen first.

Any idea what my error is?

I look for an app, that show a 'loading page with spinner' on start up or inital load and redirect to 'Login'; came back to 'index.razor' and start the work.

Is it possible, to show the 'loading div' on 'first render' and hide the 'loading div' after login and if all assemblies are loaded?

Thanks for your help
Blazor_Wasm_RenderMode_Webassembly.zip (449.2 KB)

Patric

Here is another thing you can try which seems to work better:

  1. Edit App.razor and delete the DefaultLayout attribute of the Router component.
  2. Create a new file called _Imports.razor in the Pages directory of your Client app. Add this line in that file @layout MainLayout.
  3. Rebuild and test

By default the Router component starts rendering the layout specified via DefaultLayout and then it checks for authorization. This sometimes leads to visible output from the MainLayout. Let us know if this works better for you. If it does as well as our tests show we can enable it by default in Radzen Blazor Studio.

By the way if you are using Radzen instead of Radzen Blazor Studio you will have to add the App.razor file to the code generation ignore list.

Hi Atanas,

i used Radzen Blazor Studio as a starting point and the generated code was realy helpfull. But as allways, if you need some extras, you have to change a lot and hopefully you made the right changes!

There is a _Import.razor on the same level as the App.razor (direct under root of the Client app and not in the Pages folder!). If i made the changes in the App.razor and this _Import.razor, the result is an empty page with no redirection to the login page!

I then delete the @layout-tag from this _Import.razor file, create a new one in the pages folder with only the @layout MainLayout as content and the result is better!

I now get an empty page on start (no index.razor is switch in and out!). Then a redirection to /Login with first show an empty page and then the layout/content of the Login page (with it's own LoginLayout.razor from the shared folder). After login redirect to / = Index.razor. But again first an empty screen and then the correct page without flickering (in dependence of the user account, i show and hide some items of the radzen panel menu from the main layout via variables that i set in the index.razor.cs ).

The empty pages are not so nice, but the missing flicker and the better start time are the rigth direction.

I show the new start in the attached file.

Any idea why these empty screens are shown, even if a html-content/layout for the page exists?

Thanks for your help,

Patric
Blazor_Wasm_Changed.zip (290.6 KB)

To be honest I am not sure why there is such a big initial delay. It definitely doesn't appear in a brand new Radzen application for sure.

Do you perform any background tasks during page or layout initialization? Perhaps this is the cause of the delay.

You can also try returning the render-mode back to WebAssemblyPrerendered (but keep the other changes).

<component type="typeof(Admin.Client.App)" render-mode="WebAssemblyPrerendered" />

Another thing you can do is add loading indicator:

  1. In _Host.cshtml replace <component type="typeof(Admin.Client.App)" ... /> with
    <div id="app">
        <div id="progress">
             Loading ...
        </div>
    </div>
    
    Optionally you can add a progress indicator instead of a simple text message:
    <div id="app">
        <div id="progress">
           <component type="typeof(Radzen.Blazor.RadzenProgressBarCircular)" param-ShowValue="false" param-Mode="Radzen.ProgressBarMode.Indeterminate" render-mode="Static" />
        </div>
    </div>
    
  2. Add some styling to center the loading content. Append this in the head tag in _Host.cshtml:
    <style>
       #progress {
           height: 100vh;
           display: flex;
           align-items: center;
           justify-content: center;
       }
    </style>
    
  3. Add this line in Client\Program.cs just after var builder = WebAssemblyHostBuilder.CreateDefault(args);
    builder.RootComponents.Add<App>("#app");
    

Hi Atanas,
first of all thanks for your support!
It is possible, that i had some inital work, that better is handeled in some later steps (like lazy loading assemblies or inject some servives if needed).

Do you remeber, we talk about 'global variables or dictionaries' and how to handle if needed in different pages. I'm not a friend of Parameters or Cascading Parameters so i used one 'LookupService' with a lot of variables to store infos and make them available on each page that need them. I also included some filled dictonaries for drop downs and so on. Maybe this part need some extra time; so i will try to splitt the structure to load only the variables i need in the beginning.

Now to your tips. I made the changes you suggested.

There is a short time that a white screen is shown, then the 'spinner' (RadzenProgressBarCircular) is shown. So far so good (or thats great)!

Btw. I used this statement for the 'spinner':

<div id="app">
    <div id="progress">
        <component type="typeof(Radzen.Blazor.RadzenProgressBarCircular)" param-Size="Radzen.ProgressBarCircularSize.Large" param-ShowValue="false" param-Mode="Radzen.ProgressBarMode.Indeterminate" render-mode="Static">
            <Template>Lade</Template>
        </component> 
    </div>
</div>
<style>
    #progress {
        height: 100vh;
        display: flex;
        align-items: center;
        justify-content: center;
    }
</style>

I placed it before the 'blazor-error-ui'-div. Any idea why the text in the template is not shown?

The switch to 'WebAssemblyPrerendered' result in the old problem; after login, the index.razor is shown in 'initial style' then a flicker and the correct version (with menu-items depending on the user) is shown.

So i switch back to 'WebAssembly'; the longer init time is ok, since the app is stable (since all necessary components are loaded).

But then suprise! There was a vertical scrollbar in the browser, that wasn't there before. And if i scroll down there is the same side content twice.

Any idea how this can happen or how i can suppress the second (same) content on the page?

I delete the entry 'builder.RootComponents.Add("#app");' in the Client\Program.cs; no effect.

I captured this strange behavior in the attached video. The doubling of the content also takes place on the login page.

Sorry to get such strange results!

Any help is welcome.

Thanks

Patric
Blazor_wasm_chang_2.zip (1.0 MB)

This happens if you keep
<component type="typeof(Admin.Client.App)" render-mode="WebAssemblyPrerendered" /> in _Host.cshtml

RadzenProgressBarCircular does not support templates.

I am attaching a sample application which shows everything described so far.
RBSWasm.zip (955.4 KB)

Hi Atanas,
first thanks for your example, that makes things clearer!

I will stay by render-mode="WebAssembly", but i had

<component type="typeof(HeadOutlet)" render-mode="WebAssembly" />

in the head tag and


in the body tag.

I delete the in the body tag and the duplicate content disappeared! That / you saved my day/week/month! Many thanks!

You wrote 'RadzenProgressBarCircular does not support templates'. I thought the component were the Blazor component, and there is an example with a text inside the 'spinner'; so i tried to use it.

And one last question: In your example there is a folder 'Filters' in the 'server-app'. What is the meaning of this folder?

Again thanks for your outstanding support!

Patric

If you check the code the component is rendered through the <component> element which does not support setting RenderFragment properties. Here is an excerpt from the documentation:

All types of parameters are supported, except:

  • For receiving a RenderFragment delegate for child content (for example, param-ChildContent="..."). For this scenario, we recommend creating a Razor component (.razor) that references the component you want to render with the child content you want to pass and then invoke the Razor component from the page or view with the Component Tag Helper.

So if you need a more complex loading content you can create a Blazor component in the Shared directory and use it instead:

<component type="typeof(Admin.Client.Shared.MyLoadingIndicator)" render-mode="Static" />

Client/Shared/MyLoadingIndicator.razor

<RadzenProgressBarCircular ShowValue="true" Mode="ProgressBarMode.Indeterminate">
   <Template>Loading ...
</Template>
</RadzenProgressBarCircular>

No idea - probably a remnant of some other tests.