Building a Software Survey using Blazor - Part 3 - Components
Tags: blazor, csharp
Published: 2020-09-29 07:15:48

I've decided to write a small survey site using Blazor.  Part of this is an excuse to learn Blazor.

As I learn with Blazor I will blog about it as a series of articles.

This series of articles is not intended to be a training course for Blazor - rather my thought process as I go through learning to use the product.

Earlier articles in this series:

* [Part 1 - State](https://red-folder.com/blog/building-a-software-survey-using-blazor-part-1-state)
* [Part 2 - Better State](https://red-folder.com/blog/building-a-software-survey-using-blazor-part-2-better-state)

---

Blazor is very much based on components.  This was something I was very pleased to see.

Having spent a lot of time with React, I've been quite a fan of the component structure.  The MVC structure enforced by ASP.Net, while familiar, has always seems a little clunky since working with React.

So it was definitely good to see that Blazor was taking a lot of its direction from Javascript frameworks like React & Vue.

We still have a little time to wait for CSS isolation by component - but that seem to be coming soon in [.Net 5](https://devblogs.microsoft.com/aspnet/asp-net-core-updates-in-net-5-preview-8/).  Something I'll take a look at again when released.

## The basics
Creating a component is very much a first class activity within Visual Studio - simply add a new Razor Component.

This creates our sample component ready to go.

### Test.razor
```
<h3>Test</h3>

@code {

}
```

And we can then pull that component into any other Razor component or page by adding `<Test />`

One thing to watch out for is that you components namespace will be based on the folder you create it in.  Just remember to include that namespace in the apps _Imports.razor file.

## Code
While the markdown is easy - it just goes into the razor file.  Where to put the code I suspect will produce debate in teams for years to come.

You basically have three choices:

* In the Test.razor file within the `@code { }` block
* In a Test.razor.cs file as a partial class
* In a TestBase.cs "base" class (extending ComponentBase) and then `@inherits TestBase` in the Test.razor

While I suspect that which version is used will be personal taste, I personally would advise picking one and trying to stick to it to avoid confusion.

Personally I favour using the `@code { }` block within the razor file.  It keeps the code & markup in one place and easy to see - similar to how I'd do it within React.

The `@code { }` block may get a bit unwieldy if you have a lot of code - but that maybe an indication that your trying to do too much in your component.

For me, the `@code { }` block should be fairly simple with any logic being injected in.

### Composition over inheritance
In early versions of the Software Survey I leaned heavily on the "base" class technique.  I used it to inhert functionality for the survey pages.

You can see this in [this commit version](https://github.com/Red-Folder/software-survey/tree/3cc49e13bd8f2d5f1811ab3b346f6b3142c1ce6c); that I have two base classes used by all of the pages:

* [SoftwareSurvey/Components/SurveyPageBase.cs](https://github.com/Red-Folder/software-survey/blob/3cc49e13bd8f2d5f1811ab3b346f6b3142c1ce6c/SoftwareSurvey/Components/SurveyPageBase.cs)
* [SoftwareSurvey/Components/SurveyFormBase.cs](https://github.com/Red-Folder/software-survey/blob/3cc49e13bd8f2d5f1811ab3b346f6b3142c1ce6c/SoftwareSurvey/Components/SurveyFormBase.cs)

These two bases classes provided a level of functionality for all the Survey pages - which technically worked, but definitely didn't "smell" correct.

So I refactored the functionality out of the base classes into components.  The components are then composed together - which has subsequently made the code considerably easier to understand.

If possible, always favour component composition over inheritance.

## ChildContent
Similar to React, Blazor supports children being passed into a component.

An example of where I've used this is in the `<EnsureBeenThroughStart />` component:

### EnsureBeenThroughStart.razor
```
@if (_valid)
{
    @ChildContent
}

@code {
    [Parameter]
    public RenderFragment ChildContent { get; set; }

    private bool _valid;

    ...
}
```

The component is used to ensure that the user has visited the start of the survey (if not it redirects to the start).  It should avoid respondents accidentally deep linking part way through the survey.

If valid, the component shows the `@ChildContent`.  That `@ChildContent` is automatically provided by Blazor as any thing defined between the `<EnsureBeenThroughStart> </EnsureBeenThroughStart>` tags.

As you can see below, I wrap the entire router within it.

### App.razor
```
...

<PreRenderLoadingMessage>
    <EnsureBeenThroughStart>
        <Router AppAssembly="@typeof(Program).Assembly">
            <Found Context="routeData">
                <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
            </Found>
            <NotFound>
                <LayoutView Layout="@typeof(MainLayout)">
                    <p>Sorry, there's nothing at this address.</p>
                    @{ Is404 = true; }
                </LayoutView>
            </NotFound>
        </Router>
     </EnsureBeenThroughStart>
</PreRenderLoadingMessage>

...
```

## More to learn
Components can seem a simple concept, but like many simple things, I think they will take experience to get the best from them.

I learnt that during the refactor away from the "base" classes.

I suspect overtime (and usage) patterns of usage will emerge - as they have in React.  I suspect that many ideas will cross-pollinate between Blazor and Javascript frameworks.

If you've not done so already, I'd recommend reading the [Microsoft Create and use ASP.NET Core Razor components page](https://docs.microsoft.com/en-us/aspnet/core/blazor/components/?view=aspnetcore-3.1)