3
votes

Have a Web Forms app that I would like to gradually port, on a page by page basis, to Blazor WebAssembly by embedding Blazor into Web Form pages the way it is possible with Angular.

Published the Blazor app to the Web Forms project under a subdirectory called "Blazor". If I run the Web Forms app and hit http://localhost:1234/Blazor the Blazor app runs fine (after editing the Blazor index.html => <base href="/Blazor/" />). However, when I try to embed Blazor in a Web Form page it doesn't work. The web form page asp:content contains what the Blazor index.html page contains:

<%@ Page Title="EmbedTest" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="EmbedTest.aspx.cs" Inherits="WebFormBlazor.EmbedTest" %>

<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
    <app>Loading...</app>

    <div id="blazor-error-ui">
        An unhandled error has occurred.
        <a href="" class="reload">Reload</a>
        <a class="dismiss">????</a> 
    </div>

    <script src="/Blazor/wwwroot/_framework/blazor.webassembly.js"></script>
</asp:Content>

When I go to http://localhost:1234/EmbedTest the page displays: Loading... An unhandled error has occurred. Reload ????

And in the console the following error message: Uncaught SyntaxError: Unexpected token '<' blazor.webassembly.js:1

This approach does work with Angular. What am I missing in trying to do this with Blazor WebAssembly?

Update: As per Mister Magoo, it was not downloading blazor.webassembly.js but actually downloading the index.html which explains the error message.

Changed the path in the page from /Blazor/wwwroot/_framework/blazor.webassembly.js to /Blazor/_framework/blazor.webassembly.js in the Web Form page and now downloads the script but experiences new error. Gives 404 Not Found for blazor.boot.json.

Blazor.webassembly.js doesn't know the base href should be /Blazor/ and tries to fetch blazor.boot.json from localhost:1234/_framework/blazor.boot.json instead of localhost:1234/Blazor/_framework/blazor.boot.json.

So next issue: How to tell blazor.webassembly.js that its base href should be something other than '/' (in my case '/Blazor/')?

2
Check the network tab when you load the page - does the blazor.webassembly.js file get served correctly? (My guess is no because the path looks odd - remove wwwroot) - Mister Magoo
Yes, all the necessary files get served with http status 200 including blazor.webassembly.js - Coding Dude
But is it actually returning the correct file, not just the correct status? Can you download it manually? - Mister Magoo

2 Answers

1
votes

If you want anything more complex than just one blazor page inside one web forms page I suggest you use an iframe to host the blazor app inside your web forms app. This will make them independent and you don't run the risk of fetching assets twice, and/or getting invalid HTML and/or DOM manipulations on the webforms page to hurt the blazor app.

Generally, you should also keep in mind that WebForms does not run on .NET Core (or .NET 5 and later), while Blazor runs only on .NET Core 3 or .NET 5 (or later) so this mix of technologies can bite you later.

If you want to move page by page and you won't have anything else but the blazor app - the PoC above should work out as soon as you can ensure correct paths and base paths (if you have folders in your webforms app this could throw off the blazor routing and paths). Moreover, firing up the wasm app is slow for the client, so you may want to consider a server-side blazor page instead (which will require an iframe for sure).

EDIT: You may find useful this book MS are making for WebForms -> Blazor migration https://docs.microsoft.com/en-us/dotnet/architecture/blazor-for-web-forms-developers/

0
votes

Got a proof-of-concept working:

  1. Generated the default Blazor WebAssembly project.
  2. Built the project and copied the output _framework directory and its contents into the Web Forms project.
  3. Added the following from the Blazor web.config to the Web Forms web.config:
  <system.webServer>
    <staticContent>
      <remove fileExtension=".dat" />
      <remove fileExtension=".dll" />
      <remove fileExtension=".json" />
      <remove fileExtension=".wasm" />
      <mimeMap fileExtension=".dll" mimeType="application/octet-stream" />
      <mimeMap fileExtension=".dat" mimeType="application/octet-stream" />
      <mimeMap fileExtension=".json" mimeType="application/json" />
      <mimeMap fileExtension=".wasm" mimeType="application/wasm" />
    </staticContent>
    <httpCompression>
      <dynamicTypes>
        <add mimeType="application/octet-stream" enabled="true" />
        <add mimeType="application/wasm" enabled="true" />
      </dynamicTypes>
    </httpCompression>
  </system.webServer>
  1. Edited the contents of the Counter.aspx Web Form page to be:
<%@ Page Title="Counter" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="false" CodeBehind="Counter.aspx.cs" Inherits="WebFormBlazor.Counter" %>

<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
    <app></app>

    <script src="_framework/blazor.webassembly.js"></script>
</asp:Content>
  1. Edited the Blazor MainLayout.razor to just:
@inherits LayoutComponentBase
<div>
    @Body
</div>
  1. Run the Web Forms project and go to http://localhost:1234/Counter and the Web Form Counter page comes up with the Blazor Counter page embedded.