Introduction
Blazor is a new framework built by Microsoft for creating interactive client-side web UI with .NET codebase. We can write both client-side and server-side code in C#.NET itself. I have already written an article about Blazor on C# Corner. Please refer to below article for more basics about Blazor framework.
We will create a simple Employee app using Blazor. In this app, we can add, edit, read and delete employee information. We will use entity framework core 3.0 to store and retrieve data into SQL database.
Create Blazor app in Visual Studio 2019
Visual Studio latest version is shipped with .NET Core 3.0 SDK. We can choose Blazor template and create a new Blazor project.
We are going to use entity framework core and data migration commands to create SQL database and table. We must install “Microsoft.EntityFrameworkCore.SqlServer” and “Microsoft.EntityFrameworkCore.Tools” libraries to perform these actions.
Currently, Blazor don’t support Json methods like “GetJsonAsync”, “PostJsonAsync” and “PutJsonAsync” in HttpClient class. We will create a custom HttpClient class to add these methods. Hence, we must install “Newtonsoft.Json” library also to the project.
We can create an Employee class and SqlDbContext classes.
Employee.cs
- namespace BlazorEmployeeEFCore.Data
- {
- public class Employee
- {
- public string Id { get; set; }
- public string Name { get; set; }
- public string Department { get; set; }
- public string Designation { get; set; }
- public string Company { get; set; }
- }
- }
SqlDbContext.cs
- using Microsoft.EntityFrameworkCore;
-
- namespace BlazorEmployeeEFCore.Data
- {
- public class SqlDbContext : DbContext
- {
- public SqlDbContext(DbContextOptions<SqlDbContext> options)
- : base(options)
- {
- }
- public DbSet<Employee> Employees { get; set; }
- }
- }
SqlDbContext class inherits DbContext class and contains an Employee property to perform all SQL related operations.
We can add SQL connection string in the appsettings.json file.
We must register the SqlDbContext class in the startup class as well.
I have enabled the detailed error option also for Blazor application. So that, we can see the detailed error messages in the developer console, if any occurs.
Create SQL database and table using DB migration
We are ready for creating SQL database and table using DB migration with code first approach. We have already added “Microsoft.EntityFrameworkCore.Tools” library for this purpose.
Open “Package Manager Console” from Tools menu and use below command to create migration script.
add-migration Initial
This command will create a new migration script class file under a new “Migrations” folder.
We can use below command to execute the migration script class.
update-database
We have used the default local SQL server available with Visual Studio. If you check with SQL server object explorer, you can see a new database and a table created in local server after DB migration.
We can create an Employees controller for Web API service. We will consume the web methods from this controller in our Blazor components for CRUD operations later.
EmployeesController.cs
- using Microsoft.AspNetCore.Mvc;
- using Microsoft.EntityFrameworkCore;
- using System;
- using System.Collections.Generic;
- using System.Threading.Tasks;
-
- namespace BlazorEmployeeEFCore.Data
- {
- [Route("api/[controller]")]
- [ApiController]
- public class EmployeesController : ControllerBase
- {
- private readonly SqlDbContext _dbContext;
-
- public EmployeesController(SqlDbContext dbContext)
- {
- _dbContext = dbContext;
- }
-
- [HttpGet]
- [Route("Get")]
- public async Task<List<Employee>> Get()
- {
- return await _dbContext.Employees.ToListAsync();
- }
-
- [HttpPost]
- [Route("Create")]
- public async Task<bool> Create([FromBody]Employee employee)
- {
- if (ModelState.IsValid)
- {
- employee.Id = Guid.NewGuid().ToString();
- _dbContext.Add(employee);
- try
- {
- await _dbContext.SaveChangesAsync();
- return true;
- }
- catch (DbUpdateException)
- {
- return false;
- }
- }
- else
- {
- return false;
- }
- }
-
- [HttpGet]
- [Route("Details/{id}")]
- public async Task<Employee> Details(string id)
- {
- return await _dbContext.Employees.FindAsync(id);
- }
-
- [HttpPut]
- [Route("Edit/{id}")]
- public async Task<bool> Edit(string id, [FromBody]Employee employee)
- {
- if (id != employee.Id)
- {
- return false;
- }
-
- _dbContext.Entry(employee).State = EntityState.Modified;
- await _dbContext.SaveChangesAsync();
- return true;
- }
-
- [HttpDelete]
- [Route("Delete/{id}")]
- public async Task<bool> DeleteConfirmed(string id)
- {
- var employee = await _dbContext.Employees.FindAsync(id);
- if (employee == null)
- {
- return false;
- }
-
- _dbContext.Employees.Remove(employee);
- await _dbContext.SaveChangesAsync();
- return true;
- }
- }
- }
We have added all the logic for CRUD actions inside the controller. All the methods are self-explanatory.
You must add “MapControllers” end point in “Configure” method inside the Startup class to get service calls from Web API controller.
As I mentioned earlier, currently HttpClient class doesn’t contain “GetJsonAsync”, “PostJsonAsync”, and “PutJsonAsyc” methods. I have already raised an
issue in Microsoft GitHub account for adding these methods. Please support, if you can.
We can create a custom HttpClient class to add these missing methods to handle json data.
CustomHttpClient.cs
- using Newtonsoft.Json;
- using System.Net.Http;
- using System.Text;
- using System.Threading.Tasks;
-
- namespace BlazorEmployeeEFCore.Data
- {
- public class CustomHttpClient : HttpClient
- {
- public async Task<T> GetJsonAsync<T>(string requestUri)
- {
- HttpClient httpClient = new HttpClient();
- var httpContent = await httpClient.GetAsync(requestUri);
- string jsonContent = httpContent.Content.ReadAsStringAsync().Result;
- T obj = JsonConvert.DeserializeObject<T>(jsonContent);
- httpContent.Dispose();
- httpClient.Dispose();
- return obj;
- }
- public async Task<HttpResponseMessage> PostJsonAsync<T>(string requestUri, T content)
- {
- HttpClient httpClient = new HttpClient();
- string myContent = JsonConvert.SerializeObject(content);
- StringContent stringContent = new StringContent(myContent, Encoding.UTF8, "application/json");
- var response = await httpClient.PostAsync(requestUri, stringContent);
- httpClient.Dispose();
- return response;
- }
- public async Task<HttpResponseMessage> PutJsonAsync<T>(string requestUri, T content)
- {
- HttpClient httpClient = new HttpClient();
- string myContent = JsonConvert.SerializeObject(content);
- StringContent stringContent = new StringContent(myContent, Encoding.UTF8, "application/json");
- var response = await httpClient.PutAsync(requestUri, stringContent);
- httpClient.Dispose();
- return response;
- }
- }
- }
In GetJsonAsync method, we have fetched the data from Web API service and converted string data to object. We can pass object type as a generic parameter. In our case, Employee is the object type.
In PostJsonAsync and PutJsonAsync methods, we have serialized the object type data to string content and call PostAsync and PutAsync methods respectively. These methods already available in HttpClient class.
We must pass the base URL endpoint from each Blazor component to call the Web API methods. We can store the application base URL inside the appsettings.js file and create a service to get these values from appsettings file. We can inject this service from each Blazor components.
AppSettingsService.cs
- using Microsoft.Extensions.Configuration;
-
- namespace BlazorEmployeeEFCore.Data
- {
- public class AppSettingsService
- {
- private readonly IConfiguration _config;
- public AppSettingsService(IConfiguration config)
- {
- _config = config;
- }
- public string GetBaseUrl()
- {
- return _config.GetValue<string>("MySettings:BaseUrl");
- }
- }
- }
We can store the base URL in the appsettings configuration file.
For my application, port number is 5000. In your case, it may be different. Please give the correct port number in appsettings.
We must register CustomHttpClient and AppSettingsService in the Startup class to inject from Blazor components.
We can click the Employee data menu link to navigate the employee list page.
We have already added a simple spinner in this component. We can click “Create New Employee” link to create a new employee record.
We can perform the other CRUD operations like edit and delete as well in this application.
I have noticed one interesting thing that, even though we have called various Web API methods, these were not triggered in network tab of developer console.
We can see only one “negotiate” action in entire web requests. This will improve the performance of entire application.
Conclusion
In this post, we have seen how to create a single page application with Blazor and entity framework core 3.0. We have created the database and table using database migration with code first approach. We have also created four Blazor components to perform all CRUD actions. We can see more awesome features of Blazor framework in upcoming articles. Please share your valuable feedbacks.