Learn ASP.NET Core 3.0 : MVC, Razor Pages, Web API, Entity Framework Core, and Blazor.
Microsoft's official documentation can be found here. Looking for professional online training courses? Next weekend batches are starting in November 2019. More details here.

Build your first Blazor server-side application

If you are tracking the progress of ASP.NET Core 3, you are probably aware that Blazor is getting a lot of attention and feature improvements. If you haven't developed Blazor applications yet it's worthwhile to take a quick look at the overall development process. To that end this article discusses a simple database update page build using server-side Blazor.

Blazor is a framework for building web applications that use C# for user interface development. That means instead of using JavaScript you use C# for dealing with HTML elements and other markup. Of course, you can also interact with JavaScript code whenever necessary. Blazor comes with two hosting models - client-side and server-side. The client-side hosting model uses WebAssembly whereas server-side hosting model uses a SignalR connection for UI updates.

Now that you have some idea about what Blazor is, let's go straight to code level details and develop a simple data entry form as shown below:

 

As you can see, the page displays a list of CustomerIDs from Customers table of Northwind database. Selecting a CustomerID and clicking on the Show Data button displays CompanyName, ContactName, and Country values of that customer. You can modify these values and click on Update button to save the changes back to the database.

Begin by creating a new Blazor server-side application in Visual Studio.

Once the project gets created. Add NuGet package for Entity Framework Core - Microsoft.EntityFrameworkCore.SqlServer.

Then add two classes that represent DbContext and Customer entity. These classes are added to the Data folder and are shown below:

public class Customer
{
    [Key]
    [Required]
    [StringLength(5, MinimumLength = 5)]
    public string CustomerID { get; set; }

    [Required]
    [StringLength(30)]
    public string CompanyName { get; set; }

    [Required]
    [StringLength(30)]
    public string ContactName { get; set; }

    [Required]
    [StringLength(15)]
    public string Country { get; set; }

}
public class AppDbContext:DbContext
{

    public AppDbContext(
DbContextOptions<AppDbContext> options) : 
base(options)
    {

    }
    public DbSet<Customer> Customers { get; set; }
}

These classes are quite straightforward. Notice that the Customer class uses data annotations for the sake of model validation.

To perform database operations you need one more class - CustomerManager. This class is shown below:

public class CustomerManager
{
    private AppDbContext db;

    public CustomerManager(AppDbContext db)
    {
        this.db = db;
    }

    public List<Customer> SelectAll()
    {
        return db.Customers.ToList();
    }

    public Customer SelectByID(string id)
    {
        return db.Customers.Find(id);
    }

    public string Update(Customer obj)
    {
        db.Update(obj);
        db.SaveChanges();
        return "Success!";
    }
}

