Blazor Forms and Validation

This week I’m exploring the basics of using forms and validation in a server-side Blazor. This is an area that the Blazor team is still making a lot of changes too so don’t be surprised if some of the things in this post need to be tweaked. If you need help creating a Blazor application check out my ASP.NET Core Server-Side Blazor with Authentication post, which is the app I’m using to write this post.

Model

For this example, I’m going to be creating a form for editing a contact. Blazor will make use of data annotations and automatically make sure that the conditions are valid. The following is the class I’m using as my model with a few data annotations thrown in. Project structure-wise I added a Models directory and added my model class there.

public class Contact
{
    public int Id { get; set; }
    [Required]
    public string Name { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    [StringLength(5, 
                  MinimumLength = 5, 
                  ErrorMessage = "Postal Code must be 5 characters")]
    public string PostalCode { get; set; }
    public string Phone { get; set; }
    [Required]
    [EmailAddress]
    public string Email { get; set; }
}

As you can see in the class Name and Email are both required fields. Email is also required to be a valid email address. PostalCode isn’t required, but if entered must be 5 characters. If the Postal Code is entered but isn’t 5 characters then the specified error message will show in the UI.

Component

Next, I added a new ContactEdit component. For details on how to add a new component check out Razor Components in Blazor which will walk through adding a new component using Visual Studio. It will also show you have to add the component to an existing page.

The following is the full component. Most of the component is normal HTML form elements. After the code, I will point a few things out.

@using Models
@using System.Diagnostics

<h3>Contact Edit</h3>

<div class="row">
    <div class="col-md-4">
        <EditForm Model="@contact" OnValidSubmit="@ValidSubmit">
            <DataAnnotationsValidator />
            <ValidationSummary />

            <div class="form-group">
                <label for="name" class="control-label">Name: </label>
                <InputText id="name" @bind-value="contact.Name" class="form-control" />
                <ValidationMessage For="@(() => contact.Name)" />
            </div>
            <div class="form-group">
                <label for="address" class="control-label">Address: </label>
                <InputText id="address" @bind-value="contact.Address" class="form-control" />
                <ValidationMessage For="@(() => contact.Address)" />
            </div>
            <div class="form-group">
                <label for="city" class="control-label">City: </label>
                <InputText id="city" @bind-value="contact.City" class="form-control" />
                <ValidationMessage For="@(() => contact.City)" />
            </div>
            <div class="form-group">
                <label for="state" class="control-label">State: </label>
                <InputText id="state" @bind-value="contact.State" class="form-control" />
                <ValidationMessage For="@(() => contact.State)" />
            </div>
            <div class="form-group">
                <label for="postalCode" class="control-label">Postal Code: </label>
                <InputText id="postalCode" @bind-value="contact.PostalCode" class="form-control" />
                <ValidationMessage For="@(() => contact.PostalCode)" />
            </div>
            <div class="form-group">
                <label for="phone" class="control-label">Phone: </label>
                <InputText id="phone" @bind-value="contact.Phone" class="form-control" />
                <ValidationMessage For="@(() => contact.Phone)" />
            </div>
            <div class="form-group">
                <label for="email" class="control-label">Email: </label>
                <InputText id="email" @bind-value="contact.Email" class="form-control" />
                <ValidationMessage For="@(() => contact.Email)" />
            </div>
            <button type="submit">Submit</button>
        </EditForm>
    </div>
</div>

@code {
    private Contact contact = new Contact
    {
        Id = 1,
        Name = "Eric",
        Address = "578 Main St.",
        City = "Nashville",
        State = "TN",
        Phone = "615-555-5555",
        Email = "ericeric.com"
    };

    private void ValidSubmit()
    {
        Debug.WriteLine("ValidSubmit");
    }
}

The following is a subsection of the code from above that is different from standard HTML forms.

<EditForm Model="@contact" OnValidSubmit="@ValidSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />

