What is the best practice for moving over the MAUI Blazor Hybrid components to an ABP MVC site, please? We have created the MAUI Blazor app, and want to quickly add it to the MVC solution. Hoping others have done this before and you would know best pattern to follow. Thanks in advance!
4 Answer(s)
-
0
Hi @JeffMH
The best and most sustainable way to reuse Blazor components from your MAUI Blazor Hybrid application in an ASP.NET Zero MVC project is to use a Razor Class Library (RCL) and add Blazor Server hosting capabilities to your existing MVC application.
Create a Razor Class Library (RCL) for Shared Components
If you haven't already, the first step is to move all shared components into a separate project.
- Add a new Razor Class Library project to your existing solution. For example, name it
MyProject.Shared.Components. - Move all reusable
.razorcomponents, their corresponding C# code-behind files (.razor.cs), and any component-specific CSS/JS files (located under thewwwrootfolder) from your MAUI Blazor project to this new RCL project. - Now, both your MAUI project and your ASP.NET Zero MVC project will add a reference to this RCL project.
Configure the ASP.NET Zero (MVC) Project to Host Blazor
Your MVC project needs the Blazor Server infrastructure to be able to render Blazor components. This does not break your existing MVC structure; it simply adds a new capability to it.
Add Required Services: In your
Program.csfile (orStartup.csin older .NET Core versions), add the following line where your services are configured:// Next to lines like builder.Services.AddControllersWithViews(); builder.Services.AddServerSideBlazor();Add the Blazor Hub Endpoint: In the same file, where the application's request pipeline is configured, add
MapBlazorHub:// After the app.UseRouting(); line app.UseEndpoints(endpoints => { // Your existing endpoints... endpoints.MapBlazorHub(); endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); // ... other endpoints });If you are using minimal APIs (with
app.Map...syntax), the configuration would look like this:// Next to the app.MapControllerRoute(...); line app.MapBlazorHub();Add the Required JavaScript File: Open the main layout file in your ASP.NET Zero project (
_Layout.cshtml) and add the Blazor JavaScript file just before the closing</body>tag.<script src="_framework/blazor.server.js"></script> </body> </html>
Use Blazor Components in MVC Views
Your MVC project is now ready to render Blazor components. To do this, you will use the
Component Tag Helper.Import Namespaces: To make it easier to use your components, add the namespaces for your RCL project and the Tag Helpers to the
_ViewImports.cshtmlfile.@using MyProject.Shared.Components // Your RCL project's namespace @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @addTagHelper *, MyProject.Web.Mvc // Your MVC project's name (if applicable)Render the Component: Now, inside any
.cshtmlview file, you can call your Blazor component like this:<h2>This is an MVC View</h2> <p>Below is a component rendered from Blazor:</p> <div id="my-blazor-component"> <component type="typeof(MyAwesomeComponent)" render-mode="ServerPrerendered" /> </div> @* If you want to pass parameters to your component: *@ <component type="typeof(UserProfileCard)" render-mode="ServerPrerendered" param-UserId="@Model.UserId" />
type: The full type of the component you want to use.render-mode:ServerPrerendered: When the page first loads, the component's HTML is generated on the server and sent in the initial response. After the page loads in the browser, Blazor establishes a SignalR connection to make the component interactive. This is usually the best option for SEO and initial load performance.Server: Only a placeholder is rendered when the page loads. The component's content is loaded after the SignalR connection is established.
- Styling (CSS): ASP.NET Zero comes with the Metronic theme. To ensure your Blazor components look consistent with this theme, make sure to use Metronic's CSS classes directly within your components. If you add your own styles to the
wwwrootfolder in the RCL, you must ensure these styles are also included in the MVC project. - Authentication and Authorization: Since Blazor Server runs on the existing
HttpContext, the user's identity flows automatically to the components. You can use the[Authorize]attribute and theAuthenticationStateProviderin your components just as you would in the MVC project. - JavaScript Interaction (JS Interop): If your Blazor components need to interact with jQuery or other JavaScript libraries used by ASP.NET Zero, you will need to do this through the
IJSRuntimeservice.
Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image) - Add a new Razor Class Library project to your existing solution. For example, name it
-
0
Hi @JeffMH
The best and most sustainable way to reuse Blazor components from your MAUI Blazor Hybrid application in an ASP.NET Zero MVC project is to use a Razor Class Library (RCL) and add Blazor Server hosting capabilities to your existing MVC application.
Create a Razor Class Library (RCL) for Shared Components
If you haven't already, the first step is to move all shared components into a separate project.
- Add a new Razor Class Library project to your existing solution. For example, name it
MyProject.Shared.Components. - Move all reusable
.razorcomponents, their corresponding C# code-behind files (.razor.cs), and any component-specific CSS/JS files (located under thewwwrootfolder) from your MAUI Blazor project to this new RCL project. - Now, both your MAUI project and your ASP.NET Zero MVC project will add a reference to this RCL project.
Configure the ASP.NET Zero (MVC) Project to Host Blazor
Your MVC project needs the Blazor Server infrastructure to be able to render Blazor components. This does not break your existing MVC structure; it simply adds a new capability to it.
Add Required Services: In your
Program.csfile (orStartup.csin older .NET Core versions), add the following line where your services are configured:// Next to lines like builder.Services.AddControllersWithViews(); builder.Services.AddServerSideBlazor();Add the Blazor Hub Endpoint: In the same file, where the application's request pipeline is configured, add
MapBlazorHub:// After the app.UseRouting(); line app.UseEndpoints(endpoints => { // Your existing endpoints... endpoints.MapBlazorHub(); endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); // ... other endpoints });If you are using minimal APIs (with
app.Map...syntax), the configuration would look like this:// Next to the app.MapControllerRoute(...); line app.MapBlazorHub();Add the Required JavaScript File: Open the main layout file in your ASP.NET Zero project (
_Layout.cshtml) and add the Blazor JavaScript file just before the closing</body>tag.<script src="_framework/blazor.server.js"></script> </body> </html>
Use Blazor Components in MVC Views
Your MVC project is now ready to render Blazor components. To do this, you will use the
Component Tag Helper.Import Namespaces: To make it easier to use your components, add the namespaces for your RCL project and the Tag Helpers to the
_ViewImports.cshtmlfile.@using MyProject.Shared.Components // Your RCL project's namespace @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @addTagHelper *, MyProject.Web.Mvc // Your MVC project's name (if applicable)Render the Component: Now, inside any
.cshtmlview file, you can call your Blazor component like this:<h2>This is an MVC View</h2> <p>Below is a component rendered from Blazor:</p> <div id="my-blazor-component"> <component type="typeof(MyAwesomeComponent)" render-mode="ServerPrerendered" /> </div> @* If you want to pass parameters to your component: *@ <component type="typeof(UserProfileCard)" render-mode="ServerPrerendered" param-UserId="@Model.UserId" />
type: The full type of the component you want to use.render-mode:ServerPrerendered: When the page first loads, the component's HTML is generated on the server and sent in the initial response. After the page loads in the browser, Blazor establishes a SignalR connection to make the component interactive. This is usually the best option for SEO and initial load performance.Server: Only a placeholder is rendered when the page loads. The component's content is loaded after the SignalR connection is established.
- Styling (CSS): ASP.NET Zero comes with the Metronic theme. To ensure your Blazor components look consistent with this theme, make sure to use Metronic's CSS classes directly within your components. If you add your own styles to the
wwwrootfolder in the RCL, you must ensure these styles are also included in the MVC project. - Authentication and Authorization: Since Blazor Server runs on the existing
HttpContext, the user's identity flows automatically to the components. You can use the[Authorize]attribute and theAuthenticationStateProviderin your components just as you would in the MVC project. - JavaScript Interaction (JS Interop): If your Blazor components need to interact with jQuery or other JavaScript libraries used by ASP.NET Zero, you will need to do this through the
IJSRuntimeservice.
Thank you for the quick response!
Are there considerations we need to make for the WebRequestExecutor, please? Since we were calling the APIs that way before - do we continue using that same pattern from the MVC site?
Thanks!
Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image) - Add a new Razor Class Library project to your existing solution. For example, name it
-
0
Also, could we add a /BlazorApp route and use a MainLayout like the typical Blazor approach and host all our components with Blazor handling everything there? If so, can you provide an example? That may make things much easier, rather than having to use the Blazor as components in CSHTML views with MVC routes. Looking forward to your thoughts. Thanks!
Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image) -
0
Hi @JeffMH
No, you should not use
WebRequestExecutorto call your APIs from Blazor components running on the ASP.NET Zero MVC site. It is a pattern designed specifically for client side applications.- The Purpose of
WebRequestExecutor: This service is designed for client applications (like MAUI, Angular) to make secure HTTP requests to your backend API. It simplifies development by automatically attaching necessary headers likeAuthorization(the JWT token) and__tenantfor authentication and tenancy. - The Situation in MVC: Your MVC project is the server. Your Blazor Server components live and execute within the same server process. Making an HTTP call from the server back to itself (like a request to localhost) is an unnecessary network hop. This degrades performance, adds latency, and introduces a needless layer of complexity and a potential point of failure.
This approach is significantly faster, cleaner, and less error prone. The existing authentication and tenant context from the
HttpContextis automatically flowed to the Application Service, so you don't need to manage it manually.
A Full Blazor Experience with a
/BlazorAppRouteYes, this is absolutely possible and is an excellent approach, especially if you plan to migrate a significant portion of your application to Blazor. You can create a self contained "island" within your MVC project where Blazor controls its own routing and layout.
This often provides a cleaner migration path than embedding components one by one into various
.cshtmlviews.Create a 'Host' Controller and View in the MVC Project
This controller will catch all requests that start with
/BlazorAppand will serve a single view whose only purpose is to host the Blazor application.BlazorAppController.cs(Add this to your MVC project'sControllersfolder)using Microsoft.AspNetCore.Mvc; public class BlazorAppController : Controller { // This route catches /BlazorApp and any path underneath it // e.g., /BlazorApp/users, /BlazorApp/products/details/5 [Route("BlazorApp/{*pathInfo}")] public IActionResult Index() { return View(); } }Views/BlazorApp/Index.cshtml(Create this new view) This view will be very minimal. It will not use the standard MVC_Layout.cshtmland will only contain what's necessary to bootstrap Blazor.@{ // Disable the MVC layout, as Blazor will manage its own. Layout = null; } <!DOCTYPE html> <html> <head> <title>Blazor Application</title> <base href="/BlazorApp/" /> @* This is very important! It tells Blazor what the base path is. *@ <link href="/path/to/your/main/styles.css" rel="stylesheet" /> </head> <body> @* Render the root component of the Blazor application *@ <component type="typeof(YourNamespace.Shared.Components.App)" render-mode="ServerPrerendered" /> <script src="_framework/blazor.server.js"></script> </body> </html>Note: Replace
YourNamespace.Shared.Components.Appwith the actual namespace of yourApp.razorcomponent.
Create
App.razorandMainLayout.razorin Your Shared Library (RCL)App.razor(Add this to the root of your RCL project) This component contains the Blazor Router, which decides which page to display based on the incoming URL.<Router AppAssembly="@typeof(App).Assembly"> <Found Context="routeData"> <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> <FocusOnNavigate RouteData="@routeData" Selector="h1" /> </Found> <NotFound> <LayoutView Layout="@typeof(MainLayout)"> <p role="alert">Sorry, there's nothing at this address.</p> </LayoutView> </NotFound> </Router>MainLayout.razor(Add this to aSharedfolder or similar in your RCL) This is the master template for all pages within your Blazor "island." You can put common elements like a navigation menu, header, and footer here.@inherits LayoutComponentBase <div class="page"> <div class="sidebar"> @* You can add your Blazor-specific navigation menu (NavMenu) here *@ <NavMenu /> </div> <main> <div class="top-row px-4"> <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a> </div> <article class="content px-4"> @Body @* This is where the content of the current page will be rendered *@ </article> </main> </div>
Create Your Blazor Pages
Now you can create pages in your RCL using the
@pagedirective.- Example Page:
Pages/Dashboard.razor@page "/" @* This will be the default page for /BlazorApp/ *@ @page "/dashboard" @* This will be accessible at /BlazorApp/dashboard *@ <h3>Blazor Dashboard</h3> <p>Welcome to the Blazor side of the application!</p>
How It Works
- A user navigates to
https://yoursite.com/BlazorApp/dashboard. - The ASP.NET Core routing engine matches the
[Route("BlazorApp/{*pathInfo}")]attribute and invokes theBlazorAppController. - The controller returns the
Index.cshtmlview. - That view renders the
App.razorcomponent via the<component type="typeof(App)"...tag helper. - The
<Router>insideApp.razorinspects the rest of the URL path (/dashboard), finds the component with a matching@pagedirective (Dashboard.razor), and renders it inside theMainLayout.razorwhere@Bodyis located.
With this pattern, you cleanly separate all your Blazor logic from MVC and create a coherent, self contained part of your application.
Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image) - The Purpose of