DotNetT Light_870x220

In this article we'll look into when it's helpful to use a code-behind in your Blazor development, how we benefit and what to expect when re-factoring existing components.

When working with Blazor the default component architecture is to have all of the markup and logic mixed within a single file (.razor). When components are simple this approach works well, however as the complexity becomes greater managing the entirety of a component becomes difficult. Using a "code-behind" approach allows for markup and logic to be separated into their own files. In this article we'll investigate when it's helpful to use a code-behind, how we benefit and what to expect when re-factoring existing components.

Single File Approach

Let's begin with a quick review of the single file approach. We'll use Blazor's default template's FetchData component as an example which is shown in Figure 1. The FetchData component displays an HTML table of weather forecast data by looping over data provided by a service. The component uses directives, HTML/Razor, and a @code block; these are all typical items that make up a component.

 

The FetchData component with a single file approach.

Figure 1: The FetchData component with a single file approach.

The markup for the component is quite verbose. Weighing in at 30+ lines the markup itself extends the length of the file, causing us to scroll down to find the components logic represented by a @code block. In Figure 2 we can see there is nearly 40 lines of markup before we reach the component’s logic.

 

The markup section of the FetchData component spans 37 lines.

Figure 2: The markup section of the FetchData component spans 37 lines.

Keep in mind that this component is still actually quite simple. As the complexity becomes greater each section will grow. This means we will eventually have more directives, using statements, markup, and logic in our code block. While it may be convenient to have an all-inclusive file, it will eventually become tedious to maintain due to constant scrolling between markup and logic.

Let's re-factor the FetchData component by using a code-behind file see how it improves the overall developer experience.

Code-Behind Approach

Code-behind is a common term for the technique of using a separate code file to that represents all the logic for a corresponding page, view, or component. Creating a code-behind in Blazor requires a few steps, but thankfully it's supported by the framework, so setup is quite simple. To complete our code-behind we'll need to create a class and then link the code-behind to our markup. Once we have the structure in place, we can move over our existing logic.

Creating and Linking a Code-Behind

First, we'll need a class file that will represent our code-behind. This is a standard .NET partial class; however, naming is very important. When we create our code-behind file we need to consider both the file name and class name as they can greatly affect our developer experience.

Let's start with the file name. When we add the file name, we should follow a common convention of [componentName].razor.cs. The .razor.cs extension is understood by Visual Studio and will be properly nested within the file explorer window as seen in Figure 3. Since the component already occupies a class name, we'll need to declare the new class as a partial class using the partial keyword.

public partial class FetchData { }

Visual Studio nests files with the same name and suffix with the .razor.cs pattern.

Figure 3: Visual Studio nests files with the same name and suffix with the .razor.cs pattern.

We can now migrate all the code from the @code block to our code-behind, and a few directives as well.

Migrating @code to Code-Behind

Most of the logic from our @code block can be copied directly as-is to the code-behind without change, however there are some small updates that will need to be made.

As we move code to our code-behind, additional using statements may be required if the code-behind doesn’t automatically pick up a namespace. This is where standard tooling comes in handy with ctrl+. making short work of any missing namespaces. Simply highlight any item with a red underscore and press the ctrl+. key combination, if it’s a missing namespace, then accept the fix and the change will be applied.

// added by [ctrl] + [.]
using BlazorBookExamples.WeatherComponent.Data;
using Microsoft.AspNetCore.Components;

With all the code migrated, we still need to tackle one final step, dependency injection (DI).

Dependency Injection in Blazor Code-Behind

Dependency Injection in Razor markup is handled by the @inject directive. While the directive is available in code-behind classes, it is written much differently and at first glance may not be obvious. To use dependency injection in a code-behind file we'll use the [Inject] attribute and apply it to a property of the type we would like to inject, ex: [Inject] MyType MyProp { get; set; }.

[Inject]
WeatherForecastService ForecastService { get; set; }

With the [Inject] attribute added the component can now resolve the service and we no longer need the directive in the Razor markup. We can proceed with cleaning up our markup by removing the @inject and @using directives as well as the @code block.

Code-Behind Final Thoughts

When we started the component's directives, markup and logic were all contained in a single file. While a single file approach provides benefits in its simplicity, and is great for small components, it simply doesn't scale well. Once our component requires complex markup or logic it's easy to get lost in the large file and/or confused by two different ways of expressing code. In addition, we lose access to some of Visual Studio's most valuable productivity tooling.

The process of converting an existing component to use a code-behind is quite easy. A few code changes are required with regards to using statements and dependency injection. For the most part Visual Studio even guides us through making the proper corrections to achieve a successful compilation.

A side-by-side view of the FetchData component, markup on the left and logic on the right.

Figure 4: A side-by-side view of the FetchData component, markup on the left and logic on the right.

When the transition is complete, we benefit from clearly defined roles for markup and logic with a lot less scrolling. If we need to see the component in its entirety, we can now snap the two windows side-by-side and focus on the task at hand as shown in Figure 4.

New to Blazor?

If you're new to Blazor and want to start learning quickly, see the free Blazor Quick Start video series. In this instructional video series we learn about ASP.NET Core Blazor. Learn the basics of working with Blazor concepts like: components, events, data binding, and more. The course is guided by me, Ed Charbeneau, an industry pro and five-time Microsoft MVP and author of the Free Blazor E-book.


Ed Charbeneau is a Developer Advocate for Telerik
About the Author

Ed Charbeneau

Ed Charbeneau is a web enthusiast, speaker, writer, design admirer, and Developer Advocate for Telerik. He has designed and developed web based applications for business, manufacturing, systems integration as well as customer facing websites. Ed enjoys geeking out to cool new tech, brainstorming about future technology, and admiring great design. Ed's latest projects can be found on GitHub.

Related Posts

Comments

Comments are disabled in preview mode.