    <div class="form-group">
        <label for="name" class="control-label">Name: </label>
        <InputText id="name" @bind-value="contact.Name" class="form-control" />
        <ValidationMessage For="@(() => contact.Name)" />
    </div>
    <button type="submit">Submit</button>
</EditForm>

The EditForm is a component that Microsoft created that will bind to your model and allow you to specify what function is going to be called on submit. In this example, we are using OnValidSubmit to call the ValidSubmit function only if the model validates. Make note of the usage of the DataAnnotationsValidator which is the component that enables validation based on the data annotations that we placed on our model class.

The other thing to note is the usage of the ValidationSummary component which shows a summary of all the validation issues on the model. This example is also using ValidationMessage to show errors in line with the associated fields. In a real application, I doubt both would be used, but I wanted to show how to use both.

Wrapping Up

Hopefully, this has been a helpful introduction to forms and validation in Blazor. I may end up doing a follow-up post on the other submission options.

Make sure and check out the official docs for more information.  Rémi Bourgarel also has a great post on the subject.

Blazor Component Attributes

This post is going to take a look at a couple of new ways, as of ASP.NET Core Preview 7, to make it easier to deal with components that have a lot of attributes. The example we are going to use is an input control as they provide a lot of built-in attributes.

Initial Component

The following is a basic component named InputComponent. It contains a single HTLM input element with properties for ID, Type, and Placeholder text.

<input id="@Id"
       type="@Type"
       placeholder="@Placeholder"/>

@code {
    [Parameter]
    private string Id {get; set;} = "DefaultId";

    [Parameter]
    private string Type {get; set;} = "text";

    [Parameter]
    private string Placeholder {get; set;} = string.Empty;
}

The following is an example usage of the above component to show an email input element.

<InputComponent Id="InputTest" Placeholder="Email Address" Type="email" />

Input Attributes Dictionary

The following code is the same component that has been converted pull attributes out of a dictionary.

<input @attributes="InputAttributes" />

@code {
    [Parameter(CaptureUnmatchedValues = true)]
    private Dictionary<string, object> InputAttributes { get; set; } =
        new Dictionary<string, object>() 
            {
               { "id", "DefaultId" },
               { "type", "text" },
               { "placeholder", "" }
            };
}

The results of both are the same but in this version, you don’t have to pre-define all of the attributes you might expect and it still allows you to provide defaults by prepopulating the dictionary with the default values you would like to use.

Without the [Parameter(CaptureUnmatchedValues = true)]  it seems like you still need parameters on your component to match the attribute values passed in so I’m not sure how useful using a dictionary is without capturing unmatch values other than keeping you from having to specify each value in the HTML element. I was hoping to not need the parameters defined and it captures based on the values in the dictionary.

Wrapping Up

This feature is a nice addition that can save you some keystrokes. Check out the official docs for the full details.

Event Handling in Blazor

This post is a continuation of my Blazor exploration and will be a quick post as the sample application created with Microsoft’s template already contains an example. If you want to see how the sample application is created check out my ASP.NET Core Server-Side Blazor with Authentication post, or check out all my Blazor related posts.

Events

It is hard to write an application without needing to handle user input in some manner. For this post, we are going to be using a button click as an example. We will also be using the counter component as the example which can be found in the Counter.razor file. The following is the code for the component.

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    int currentCount = 0;

    void IncrementCount()
    {
        currentCount++;
    }
}

In the above example the @onclick=”IncrementCount” is the bit we are interested in. Blazor uses @onEventName with the string that follows is the function in the @code section of the component that should handle the event.

In our sample, the on click event of the button calls the IncrementCount function which changes the currentCount variable which causes the component to update with the new count value.

Just to show that this works with more than just click if you change the button to include an event to mouse over you will see the counter increment when your mouse goes over the button or when the button is clicked.

<button class="btn btn-primary" @onmouseover="IncrementCount" @onclick="IncrementCount">Click me</button>

Wrapping Up

I’m slowing building up the basics of Blazor applications for myself. I hope these more bite-sized chunks of Blazor info are helpful for you all as well. Writing these posts are helping cement the concepts in my mind.

Razor Components in Blazor

Since the release candidate for .NET Core 3.0 is getting closer it seemed like a good time to take a closer look at Blazor, as you can tell from the string of Blazor posts lately. For this post, I’m taking my first look at Razor Components in a Blazor server-side application.

This post is working off the same sample project used in the following posts. The first one contains the creation of the project if you want to follow along.

ASP.NET Core Server-Side Blazor with Authentication
Blazor Authentication: Hide a Nav Menu Item

What are Razor Components?

To quote the docs:

A component is a self-contained chunk of user interface (UI), such as a page, dialog, or form. A component includes HTML markup and the processing logic required to inject data or respond to UI events. Components are flexible and lightweight. They can be nested, reused, and shared among projects.

Basically, Razor Components gives us a way to create smart reusable chunks of UI.

Create a new Razor Component

To start I created a new Components directory in my project. This isn’t required, but it was how one of the Blazor sample projects were set up. Caution, if you do follow this path make sure and add the new namespace to _Imports.razor or your components will fail to render. Please don’t ask how long it took for me to figure that out.

@using System.Net.Http
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Layouts
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.JSInterop
@using BlazorAuth
@using BlazorAuth.Shared
@using BlazorAuth.Components

Right-click on the directory you want to create the component in and select Add > New Item.

In the Add New Item dialog select Razor Component, give the component a name and click Add.

The resulting file will look like the following.

<h3>HelloWorld</h3>

@code {

}