The CustomerManager class contains three methods - SelectAll(), SelectByID(), and Update(). These methods perform the respective operations. Once developed the AppDbContext and CustomerManager need to be registered with the DI container. This is done in the ConfigureServices() of the Startup class.

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddDbContext<AppDbContext>(options => 
options.UseSqlServer("data source=.;
initial catalog=Northwind;integrated security=true;"));

    services.AddScoped<CustomerManager>();
}

You register AppDbContext with the DI container using AddDbContext() method whereas CustomerManager is registered using AddScoped() method.

Next, add a new Razor Component named Customers.razor to the Pages folder.

Open Customers.razor file and following code at the top:

@page "/customers"
@using BlazorDemo.Data
@inject BlazorDemo.Data.CustomerManager customerManager

The @page directive controls the route at which this component can be accessed. In this case the component is accessible at this URL : http://localhost:1234/customers. The @using directives uses Data namespace so that model classes can be referenced in the code. Notice the @inject directive that injects an instance of CustomerManager into the component (you registered it in ConfigureServices()).

Now, add the following code to the @code block.

@code {
    Customer cust = new Customer();
    List<Customer> customers = null;
    string Message { get; set; }
}

As you might have guessed the @code block is used to write C# code (members, properties, methods) that interacts with the user interface. Here, the code declares a member of type Customer. This member is used during data binding with the form (discussed shortly). The List<Customer> stores a list of customers returned from SelectAll() method and is also used to fill the dropdown list. The Message property is used to notify user of the result of database update operation.

As soon as the component is initialized you need to call the SelectAll() method so that the CustomerID dropdown list can be populated. To do this, you write OnInit() method in @code block as shown below:

protected override void OnInit()
{
    customers = customerManager.SelectAll();
}

You are basically overriding OnInit() method of ComponentBase class (Blazor components inherit from ComponentBase class). Inside, you call SelectAll() method and store the return value into customers member.

If you observe the user interface shown at the beginning of this article, you will find that there are two buttons - Show Data and Update. You need click event handlers for these buttons.

void OnShowData()
{
    cust = customerManager.SelectByID(cust.CustomerID);
}

void OnUpdate()
{
    Message = customerManager.Update(cust);
}

You will be binding cust member with the data entry form. The data binding features of Blazor allow you to do one-way and two-way data binding. When you select a CustomerID the CustomerID property of cust member is automatically changed to reflect the selection. So, when you pass cust.CustomerID in the SelectByID() call you are passing the selected value. The returned Customer object's values are reflected in the other textboxes. The  OnUpdate() event handler simply calls the Update() method of CustomerManager to save the changes to the database.

Below the @code block write the following Blazor markup.

<h2>Customer Manager</h2>

<EditForm Model="cust">
    <DataAnnotationsValidator>
    </DataAnnotationsValidator>

    <table border="0" cellpadding="20">
        <tr>
            <td>Customer ID :</td>
            <td>
                <InputSelect id="customerid" 
@bind-Value="@cust.CustomerID">
                    @if (customers != null)
                    {
                        foreach (var c in customers)
                        {
                            <option value="@c.CustomerID">
@c.CustomerID</option>
                        }
                    }
                </InputSelect>
                <button type="button" 
@onclick="@OnShowData">Show Data</button>
            </td>
        </tr>
        <tr>
            <td>Company Name :</td>
            <td>
                <InputText id="companyname" 
@bind-Value="@cust.CompanyName" />
                <ValidationMessage 
For="@(() => cust.CompanyName)" />
            </td>
        </tr>
        <tr>
            <td>Contact Name :</td>
            <td>
                <InputText id="contactname" 
@bind-Value="@cust.CompanyName" />
                <ValidationMessage 
For="@(() => cust.ContactName)" />
            </td>
        </tr>
        <tr>
            <td>Country :</td>
            <td>
                <InputText id="country" 
@bind-Value="@cust.Country" />
                <ValidationMessage 
For="@(() => cust.Country)" />
            </td>
        </tr>
        <tr>
            <td colspan="2">
                <button type="button" 
@onclick="@OnUpdate">Update</button>
            </td>
        </tr>
    </table>
    <ValidationSummary></ValidationSummary>
</EditForm>
<h5>@Message</h5>

The above markup shows several Blazor features including data binding, components, data annotations and validations.

The <EditForm> component is used to render a data entry <form>. The Model property sets the model for the form to an object (Customer object in this case). The <DataAnnotationsValidator> component enables form validations based on data annotation attributes such as [Required] and [StringLength].

The CustomerID dropdown list is rendered using an <InputSelect> component (same as <select> HTML element). To bind the dropdown list with model's property @bind-Value attribute performs two-way data binding (from cust to dropdown and from dropdown to cust). To populate all the CustomerIDs into the dropdown list C# foreach loop is used. The onclick event handler of Show Data button is wired to OnShowData() method written in the @code block.

To display CompanyName, ContactName, and Country <InputText> component is used. This component renders HTML <input> element. Two-way data binding is done as before. To display field level validation errors <ValidationMessage> component is used. The onclick  event of Update button is handled by OnUpdate() method. At the bottom, there is <ValidationSummary> component that displays a collective list of error messages.

Finally, the Message property is displayed so that use known the outcome of update operation.

Compile the project and run the application by pressing F5. Once the browser window loads the application, go to the address bar and change the URL to http://localhost:1234/customers. You should now see the UI of the Customers component. Check whether data can be updated or not. 

That's it for now! Keep coding!!


Bipin Joshi is an independent software consultant, trainer, author, yoga mentor, and meditation teacher. He has been programming, meditating, and teaching for 24+ years. He conducts instructor-led online training courses in ASP.NET family of technologies for individuals and small groups. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced the Yoga way of life he also teaches Ajapa Yoga to interested individuals. To know more about him click here.

Get article updates : Facebook  Twitter  LinkedIn

Posted On : 15 July 2019


Tags : ASP.NET ASP.NET Core Data Access C# Visual Studio


Subscribe to our newsletter

Get monthly email updates about new articles, tutorials, code samples, and how-tos getting added to our knowledge base.

  

Receive Weekly Updates