How-To: Use Class File for Blazor Logic Code

As our logic continues to grow and our testing requirements increase, we will find that it is more efficient to separate our application logic from the rendering logic on pages. This split helps us separate these concerns and build cleaner pages. Also, having the logic within a separate C# class allows us to unit test that class directly without having to provide a UI context for it. We simply verify the methods process data and return values as expected, and don’t worry about how that data gets rendered on a page.

This separation starts us down the path of broader code separation design patterns, like Model-View-ViewModel (MVVM) and Model-View-Controller (MVC), but at a simpler level to begin with. I always try to separate my code and presentation even for simple projects, but many times don’t need a full MVVM framework unless the project grows much larger. But placing our logic in separate classes, even for simple pages, prepares our code to easily move down that path later.

First, we must have a Blazor project. Either open an existing Blazor project, or please follow the steps in the How-To: Create Blazor WASM Project article to create a new one. For this article, we called the project: Blazor.HowTo.

Then, we must work with a page. If we don’t already have a page, we can create one using the steps in the How-To: Create New Page in Blazor article. For this article, we named the page: ‘Page4.razor’.

Create the Code File

First, we will follow these steps to create a new C# file.

  1. Right-click on our project in the Solution Explorer (this will bring up the context menu).
  2. Select the ‘Add > Class…’ menu option.
  3. In the ‘Add New Item’ dialog, enter our new class name: ‘BinaryToDecimalViewModel.cs’.
Fig 1 – New Logic Class
  1. Press the ‘Add’ button to generate the new class file.

Then, in the BinaryToDecimalViewModel class, we will add the binding properties and logic that our page depends upon:

using System;

namespace Blazor.HowTo.ViewModels
{
    public class BinaryToDecimalViewModel
    {
        public string Binary { get; set; }

        public string Result { get; private set; }

        public void ConvertToDecimal()
        {
            try
            {
                Result = Convert.ToInt32(Binary, 2).ToString();
            }
            catch
            {
                Result = "Error: not a valid binary number.";
            }
        }
    }
}

We defined properties for the Binary and Result, which our page can bind and display. Then, we have the ConvertToDecimal method that can be used to bind to a component click event. This code is completely separate from our page, so we can easily test the logic by instantiating the class, setting the properties, and calling the ConvertToDecimal method. This is very convenient for creating fast, reliable unit tests.

If you read the How-To: Use Blazor Code-Behind File article, you will notice that this code is very similar to what we placed in the code-behind file. In that case the code was merged into the page code itself. In this case it remains in its own class.

Create the Page Markup

Now, let’s update the Page4.razor markup to the following:

@page "/page-4"

<h3>Binary-Decimal Converter [view-model]</h3>
<form class="form-row col-lg-4 col-md-12">
    <div class="form-group col-12">
        <label for="binary">Binary:</label>
        <input type="text" class="form-control" id="binary"
               placeholder="Enter binary number" @bind-value="@vm.Binary">
    </div>
    <div class="form-group col-12">
        <input id="convert-decimal" type="button"
               value="Convert to Decimal" @onclick=vm.ConvertToDecimal />
    </div>
    <div class="form-group col-12">
        <label>Decimal Result: @vm.Result</label>
    </div>
</form>

@code {
    BinaryToDecimalViewModel vm = new BinaryToDecimalViewModel();
}
  1. We set the route to this page to be “/page-4”.
  2. We define a vm local variable (line 20) which holds an instance of the BinaryToDecimalViewModel class (defined above).
  3. Then, we two-way bind the vm.Binary property to the input component (line #8). This is nearly identical to how we bound to local variables… it includes the vm local variable followed by the property name.
  4. Then, we one-way bind the vm.Result property to a label for display (line #15).
  5. Finally, we one-way bind the vm.ConvertToDecimal method to the convert button’s onclick event.

With these changes and binding to the logic class, we have reimplemented the full functionality of the binary-to-decimal converter. It’s great to see how creating this UI can be achieved in several different ways, so that we can use the right approach for our codebase.

Let’s run the application, navigate to page-4, and test out binding to our logic class:

Fig 2 – BinaryToDecimal Converter with Logic Class

In conclusion, separating our code and markup files allows us to build more flexible applications. And, having our logic in a separate class allows us easily test that code outside of the context of the user interface. We can easily connect that class as a member variable in our page markup file.

If you’re familiar with the Model-View-ViewModel (MVVM) design pattern, then this is the mechanism used to separate the view (page) code from the ViewModel (logic) code. In future articles, we will show a richer example of the MVVM pattern and how it can easily be achieved in Blazor.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s