5
votes

I've edited the whole question for better understanding

My sample solution consists of 2 Projects

  • MVC App + Blazor Server
  • Razor Class Library

The Razor Class Library has a very simple Component "Awesome.razor":

<h3>@name</h3>

<button @onclick="@(() => name = name.ToUpper())">Upper case me</button>

@code {
    string name = "Mr. Blazor";

}

The MVC App has an Home/Index.cshtml:

That looks like this:

<div id="MyComponent">
    @(await Html.RenderComponentAsync<Awesome>(RenderMode.ServerPrerendered))
</div>

If I run the App (<root>/home/index)

I can click on the button and the Awesome component works.

Can I use the same technique (Html.RenderComponentAsync) but instead of using Blazor Server to use Blazor WebAssembly?

I did some attempt to make it work (try/error by using the template of Blazor WebAssembly and integrating it with MVC App), but wasn't able to make it work. I'm wondering if I did something wrong or if RendercomponentAsync can only be used in combination with Blazor Server.

The whole source code can be found here (without my attempt of WebAssembly): https://github.com/geeForceOne/MvcWithBlazor

UPDATE

Apparently there's RenderComponentAsync support in Blazor WebAssembly.

I managed to partially achieve what I wanted (credits to Daniel Roth) by adapting his sample app to this https://github.com/geeForceOne/BlazorWebAssemblyWithPrerendering.

I tried different things with try n error and came up with this solution:

In Startup.cs of Blazor.Client Project I registered two components:

app.AddComponent<Counter>("counter");
app.AddComponent<Awesome>("awesome");

Then I created two Razor Pages MyTest.cshtml and MyTest2.cshtml. While MyTest.cshtml does exactly what I want and works correctly:

<awesome>
    @(await Html.RenderComponentAsync<Awesome>(RenderMode.Static))
  </awesome>

<counter>
    @(await Html.RenderComponentAsync<Counter>(RenderMode.Static))
</counter>

<script src="_framework/blazor.webassembly.js"></script>

It does not work on on MyTest2.chshtml

@* To make this work, you need to 
    call
        app.AddComponent<Awesome>("awesome"); 
    before 
        app.AddComponent<Counter>("counter");
    in
        BlazorWebAssemblyWithPrerendering.Client.Startup
*@

<awesome>
    @(await Html.RenderComponentAsync<Awesome>(RenderMode.Static))
</awesome>


<script src="_framework/blazor.webassembly.js"></script>

My quesion: Am I on the right path (what do I need to change to make it work properly)? Or can I run just one Component this way as per original sample of Daniel Roth?

1
I've removed my old answer and added a new one after seeing your sample app...user12207343

1 Answers

3
votes

Having seen your app and doing some investigation, this my new answer:

You cannot execute a Razor Component embedded in a Razor Pages App or an MVC App on the browser. In other words, your component is not executed with WebAssembly.

Even if you reference in your app a Blazor WebAssembly App, the referenced components do not run on the browser using WebAssembly. I've created the default Blazor WebAssembly App in your MVC solution, and added a reference to it in your MVC project. I then rendered the Counter in the Index.Html and it worked well. But the Counter Component was not executed on the Browser using WebAssembly.

When I used this version:

@(await Html.RenderComponentAsync<MyBlazorAssembly.Pages.Counter>(RenderMode.ServerPrerendered))

the Counter component was interactive, incrementing and displaying the new value. The same behavior is produced when I used RenderMode.Server. In both case, the Counter component is interactive due to the RenderMode selected, and the component is prerendered on the server. When RenderMode.Static is selected, the component is rendered as static Html, and no interactivity is possible.

This is exactly what had happened when you tried to run your Awesome component on WebAssembly. Unfortunately, it is rendered as static Html, and when you click the button, no response is elicited... the event handler is not triggered, no lambda expression is executed, and there is no way to uppercase your text (you can do that with pure JavaScript).

You can read here about the rendering modes.

Please, if I was not clear enough don't hesitate to ask me any question...