Search code examples
asp.net-coreblazorrazor-pagesblazor-webassembly

How to host Blazon in Razor Pages application


The "standard" Blazor WASM application is hosted inside a static HTML page; e.g., index.html. Due to certain requirements, I want to host Blazor inside a Razor pages application.

What I did is starting from a "standard" Blazor WASM application, removed the static files, because I do not need them, moved the content of index.html to the Wasm.cshtml, and change endpoints.MapFallbackToFile("index.html"); to endpoints.MapFallbackToPage("/Wasm");.

Everything seemed to be working as expected; I can run the application and navigate to the different pages I have in Blazor.

However, things fall apart when I try to access a page using its URL; e.g., http://mysite/counter, where /counter is a page in Blazor, and I get the following error:

An unhandled exception occurred while processing the request.
AmbiguousMatchException: The request matched multiple endpoints. Matches:

/Wasm
/Wasm

Can someone help me identify what I am doing wrong?

P.S.:

  • I looked at some answer here, but all that I found is people talking about Blazor Server.
  • I am using .NET 3.1 and Blazor 3.2.
  • I want to use my Razor Pages application to host/serve Blazor WASM not mixing them in a single project. They as still 2 different projects.
  • I am totally aware that Blazor WASM and Razor Pages are unrelated technologies. I am not trying to integrate them. I am only trying to server Blazor WASM files from a dynamic page. If it makes you think better about what I am trying to achieve, think about Razor Pages as any server-side technology; PHP, Node, or whatever, then apply this to the routing issue that I am trying to resolve.

Solution

  • OK, based on what you've written so far take a look at ShaunCurtis/Blazor-Experimental on Github. It's a temporary Repo for some experimental code. Ignore BlazorTest. The startup project is Blazor-Experimental.

    The default page is a normal razor page. It's a mixed Razor, Blazor Server and Blazor WASM site. All the WASM routes look like wasm/fetchdata, so we have different URLs for all the Server and WASM "Pages".

    Startup differentiates URLs using multiple endpoints, so any URL that is in the "scope" of the Blazor WASM application gets set to _wasm.cshtml. Anything else that can't be mapped directly is in the "scope" of the Blazor Server Application at _host.cshtml. All plan Razor pages on the site get served as is. You don't need the Blazor Server bit at all, just fallback to the default Razor page.

      endpoints.MapFallbackToPage("/wasm/{**segment}", "/_wasm");
      endpoints.MapFallbackToPage("/_Host");
    

    To summarise the answer:

    • Create a Blazor WASM project. You can copy the one from Blazor Hosted template.
    • Reference the project from the Razor Pages project.
    • Create the page that will host Blazor WASM; e.g., Wasm.cshtml, and make sure the page route is not set; i.e., only @page at the top of the page, so that it takes the default route /wasm.
    • Copy the code from index.html in the Blazor WASM project into Wasm.cshtml.
    • Important: If you are using your own layout, it is important to have <base href="/" /> on the page or the layout <head> section.
    • Remove all the static files from form the Blazor WASM project; e.g., index.html.
    • Remove all *.razor pages from the Blazor WASM project.
    • Add Wasm.razor to the Blazor WASM project and set its route to /wasm; i.e., @page "/wasm".
    • In Startup.cs in the Razor Pages project, add app.UseBlazorFrameworkFiles(); after app.UseStaticFiles();.
    • Also in the same Startup.cs, add endpoints.MapFallbackToPage("/wasm/{**segment}", "/wasm"); inside app.UseEndpoints() lambda.
    • Now run the application and navigate to /wasm. You should see the content of your Wasm.razor in addition to whatever layout you have set. You will get the same result when you paste the URL http://whateveryoursiteis/wasm.