This article is the first one in a series where I will cover how I currently plan to create a Blazor client side application to replace my production Silverlight application. The focus of this series is applying the Model-View-ViewModel pattern to client side Blazor.

In a previous article I discussed how I am working towards migrating my production Silverlight application to a new platform. My current hope is that I will be able to use Blazor as that platform. I talked about changing my application to use Web API REST calls instead of WCF services. If you do have any interest is using Web API with Silverlight you can read that article here:

I have uploaded the completed solution that will be created by following the steps in this article to GitHub. The code for this article can either be retrieved from the ArticleOne branch or from the V4.1 release. The repository is at:

My current application is a Silverlight MVVM application built using a View First implementation. Navigating to a page brings up the Silverlight XAML page and that page instantiates it’s own ViewModel which then instantiates a View. Blazor can do that quite easily as well and using the built in Dependency Injection it does it even more cleanly than my Silverlight application does. Implemented in Blazor the relationship will look like this:

MVVM Blazor

This article has been updated to work with Visual Studio 2019 Preview with .Net Core 3 preview 4 and the 4/18 release of client side Blazor. I am just focusing on an MVVM sample and not looking at anything else application related such as authentication or data access. I am going to work with the included sample template; if you already have everything installed on your system you can start a new Blazor (ASP.Net Core Hosted) application and follow these steps.

Project Structure

To start off and keep our project clean we are going to add new folders to the .Client project for Views, ViewModels and Models:

To make our Views look and work the same as the existing sample pages we will add the same _Imports.razor to our Views folder that is in the Pages folder. For this example we will recreate the FetchData page from the sample so add the three following files:

FetchDataView as a new Razor View in the Views folder

FetchDataViewModel as a new C# class in the ViewModels folder

FetchDataModel as a new C# class in the Models folder

Our solution now looks like this:

To be able to get to the new View when we start testing go into NavMenu.razor in the Shared folder and modify the div that contains the NavMenu. Simply copy the list item block and paste it as a fourth item then modify the href to “fetchdatamvvm” and the span text to “Fetch data MVVM”. The updated navmenu will look like the code below.

View and ViewModel

To start things off add the bare minimum to FetchDataView.razor.

@page "/fetchdatamvvm" <h1>Weather forecast</h1> <p>This component demonstrates fetching data from the server.</p>

At this point we can launch the app in debug and see that the View is accessible and returns the static HTML that we added:

Now that our View exists it needs a ViewModel to bind to. If we go back to the FetchData Page from the sample application we see that there is an array of WeatherForecast and there is an async method which populates that array. Go to FetchDataViewModel.cs and update it with this code:

We have made a private array with a public property in the class to hold and expose our WeatherForecast[]. We also added a Console.Writeline() to our constructor so that we can see in our browser debugging tools that our object is being instantiated. Unfortunately we can’t set breakpoints in Visual Studio on client side C# for Blazor at this point in time so this is one of the options we have available to us. We have also declared a public interface for our class. In the spirit of loose coupling and test-ability we will uses interfaces for all our references.

Now that we have a ViewModel we are going to make it available to our View. We will do this using the .Net Core built in dependency injection. Go to the Startup.cs in our client project and add this line of code to the ConfigureServices method (as well as the necessary using statement):

services.AddTransient<IFetchDataViewModel, FetchDataViewModel>();

This isn’t an article on Dependency Injection but this statement will provide any class that is requesting an IFetchDataViewModel with a new instance of FetchDataViewModel. The AddTransient method is why receive a new instance; there is also AddSingleton and AddScoped which we will not be using today.

Now that our ViewModel is ready for use we can update our View to use it. Go back to FetchDataView and add these two lines of code under the page directive:

@using BlazorMVVM.Client.ViewModels @inject IFetchDataViewModel fetchDataViewModel

And add this code below the static html:

@if (fetchDataViewModel.WeatherForecasts == null)

{

<p><em>Loading...</em></p>

}

else

