Introduction
In this article, we will learn what Blazor is and how we can set up Blazor by making a basic CRUD Application with Entity Framework Core Code first approach in .Net 5 (the latest version).
Prerequisites
- Install the latest .NET 5.0 SDK from here.
- Install the latest version of Visual Studio 2019 from here.
What we are going to cover in this?
- What is Blazor and why it is exciting for C# Developers?
- Difference between Blazor Server - Blazor Web Assembly
- Setup the CRUD App using Blazor
- Run and Test
Download Source Code - Git Hub.
What is Blazor and why is it exciting for C# Developers?
Blazor is a .NET web system that runs in the program. Think Angular or React however controlled by C# and Razor. Designers make Blazor applications utilizing a combination of C#, Razor, and HTML. These applications execute .NET congregations utilizing the Mono .NET runtime carried out through WebAssembly. Blazor utilizes the most recent web guidelines and requires no extra modules or additional items to run, this is not another Silverlight.
Blazor Server App
In the worker side facilitating model (Blazor Server-Side), Blazor is executed on the worker from inside an ASP.NET Core application. UI refreshes, occasion dealing with, and JavaScript brings are taken care of over a SignalR association.
Blazor also supports features of the SPA(Single Page Application) framework such as,
- Routing
- Layouts
- Forms and validation
- JavaScript interop
- Build on save during development
- Server-side rendering
- Dependency Injection
Blazor Web Assembly
In the customer-side model (Blazor WebAssembly), the Blazor application, its conditions, and the .NET runtime are downloaded to the program, and the application is executed straightforwardly on the program UI string. All UI updates and occasions taking care of occur inside a similar cycle.
Setup
Create a Blazor Server App.
Add the project name for your Application
Make sure you have .Net 5.0 installed in your machine and then it will automatically be added in the dropdown select target framework as .Net 5.0
A basic scaffolded template will generate here is the project structure
Create an class in the Data folder to act as table in database to store all our CRUD Operations.
Employee.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace BlazorCRUD.Data
{
public class Employee
{
[Key]
public int Id { get; set; }
public string EmployeName { get; set; }
public string Gender { get; set; }
public string City { get; set; }
public string Designation { get; set; }
}
}
Create a dbcontext file to setup the configuration with Database.
AppDbContext.cs
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BlazorCRUD.Data
{
public class AppDBContext : DbContext
{
public AppDBContext(DbContextOptions<AppDBContext> options) : base(options)
{
}
public DbSet<Employee> Employees { get; set; }
}
}
Create an employee service with all the business logic inside this service.
Setup a connection string in appsettings.json file.
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"myconn": "server= Your Server name; database=BlazorCRUD;Trusted_Connection=True;"
}
}
EmployeeService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
namespace BlazorCRUD.Data
{
public class EmployeeService
{
#region Property
private readonly AppDBContext _appDBContext;
#endregion
#region Constructor
public EmployeeService(AppDBContext appDBContext)
{
_appDBContext = appDBContext;
}
#endregion
#region Get List of Employees
public async Task<List<Employee>> GetAllEmployeesAsync()
{
return await _appDBContext.Employees.ToListAsync();
}
#endregion
#region Insert Employee
public async Task<bool> InsertEmployeeAsync(Employee employee)
{
await _appDBContext.Employees.AddAsync(employee);
await _appDBContext.SaveChangesAsync();
return true;
}
#endregion
#region Get Employee by Id
public async Task<Employee> GetEmployeeAsync(int Id)
{
Employee employee = await _appDBContext.Employees.FirstOrDefaultAsync(c => c.Id.Equals(Id));
return employee;
}
#endregion
#region Update Employee
public async Task<bool> UpdateEmployeeAsync(Employee employee)
{
_appDBContext.Employees.Update(employee);
await _appDBContext.SaveChangesAsync();
return true;
}
#endregion
#region DeleteEmployee
public async Task<bool> DeleteEmployeeAsync(Employee employee)
{
_appDBContext.Remove(employee);
await _appDBContext.SaveChangesAsync();
return true;
}
#endregion
}
}
Configure the connection setup and inject the EmployeeService in Configure Services method in startup.cs file.
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<WeatherForecastService>();
services.AddScoped<EmployeeService>();
#region Connection String
services.AddDbContext<AppDBContext>(item => item.UseSqlServer(Configuration.GetConnectionString("myconn")));
#endregion
}
Create the table by using these commands in Package Console Manager
Commands
- Add-Migration 'Your Migration Name'
- Update-Databse
Now the actual binding of Data will see once we create the Razor pages inside the Pages folder lets create pages and for each form. Will create the Employee Form where it will have the datatable to show all the Saved information in it.
To create a Razor component Right Click on pages -> Click on Add -> Click on Razor Component then create a page with the Employee.Razor .
Employees.Razor
@page "/Employees"
@using BlazorCRUD.Data
@inject EmployeeService employeeService
<NavLink class="nav-link" href="AddEmployee">
<span class="oi oi-plus" aria-hidden="true">Add New</span>
</NavLink>
<h1>Employee Info</h1>
@if (EmpObj is null)
{
<p><em>Loading... !</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Emp Id</th>
<th>Employee Name</th>
<th>Gender</th>
<th>Designation</th>
<th>City</th>
<th>Action</th>
</tr>
</thead>
<tbody>
@foreach(var emp in EmpObj)
{
<tr>
<td>@emp.Id</td>
<td>@emp.EmployeName</td>
<td>@emp.Gender</td>
<td>@emp.Designation</td>
<td>@emp.City</td>
<td>
<a class="nav-link" href="EditEmployee/@emp.Id">
<span class="oi oi-pencil" aria-hidden="true">Edit</span>
</a>
<a class="nav-link" href="Delete/@emp.Id">
<span class="oi oi-trash" aria-hidden="true">Delete</span>
</a>
</td>
</tr>
}
</tbody>
</table>
}
@code {
List<Employee> EmpObj;
protected override async Task OnInitializedAsync()
{
EmpObj = await Task.Run(() => employeeService.GetAllEmployeesAsync());
}
}
@page - the actual navigation page name
@inject - Injection of Service layer here to have interaction with Business logic
@code - Where we call the service method to bind all the values inside the Razor component.
AddEmployee.cs
Injected the NavigateManager to navigate from one page to another with the page names.
@page "/AddEmployee"
@using BlazorCRUD.Data
@inject EmployeeService employeeService
@inject NavigationManager NavigationManager
<h2>Add Employee</h2>
<hr />
<form>
<div class="row">
<div class="col-md-8">
<div class="form-group">
<label for="Name" class="control-label">Name</label>
<input form="Name" class="form-control" @bind="@obj.EmployeName" />
</div>
<div class="form-group">
<label for="Gender" class="control-label"></label>
<select @bind="@obj.Gender" class="form-control">
<option value="">-Select Gender</option>
<option value="Male">Male</option>
<option value="Female">Female</option>
</select>
</div>
<div class="form-group">
<label for="Designation" class="control-label">Designation</label>
<input form="Designation" class="form-control" @bind="@obj.Designation" />
</div>
<div class="form-group">
<label for="City" class="control-label">City</label>
<input form="City" class="form-control" @bind="@obj.City" />
</div>
</div>
</div>
<div class="row">
<div class="col-md-4">
<div class="form-group">
<input type="button" class="btn btn-primary" @onclick="@CreateEmployee" value="Save"/>
<input type="button" class="btn btn-primary" @onclick="@Cancel" value="Cancel"/>
</div>
</div>
</div>
</form>
@code {
Employee obj = new Employee();
protected async void CreateEmployee()
{
await employeeService.InsertEmployeeAsync(obj);
NavigationManager.NavigateTo("Employees");
}
void Cancel()
{
NavigationManager.NavigateTo("Employees");
}
}
EditEmployee.razor
@page "/EditEmployee/{Id}"
@using BlazorCRUD.Data
@inject EmployeeService employeeService
@inject NavigationManager NavigationManager
<h2>Edit Employee</h2>
<hr />
<form>
<div class="row">
<div class="col-md-8">
<div class="form-group">
<input form="Name" class="form-control" @bind="@obj.Id" />
</div>
<div class="form-group">
<label for="Name" class="control-label">Name</label>
<input form="Name" class="form-control" @bind="@obj.EmployeName" />
</div>
<div class="form-group">
<label for="Gender" class="control-label"></label>
<select @bind="@obj.Gender" class="form-control">
<option value="">-Select Gender</option>
<option value="Male">Male</option>
<option value="Female">Female</option>
</select>
</div>
<div class="form-group">
<label for="Designation" class="control-label">Designation</label>
<input form="Designation" class="form-control" @bind="@obj.Designation" />
</div>
<div class="form-group">
<label for="City" class="control-label">City</label>
<input form="City" class="form-control" @bind="@obj.City" />
</div>
</div>
</div>
<div class="row">
<div class="col-md-4">
<div class="form-group">
<input type="button" class="btn btn-primary" @onclick="@UpdateEmployee" value="Update" />
<input type="button" class="btn btn-primary" @onclick="@Cancel" value="Cancel" />
</div>
</div>
</div>
</form>
@code {
[Parameter]
public string Id { get; set; }
Employee obj = new Employee();
protected override async Task OnInitializedAsync()
{
obj = await Task.Run(() => employeeService.GetEmployeeAsync(Convert.ToInt32(Id)));
}
protected async void UpdateEmployee()
{
await employeeService.UpdateEmployeeAsync(obj);
NavigationManager.NavigateTo("Employees");
}
void Cancel()
{
NavigationManager.NavigateTo("Employees");
}
}
Actually we used to pass the the Id for Edit employee to fetch the details from the database and to store in edit employee form.
Delete.Razor
@page "/Delete/{Id}"
@using BlazorCRUD.Data
@inject EmployeeService employeeService
@inject NavigationManager NavigationManager
<h2>Delete Employee</h2>
<hr />
<h3>Are you sure want to delete this?</h3>
<form>
<div class="row">
<div class=" col-md-8">
<div class="form-group">
<label>Employee Id:</label>
<label>@obj.Id</label>
</div>
<div class="form-group">
<label>Employee Name:</label>
<label>@obj.EmployeName</label>
</div>
<div class="form-group">
<label>Desigation:</label>
<label>@obj.Designation</label>
</div>
<div class="form-group">
<label>Gender:</label>
<label>@obj.Gender</label>
</div>
<div class="form-group">
<label>City:</label>
<label>@obj.City</label>
</div>
</div>
</div>
<div class="row">
<div class="col-md-4">
<div class="form-group">
<input type="button" class="btn btn-danger" @onclick="@DeleteEmployee" value="Delete" />
<input type="button" class="btn btn-primary" @onclick="@Cancel" value="Cancel" />
</div>
</div>
</div>
</form>
@code {
[Parameter]
public string Id { get; set; }
Employee obj = new Employee();
protected override async Task OnInitializedAsync()
{
obj = await Task.Run(() => employeeService.GetEmployeeAsync(Convert.ToInt32(Id)));
}
protected async void DeleteEmployee()
{
await employeeService.DeleteEmployeeAsync(obj);
NavigationManager.NavigateTo("Employees");
}
void Cancel()
{
NavigationManager.NavigateTo("Employees");
}
}
Run and test the applicaton
Click on employee tab you will see all the existing details in the grid
Add the employee details and save in Database.
Edit the employee details
Update the details
Delete operation
Here is a clear picture of the Crud Application in Blazor and I hope this article helps you... !!!
Keep learning .... !!!!!