For this component, I don’t have any code so I deleted that section and added space between Hello and World. To use this component you can add <HelloWorld /> to any of your existing components or pages. For example, in the sample application, I changed the Index.razor to include the new component.

@page "/"

Welcome to your new app.

<HelloWorld />

The above will render as the following.

A Component with a Parameter

The above is great, but we all know that a component that only contains static HTML isn’t going to be super useful without the ability to make parts of the component more dynamic. The following example is only one of the ways to get data into a component.

The following bit of code is a new component that has a private name property that is marked with the Parameter attribute. This property can then be used in the non-code section of the component in the standard Razor syntax way.

<h3>Hello @Name!</h3>

@code {
    [Parameter]
    private string Name {get; set;}
}

The following is the usage of the HelloName component back in the Index.razor and is passing in a name via the name parameter.

@page "/"

Welcome to your new app.

<HelloWorld />
<HelloName Name="Eric" />

And the resulting output when the application is run.

Wrapping Up

Components provide a great unit of reusability. I highly recommend you take some time to play around with them. Also, make sure and check out the Create and use ASP.NET Core Razor components doc from Microsoft as it covers the full range of options when developing components.

Blazor Authentication: Hide a Nav Menu Item

In last week’s post, Server-Side Blazor with Authentication, we covered creating a Server-Side Blazor application with Authentication and then used the attribute to not allow the user to view the Fetch data page if they weren’t logged in.

While the authorize attribute does keep the user from viewing the contents of the page it still allows the user access to the nav menu item for the page they aren’t authorized to access. This is going to be a quick post showing how the AuthorizedView component can be used to hide any content that a user should be logged in to see (or be in a specific role).

Hide a Nav Menu Item

In the Pages/Shared directory open the NavMenu.razor file which is the file where the nav menu is defined. The following code is the code that renders the Fetch data menu item which is the section we want to hide if the user isn’t logged in.

<li class="nav-item px-3">
    <NavLink class="nav-link" href="fetchdata">
        <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
    </NavLink>
</li>

To hide menu item we wrap the list item in the AuthorizeView component.

<AuthorizeView>
    <li class="nav-item px-3">
        <NavLink class="nav-link" href="fetchdata">
            <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
        </NavLink>
    </li>
</AuthorizeView>

Do note that you should still use the Authorize attribute on the page that should require authorization and not depend on the menu item being hidden keeping users from finding the page.

Wrapping Up

While the Authorize attribute is still very useful I’m sure that the AuthorizeView will be getting a lot of use in Blazor apps. AuthrozieView has the advantage of not being limited to page component.

Also, note that AuthorizeView also supports roles and policies. Make sure and check out the official AuthorizeView component docs for more details. If interested the code for the component is on GitHub.

ASP.NET Core Server-Side Blazor with Authentication

It has been close to a year since I did my first into post on Blazor, ASP.NET Core Basics: Blazor, and a lot has changed. The biggest thing is that it was announced that Server-Side Blazor is going to ship with .NET Core 3. This post is going to walk through creating a server-side Blazor application including authentication.

Sever-Side Blazor

What is server-side Blazor and how is it different from client-side Blazor? The quick answer is that client-side Blazor uses WebAssembly and Mono to run .NET code in the browser allowing for basically a SPA written in .NET. With Server-Side Blazor the app is executed on the server and update/processing are requested over a SignalR connection.

For a deeper dive into the differences check out the ASP.NET Core Blazor hosting models doc.

Pre-requisites

To start make sure to install at least preview 6 of .NET Core 3. Using a command prompt you can run the following command to see which versions of the .NET Core SDK are installed.

dotnet --list-sdks

The previews of .NET Core 3 can be downloaded from here. Also, make sure to use the latest preview of Visual Studio 2019.

Application Creation

I used the following command from the command prompt to create a new Blazor application using individual authentication.

dotnet new blazorserverside --auth Individual

Visual Studio also has the template available if you select the ASP.NET Core Web Application project type and about three screens in select the Blazor Server App option.

After the creation process is complete open the project in Visual Studio. At this point, if you run the application you will see the standard options to log in or register.

Requiring Auth for a Page

At this point, the application allows account creation and login, but all pages are available to all user, even if they aren’t logged in. There are multiple ways to deal with this. For this post, I’m going with the closest to what I am used to from MVC which is using an Authorize attribute. In the Pages directory open then FetchData.razor file and make the following changes to make the page require the user to be authorized. Note that this method should only be used on page components.

Before:

@page "/fetchdata"
@using BlazorAuth.Data
@inject WeatherForecastService ForecastService

After:

@page "/fetchdata"
@using BlazorAuth.Data
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]
@inject WeatherForecastService ForecastService