{}

The @using statement is just like one from a C# class; it makes the namespace available to our View. The @inject statement tells our Dependency Injection container to give us a new instance of IFetchDataViewModel. Because of the statement we added in Startup.cs this will result in the ViewModel receiving a new instance of FetchDataViewModel. The View now looks like this:

Our View is now wired to our ViewModel. We can prove this by launching the application and opening the browser console and navigating to the view.

You can see that we receive the Loading text on the View because fetchDataViewModel.WeatherForecasts is null which met the criteria and the console output shows the statement we added to the debugger. Now that we have a working ViewModel and View we can implement and wire up our Model.

Adding the Model

For this article we’re going to build the model as a simple passthrough and not discuss storing data in the model and having the ViewModel transform it. We will actually do that in the next article. Go back to the FetchDataModel and put in the following code:

We have created one public method and exposed it in the IFetchDataModel interface. We have also declared a private variable to hold an HttpClient instance. Notice that there are no other references to HttpClient anywhere else in the code we have written. We are using contructor dependency injection (as opposed to the @inject statement we use in our View) to have the framework provide us with an HttpClient. This code provides us with an HttpClient that is already configured and ready to make calls back to the server and is the same client that was being used in the FetchData page from the default template. The `RetrieveForecastsAsync()` method just makes the GET request back to the server to fetch our WeatherForecast[].

Now that the model has the basic functionality that we require we can go to Startup.cs and add it to ConfigureServices with this line of code (along with the needed using statement):

services.AddTransient<IFetchDataModel, FetchDataModel>();

We can now update the FetchDataViewModel to instantiate the Model. The first thing we will do is update our constructor to get an instance of our Model from dependency injection. Add another private member to the ViewModel along with the needed using statement:

private IFetchDataModel _fetchDataModel;

Then update the ViewModel constructor to fill it with an implementation:

public FetchDataViewModel(IFetchDataModel fetchDataModel)

{

Console.WriteLine("FetchDataViewModel Constructor Executing");

_fetchDataModel = fetchDataModel;

}

Now that the Model is implemented and accessible we will add a method which asks the model for our WeatherForecast[]. Add the following method to the ViewModel:

public async Task RetrieveForecastsAsync()

{

_weatherForecasts = await _fetchDataModel.RetrieveForecastsAsync();

Console.WriteLine("FetchDataViewModel Forecasts Retrieved");

}

Also add this line to the interface to expose the new method:

Task RetrieveForecastsAsync();

The FetchDataViewModel now looks like this:

Now that our Model and ViewModel are wired together we are going to have the View ask the ViewModel for data. We are going to hook into the life-cycle of the Blazor view so for now I’m including this directly in the View. Another option which may be preferable once you need a lot of View specific code is to create a code behind class. To do this declare a C# class that inherits from `ComponentBase` and then have the view use `@inherits` to make that class become the code behind for the View. You can then override any of the life-cycle methods in that code behind. For now we are going to add this code to the bottom of FetchDataView:

@functions {

protected override async Task OnInitAsync()

{

await fetchDataViewModel.RetrieveForecastsAsync();

}

}

This is going to call the server to populate WeatherForecasts[] when the View is initialized. At this point we can launch the application again and we will see the loading message appear briefly and then disappear once the WeatherForecast[] has been received by the Model and passed to the ViewModel.

Bringing it all together

The final step is to update the View to match the original FetchData Page. Replace the empty else{} block in the View with the following code:

This is all the same code from the original Page except it now references the ViewModel instead of the Page local variables from a function block. If we now run the application and navigate to the FetchDataMVVM tab we will see our forecast:

This might feel like overkill in this small sample application but once an application grows larger and more complicated it becomes much easier to maintain. Having all of your ViewModels and Models as pure C# classes without concrete dependencies will also make it easier to perform unit testing or replace dependencies as you need. I will try to keep this up to date as new previews of Blazor are released.

The follow up to this article is now available building on the project built in this article: