Blazor WASM could've been easily preferred over Blazor Server-Side without its downsides development-wise. Currently, Blazor WASM doesn't support a full-featured debugging experience and has a very slow startup. This slows down development much more than with Blazor Server-Side. Though I honestly personally think that the debugging experience slows down the development much more than the slow startup.
NOTE: I included the "proposed" word in there because I'm not sure about the downsides that this solution can cause, so feel free to comment on my answer below.
The solution is to simply create an additional Blazor Server-Side project then reference the Blazor WASM project to the Blazor Server-Side project. Afterwards, add some tweaks to the Startup
and the _Host.cshtml
of the Blazor Server-Side to properly use the Blazor WASM razor files and the wwwroot files. See my proposed answer below for a step-by-step explanation for this solution.
In simpler terms, this solution just adds and configures the Blazor Server-Side project without making any changes and any significant code duplication to the Blazor WASM project.
The Blazor Server hosting model offers several benefits: Download size is significantly smaller than a Blazor WebAssembly app, and the app loads much faster. The app takes full advantage of server capabilities, including the use of .NET Core APIs.
Blazor WebAssembly (WASM) apps run client-side in the browser on a WebAssembly-based . NET runtime. The Blazor app, its dependencies, and the . NET runtime are downloaded to the browser.
NOTE: In this example, I'm using Visual Studio 2019 16.7.2 and the version of the templates are currently at 3.1.8
Create a Blazor WASM project. Either the ASP.NET Core Hosted or the Standalone option will work fine but they will have different configurations later that will be discussed. The rest of the options won't have any effect. In this example, I'll go with the ASP.NET Core Hosted to explain later about having API Controllers. Also create the Blazor Server-Side project afterwards.
As of this moment, your project structure should be similar to the first screenshot below.
Delete the highlighted items in the Blazor Server-Side project shown in the second screenshot below.
Reference the Blazor WASM project to the Blazor Server-Side project.
BlazorWasm.Client
& BlazorWasm.Server
project.Go to the Startup
class of the Blazor Server-Side project. In the ConfigureServices()
, remove the WeatherForecastService
together with the BlazorServer.Data
namespace then add a service for the HttpClient
to be used by the razor files from the Blazor WASM project.
services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(sp.GetRequiredService<NavigationManager>().BaseUri) });
NOTE In production, I don't suggest creating an instance of the
HttpClient
. Use theIHttpClientFactory
instead. Visit this article Use IHttpClientFactory to implement resilient HTTP requests.
For ASP.NET Core WASM Projects
In the Configure()
, map the controllers' endpoints. This will use the controllers in the X.Server
/BlazorWasm.Server
project.
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
...
});
Go to the _Host.cshtml
in the /Pages folder of the Blazor Server-Side project. Change the reference of the css/site.css
to css/app.css
since the filenames for the main css file for the Blazor WASM project are different.
<link href="css/site.css" rel="stylesheet" /> <!-- Previous -->
<link href="css/app.css" rel="stylesheet" /> <!-- New -->
Lastly, change the App
in the type
attribute of the component
tag and refer to the App
razor class file in the Blazor WASM project. In this example, the App
class is found in the BlazorWasm.Client
project:
<component type="typeof(App)" render-mode="ServerPrerendered" /> <!-- Previous -->
<component type="typeof(BlazorWasm.Client.App)" render-mode="ServerPrerendered" /> <!-- New -->
That's it! When you run the Blazor Server-Side project, it should load without the "Loading ..." text.
launchSettings.json
& appsettings.json
.Startup
for the Blazor Server-Side, you can just create extension methods in the Blazor WASM project(s) and use them in the Blazor Server-Side project.NOTE: I honestly think this is ideally(?) only for debugging during development since the WASM razor files won't fully utilize the capability of a true Blazor Server-Side because it would still use HTTP Requests.
Hoping for feedbacks down below! :DD
I would suggest an alternate way. There are other drawbacks to referring to WASM project from a server project, but personally I think it is an architecturally inelegant solution.
There are some critical areas where Blazor Server and WASM differ :
Therefore, for most applications (and definitely the ones that require database access) you will not be able to share 100% codebase between WASM and Server-side.
Here is what you should do instead:
For the points mentioned above, (auth, but mostly db access), create a data access service dependency (say IDataAccessLayer). One implementation will access the database directly (to be used in server side) The other implementation will access the database through an HttpClient (to be used in blazor WASM).
Now, put your entire app in an RCL. Call it "BlazorAppRCL". This RCL obviously does not have Startup.cs and Program.cs
Create a project for server and client specific db access implementation
Now, you have the following set of projects:
For Server Side: BlazorServer (has only settings + Program.cs + Startup.cs). It refers to the RCL + Server specific implementation of IDataAccessLayer
For hosted WASM: BlazorWebAPI : For database access, it has API to access database BlazorClientDAL : WASM specific implementation of IDataAccessLayer BlazorWASM : Blazor WASM project All three refer to your BlazorAppRCL.
The crux is to use DI/ inversion of control pattern to address the divergence between WASM and Server. This way, you can have a both instances WASM and Server instances with minimal code divergence. Note that the WASM WebAPI can simply use the server side blazor's implementation od IDataAccessLayer as it is. So beyond API related overhead, additional coding is not necessary.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With