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.
- Right-click on our project in the Solution Explorer (this will bring up the context menu).
- Select the ‘Add > Class…’ menu option.
- In the ‘Add New Item’ dialog, enter our new class name: ‘BinaryToDecimalViewModel.cs’.

- 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();
}
- We set the route to this page to be “/page-4”.
- We define a
vm
local variable (line 20) which holds an instance of theBinaryToDecimalViewModel
class (defined above). - 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 thevm
local variable followed by the property name. - Then, we one-way bind the
vm.Result
property to a label for display (line #15). - Finally, we one-way bind the
vm.ConvertToDecimal
method to the convert button’sonclick
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:

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.