Now if you go to the Fetch data page without being logged in you will see a Not authorized message. This message can be customized using the AuthorizeView component. You can find more details in the docs.

Wrapping Up

It is neat seeing how far Blazor has come since I last played with it. The docs are great and the product has improved a ton. I may do a follow-up post to go more into how to use the AuthorizeView component.

Make sure to check out the official docs on Blazor authentication and authorization to get the full picture of the subject.

ASP.NET Core Basics: Blazor

Blazor is a single page application framework that uses .NET running in the browser through the magic of WebAssembly and Mono. Check out How Blazor runs .NET in the browser for more information. You can think of Blazor like you do Angular or React, but written in .NET.

Please make note that this project is still an unsupported experiment and shouldn’t be used for production applications. This is part of the reason I held off on trying it until now.

I will be adding the Blazor project to my ASP.NET Core Basics repo. The code before any changes can be found here.

Getting Started

For an experiment, Blazor already has some really good docs. A lot of this post is going to mirror the Get started with Blazor docs page, but I try and document as I go. First, make sure you have the latest version of .NET Core 2.1.x SDK installed.

If you are going to be using Visual Studio you will need at least version 15.7. In addition, you will need to install the Blazor Language Services extension. From within Visual Studio, this can be done from the Tools > Extension and Updates menu. Select Online and search for Blazor. It should come up with just one item and you can click Download to start the install process.

Project Creation

We are going to use the .NET CLI to install the Blazor templates and add the resulting project to the ASP.NET Core Basics solution. First, open a command prompt and use the following command to get the Blazor template installed.

dotnet new -i Microsoft.AspNetCore.Blazor.Templates

If you are using the sample code I am running the commands from a new Blazor directory in the existing src directory. Then run the following command to create the Blazor project.

dotnet new blazor

The next command will add the new project to the existing solution. The path to the solution file isn’t required if the command is being run from the same directory as the solution file, but in our case, we are running the commands two level down from where the solution file is located.

dotnet sln "../../ASP.NET Core Basics.sln" add Blazor.csproj

At this point, you can use the following command to run the application.

dotnet run

Adding the Contact List

As with the other post in the ASP.NET Basics category, we are going to add a contact list page that pulls a list of contacts from an API. For this example, the API is part of the Contacts project that already exists in the sample solution. All the changes in the section take place in the Blazor project we created above.

In the Pages directory add a ContactList.cshtml file with the following contents. A break down of some of the parts of this file will follow.

@page "/contacts"
@inject HttpClient Http

<h1>Contact List</h1>

@if (contacts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var contact in contacts)
            {
                <tr>
                    <td>@contact.Id</td>
                    <td>@contact.Name</td>
                </tr>
            }
        </tbody>
    </table>
}

@functions {
    Contact[] contacts;

    protected override async Task OnInitAsync()
    {
        contacts = await Http.GetJsonAsync<Contact[]>("http://localhost:13322/api/contactsApi/");
    }

    class Contact
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string PostalCode { get; set; }
        public string Phone { get; set; }
        public string Email { get; set; }
    }
}

This has a lot going on so we are going to start with the functions section which is essentially a way to block off code needed by the page. It can contain functions, classes, or whatever else C# construct the page may need. The following is just the functions section of the above page.

@functions {
    Contact[] contacts;

    protected override async Task OnInitAsync()
    {
        contacts = await Http.GetJsonAsync<Contact[]>("http://localhost:13322/api/contactsApi/");
    }

    class Contact
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string PostalCode { get; set; }
        public string Phone { get; set; }
        public string Email { get; set; }
    }
}

In our sample, we are using the functions to define a Contact class to hold the data we get back from the API call in the OnInitAsync function. The OnInitAsync function is one of the lifecycle functions provided by the Blazor components. We aren’t going to dive into components, I recommend you check out the component docs for more information.

The @page "/contacts" is defining the route that the page will be served for. Next, @inject HttpClient Http is showing how to use ASP.NET Core’s dependency injection to get an instance of an HttpClient.

The remaining bit of the file is normal Razor. Everything defined in the functions section is available for use in your layout. For example, we are using the list of contacts filled by the OnInitAsync to loop and create a table to display our contact list.

<h1>Contact List</h1>

@if (contacts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var contact in contacts)
            {
                <tr>
                    <td>@contact.Id</td>
                    <td>@contact.Name</td>
                </tr>
            }
        </tbody>
    </table>
}

Wrapping Up

Blazor is a very interesting concept. I hope it is able to make it through the experimental phase into a supported project. It seems like it would be a great option for .NET developers. It was a lot of fun to finally try out. Go give it a try and make sure and provide feedback to Microsoft so they can make an informed decision on how to proceed with the project.

The finished code can be found here.