Combining Blazor and Razor Pages in one ASP.NET Core 3 app

The translation of the article was prepared in anticipation of the start of the "C # ASP.NET Core Developer" course .










In this article, I'll show you how you can add Blazor-based pages to an existing Razor Pages app.







Foreword



Blazor will go gold in two weeks . Many things in the project are still subject to quite dramatic changes, and the latest Preview 9 has made the interaction between Razor Pages and Blazor components much more difficult: it is no longer possible to pass parameters from a Razor page to a Blazor component using Html.RenderComponentAsync. This may change in the future, but it is likely that in .NET Core 3.0 it will appear with this limitation.



If you still want to enhance your existing Razor Pages app with Blazor magic, one solution is to completely create your pages in Blazor. In this article, I'll show you how you can add Blazor Pages to an existing Razor Pages app, where parts of the app are built using Razor Pages and others using Blazor Pages. The layout is the same for both types of pages .



Step one: support for Blazor



So, we have an existing Razor Pages application that has been converted to .NET Core 3.







First, you need to add Blazor support to your application. This support will allow you to render Blazor components from a Razor page. The official documentation walks you through the process completely, but here's a quick rundown.



Startup.cs:



We need to add Services.AddServerSideBlazorto ConfigureServicesand endpoints.MapBlazorHubin Configure:







_Layout.cshtml : The Blazor



JS library is needed to connect Blazor on the server side. It can be added to _Layout.cshtml:







?

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


_Imports.razor:



We also need a new file named _Imports.razor. It must be added to the Pages folder:







_Imports.razorused to set the using statements for your Blazor components. You can start with the following



:?

@using System.Net.Http
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.JSInterop
@using Microsoft.AspNetCore.Components.Web


And that's all . Our app now supports Blazor. Can we verify this by copying the classic Counter component into our application







?

@page "/counter"
 
<h1>Counter</h1>

<p>Current count: @currentCount</p>
 
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
 
@code {
    int currentCount = 0;
 
    void IncrementCount()
    {
        currentCount++;
    }
}


And edit Privacy.cshtmlto include the Counter component:



<a href="https://mikaelkoskinen.net/post/combining-razor-blazor-pages-single-asp-net-core-3-application#">?</a>
@page
@model PrivacyModel
@{
    ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
 
<p>Use this page to detail your site's privacy policy.</p>
 
<component>@(await Html.RenderComponentAsync<Counter>(RenderMode.Server))</component>


Now, when we launch the application, a working Counter should appear on our page:







In the next part of this article, I'll show you how you can modify your Razor Pages application so that instead of just adding components to existing pages, you can create complete Blazor pages.



Step two: support for Blazor Pages



Our Blazor component defines a route โ€œ/counterโ€:







But following it doesn't work:







Our goal is to get routing to Blazor pages to work. And we want Blazor pages to use the same layout as Razor pages. We'll need a few things to do this, starting with the Router .



App.razor:



Create a new file App.razorin the folder
Pages
:







Router component is defined in App.razor:



?



@using Microsoft.AspNetCore.Components.Routing
 
<Router AppAssembly="typeof(Program).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="routeData"/>
    </Found>
    <NotFound>
        <h1>Page not found</h1>
        <p>Sorry, but there's nothing here!</p>
    </NotFound>
</Router>


Router automatically scans all Blazor components using the page directive and adds routes to them.



_Host.cshtml:



We also need a page to host the Blazor pages. It can be called whatever you want, but Blazor templates are used by default _Host.cshtml, which is fine for us (as well as any other). In _Host.cshtmlwe can define a layout, which in our case will be the same as for Razor pages.







_Host.cshtmlcontains the call Html.RenderComponentAsync:



?



@page "/blazor"
 
@{
    Layout = "_Layout";
}
 
<app>
    @(await Html.RenderComponentAsync<App>(RenderMode.Server))
</app>


Startup.cs:



And finally, a small addition to the method Configure Startup.cs. Earlier we added MapBlazorHub, and now we need to add a call MapFallbackToPagepointing to the new one _Host.cshtml:







And that's it! Now we just need to test our setup. Add a Blazor Page Counter (Counter) to your layout by editing Pages/Shared/_Layout.cshtml:







When we launch the app, we see a working Blazor page in our Razor Pages app:







And we didn't break support for adding Blazor components to Razor Pages:







Notes



A couple of things to note:



  • Blazor routes only work when they point to the root. If โ€œ/ counterโ€ is changed to, for example, the โ€œ/products/counterโ€page will not be able to load the required one blazor.server.js. We'll get a 404 instead. It should be possible to change the script tag so that it can load the required script regardless of location, but that seems to have changed from pre-8 to pre-9 and I couldn't get it to work. Here is a 404 screenshot showing the problem:
  • If you manage to load the script, you will probably run into the same problems with Blazor hub: scripts try to find hub in / products / blazor instead of blazor. To work around this, you can manually initiate a connection between the server and browser:


?



<script src="~/_framework/blazor.server.js" autostart="false"></script>
<script>
  Blazor.start({
    configureSignalR: function (builder) {
      builder.withUrl('/_blazor');
    }
  });
</script>


Sample code



Sample code for this project is available on GitHub .






Want to know more about our course? Here you go .






Read more:









All Articles