Create A Blazor App With Google ☁️Cloud SQL Using MySQL Engine

We will see how to create a Google Cloud SQL instance using the MySQL engine and will create a single page application in Blazor.

Introduction

Cloud SQL is a fully managed database service that makes it simple to line up, maintain, manage, and administer your relational PostgreSQL and MySQL databases within the cloud. Cloud SQL offers high performance, scalability, and convenience. Hosted on Google Cloud platform, Cloud SQL provides a data infrastructure for applications running at any place.

We will see all the steps to create a Google Cloud SQL instance. We will create a project in the Google Cloud console and then, we will create a MySQL instance and will connect this instance from MySQL Workbench 8.0 Community Edition. We will create a database and table. Later, we will connect this table and database from our Blazor application.
 

About Blazor Framework

Blazor is a .NET web framework from Microsoft using C#/Razor and HTML that runs in the browser with Web Assembly. Blazor provides all the benefits of a client-side web UI framework using .NET on the client and optionally, on the server.

I have already written many articles on Blazor on C# Corner. If you are new to it, please refer to the below articles to get started with Blazor.

Create Google Cloud SQL instance with MySQL engine

You must create a Google Cloud account before starting it. Currently, Google provides a one-year free membership with $300 credits.

Log into Google Cloud console with your Google credentials.

Please select a project if you have any. Otherwise, you can click the “New Project” button to create a new project.

Create a Blazor App with Google Cloud SQL using MySQL Engine
 
Choose a unique name for your project and click the “Create” button to start project creation.
 
Create a Blazor App with Google Cloud SQL using MySQL Engine 
 
Your project will be ready in a few minutes. You can choose the project and it will list the project details on the dashboard.
 
Create a Blazor App with Google Cloud SQL using MySQL Engine 
 
We can create the Cloud SQL instance now. Please choose the SQL tab from the left side menu.
 
Create a Blazor App with Google Cloud SQL using MySQL Engine 
 
Click the “Create Instance” button to proceed.
 
Create a Blazor App with Google Cloud SQL using MySQL Engine 
 
Currently, Google Cloud SQL supports MySQL and PostgreSQL engines. Here, we have selected the MySQL engine.
 
Create a Blazor App with Google Cloud SQL using MySQL Engine 
 
We can give a valid instance name and give a password to the “root” user. Please note this is a default user. We can later change the password if needed. We can also create multiple users on a later stage. Here, I have chosen “asia-south1” region. You can choose your convenient region.
 
Create a Blazor App with Google Cloud SQL using MySQL Engine 
 
It will take some time to create the instance. Before connecting this instance with MySQL workbench, you must add your local IP address to the Cloud SQL authorized networks. You can open the "Connections" tab to add your local IP address.
 
Create a Blazor App with Google Cloud SQL using MySQL Engine 
Add your local IP address and "Save".
 
Create a Blazor App with Google Cloud SQL using MySQL Engine 
Now, we can connect the instance from MySQL client. Here, we are using MySQL Workbench 8.0 Community Edition. It is a very good and free SQL Editor. We can give the instance details and test the connection.
 
Create a Blazor App with Google Cloud SQL using MySQL Engine 
 
Our connection is successful now.
 
Create a Blazor App with Google Cloud SQL using MySQL Engine 
 
Open the SQL editor and create a database and table in the Cloud SQL instance.
 
Create a Blazor App with Google Cloud SQL using MySQL Engine 
  1. CREATE DATABASE sarathcloudsql;        
  2. USE sarathcloudsql;        
  3. DROP TABLE IF EXISTS Book;      
  4. CREATE TABLE Book     
  5. (Id VARCHAR(50) PRIMARY KEY,      
  6. Name VARCHAR(50),      
  7. ISBN VARCHAR(50),      
  8. Author VARCHAR(50),      
  9. Price DECIMAL(18,8));    

Create a Blazor project in Visual Studio 2017

In this article, we will create a Book Data Entry single page application. I am using free Visual Studio 2017 Community edition to create the Blazor application.

Choose .NET Core -> ASP.NET Core Web Application template. Currently, there are three types of Blazor templates available. We choose Blazor (ASP.NET Core hosted) template.
 
Create a Blazor App with Google Cloud SQL using MySQL Engine 
 
Our solution will be ready in a few minutes. Please note that there are three projects created in the solution - “Client”, “Server” and “Shared”.
 
Create a Blazor App with Google Cloud SQL using MySQL Engine 

By default, Blazor created some files in these three projects. We can remove all the unwanted files like “Counter.cshtml”, “FetchData.cshtml”, “SurveyPrompt.cshtml” from the Client project and “SampleDataController.cs” file from Server project and delete “WeatherForecast.cs” file from the Shared project too.

Now, let us create a Models folder in “Shared” project and create “Book” class inside this.

Book.cs
  1. namespace BlazorCloudSQL.Shared.Models  
  2. {  
  3.     public class Book  
  4.     {  
  5.         public string Id  
  6.         {  
  7.             get;  
  8.             set;  
  9.         }  
  10.         public string Name  
  11.         {  
  12.             get;  
  13.             set;  
  14.         }  
  15.         public string ISBN  
  16.         {  
  17.             get;  
  18.             set;  
  19.         }  
  20.         public string Author  
  21.         {  
  22.             get;  
  23.             set;  
  24.         }  
  25.         public decimal Price  
  26.         {  
  27.             get;  
  28.             set;  
  29.         }  
  30.     }  
  31. }  

Install “MySql.Data” NuGet Package in the “Server” project. This package is developed by Oracle Corporation.

Create a Blazor App with Google Cloud SQL using MySQL Engine 
 
Create a “DataAccess” folder in the “Server” project and create CloudSQLContext class inside the DataAccess folder. Add all the CRUD operation logic inside this class. We will call the methods in this class from our Controller class later.
 
CloudSQLContext.cs
  1. using BlazorCloudSQL.Shared.Models;  
  2. using MySql.Data.MySqlClient;  
  3. using System;  
  4. using System.Collections.Generic;  
  5. using System.Data;  
  6. using System.Threading.Tasks;  
  7.   
  8. namespace BlazorCloudSQL.Server.DataAccess  
  9. {  
  10.     public class CloudSQLContext  
  11.     {  
  12.         public string ConnectionString { getset; }  
  13.   
  14.         public CloudSQLContext(string connectionString)  
  15.         {  
  16.             ConnectionString = connectionString;  
  17.         }  
  18.   
  19.         private MySqlConnection GetConnection()  
  20.         {  
  21.             return new MySqlConnection(ConnectionString);  
  22.         }  
  23.   
  24.         public async Task<List<Book>> GetAllAsync()  
  25.         {  
  26.             List<Book> list = new List<Book>();  
  27.   
  28.             using (MySqlConnection conn = GetConnection())  
  29.             {  
  30.                 conn.Open();  
  31.                 var commandText = @"SELECT Id,Name,ISBN,Author,Price FROM Book;";  
  32.                 MySqlCommand cmd = new MySqlCommand(commandText, conn);  
  33.   
  34.                 using (var reader = cmd.ExecuteReader())  
  35.                 {  
  36.                     while (await reader.ReadAsync())  
  37.                     {  
  38.                         list.Add(new Book()  
  39.                         {  
  40.                             Id = await reader.GetFieldValueAsync<string>(0),  
  41.                             Name = await reader.GetFieldValueAsync<string>(1),  
  42.                             ISBN = await reader.GetFieldValueAsync<string>(2),  
  43.                             Author = await reader.GetFieldValueAsync<string>(3),  
  44.                             Price = await reader.GetFieldValueAsync<decimal>(4),  
  45.                         });  
  46.                     }  
  47.                 }  
  48.   
  49.             }  
  50.             return list;  
  51.         }  
  52.   
  53.         public async Task InsertAsync(Book book)  
  54.         {  
  55.             book.Id = Guid.NewGuid().ToString();  
  56.   
  57.             using (MySqlConnection conn = GetConnection())  
  58.             {  
  59.                 conn.Open();  
  60.                 var commandText = @"INSERT INTO Book (Id,Name,ISBN,Author,Price) VALUES (@Id, @Name, @ISBN, @Author, @Price);";  
  61.   
  62.                 MySqlCommand cmd = new MySqlCommand(commandText, conn);  
  63.   
  64.                 cmd.Parameters.Add(new MySqlParameter  
  65.                 {  
  66.                     ParameterName = "@Id",  
  67.                     DbType = DbType.String,  
  68.                     Value = book.Id,  
  69.                 });  
  70.   
  71.                 cmd.Parameters.Add(new MySqlParameter  
  72.                 {  
  73.                     ParameterName = "@Name",  
  74.                     DbType = DbType.String,  
  75.                     Value = book.Name,  
  76.                 });  
  77.   
  78.                 cmd.Parameters.Add(new MySqlParameter  
  79.                 {  
  80.                     ParameterName = "@ISBN",  
  81.                     DbType = DbType.String,  
  82.                     Value = book.ISBN,  
  83.                 });  
  84.   
  85.                 cmd.Parameters.Add(new MySqlParameter  
  86.                 {  
  87.                     ParameterName = "@Author",  
  88.                     DbType = DbType.String,  
  89.                     Value = book.Author,  
  90.                 });  
  91.   
  92.                 cmd.Parameters.Add(new MySqlParameter  
  93.                 {  
  94.                     ParameterName = "@Price",  
  95.                     DbType = DbType.Decimal,  
  96.                     Value = book.Price,  
  97.                 });  
  98.   
  99.                 await cmd.ExecuteNonQueryAsync();  
  100.   
  101.             }  
  102.         }  
  103.   
  104.         public async Task UpdateAsync(Book book)  
  105.         {  
  106.             using (MySqlConnection conn = GetConnection())  
  107.             {  
  108.                 conn.Open();  
  109.                 var commandText = @"UPDATE Book SET Name=@Name, ISBN=@ISBN, Author=@Author, Price=@Price  Where Id=@Id;";  
  110.   
  111.                 MySqlCommand cmd = new MySqlCommand(commandText, conn);  
  112.   
  113.                 cmd.Parameters.Add(new MySqlParameter  
  114.                 {  
  115.                     ParameterName = "@Id",  
  116.                     DbType = DbType.String,  
  117.                     Value = book.Id,  
  118.                 });  
  119.   
  120.                 cmd.Parameters.Add(new MySqlParameter  
  121.                 {  
  122.                     ParameterName = "@Name",  
  123.                     DbType = DbType.String,  
  124.                     Value = book.Name,  
  125.                 });  
  126.   
  127.                 cmd.Parameters.Add(new MySqlParameter  
  128.                 {  
  129.                     ParameterName = "@ISBN",  
  130.                     DbType = DbType.String,  
  131.                     Value = book.ISBN,  
  132.                 });  
  133.   
  134.                 cmd.Parameters.Add(new MySqlParameter  
  135.                 {  
  136.                     ParameterName = "@Author",  
  137.                     DbType = DbType.String,  
  138.                     Value = book.Author,  
  139.                 });  
  140.   
  141.                 cmd.Parameters.Add(new MySqlParameter  
  142.                 {  
  143.                     ParameterName = "@Price",  
  144.                     DbType = DbType.Decimal,  
  145.                     Value = book.Price,  
  146.                 });  
  147.   
  148.                 await cmd.ExecuteNonQueryAsync();  
  149.             }  
  150.   
  151.         }  
  152.   
  153.         public async Task DeleteAsync(string id)  
  154.         {  
  155.             using (MySqlConnection conn = GetConnection())  
  156.             {  
  157.                 conn.Open();  
  158.                 var commandText = @"DELETE FROM Book Where Id=@Id;";  
  159.   
  160.                 MySqlCommand cmd = new MySqlCommand(commandText, conn);  
  161.   
  162.                 cmd.Parameters.Add(new MySqlParameter  
  163.                 {  
  164.                     ParameterName = "@Id",  
  165.                     DbType = DbType.String,  
  166.                     Value = id,  
  167.                 });  
  168.   
  169.                 await cmd.ExecuteNonQueryAsync();  
  170.             }  
  171.   
  172.         }  
  173.   
  174.         public async Task<Book> FindOneAsync(string id)  
  175.         {  
  176.             using (MySqlConnection conn = GetConnection())  
  177.             {  
  178.                 conn.Open();  
  179.                 var commandText = @"SELECT Name,ISBN,Author,Price FROM Book Where Id=@Id;";  
  180.                 MySqlCommand cmd = new MySqlCommand(commandText, conn);  
  181.                 cmd.Parameters.Add(new MySqlParameter  
  182.                 {  
  183.                     ParameterName = "@Id",  
  184.                     DbType = DbType.String,  
  185.                     Value = id,  
  186.                 });  
  187.   
  188.                 using (var reader = cmd.ExecuteReader())  
  189.                 {  
  190.                     if (await reader.ReadAsync())  
  191.                     {  
  192.                         return new Book()  
  193.                         {  
  194.                             Id = id,  
  195.                             Name = await reader.GetFieldValueAsync<string>(0),  
  196.                             ISBN = await reader.GetFieldValueAsync<string>(1),  
  197.                             Author = await reader.GetFieldValueAsync<string>(2),  
  198.                             Price = await reader.GetFieldValueAsync<decimal>(3),  
  199.                         };  
  200.                     }  
  201.                     else  
  202.                     {  
  203.                         return null;  
  204.                     }  
  205.   
  206.                 }  
  207.             }  
  208.         }  
  209.     }  
  210. }  

We have created each method for CRUD actions inside this class. Please note we are using “MySqlConnection” class from “MySql.Data” library to connect MySQL database.

Now, let us inject the CloudSQLContextservice in the Startup class.
 
Startup.cs
  1. using BlazorCloudSQL.Server.DataAccess;  
  2. using Microsoft.AspNetCore.Blazor.Server;  
  3. using Microsoft.AspNetCore.Builder;  
  4. using Microsoft.AspNetCore.Hosting;  
  5. using Microsoft.AspNetCore.ResponseCompression;  
  6. using Microsoft.Extensions.DependencyInjection;  
  7. using System.Linq;  
  8. using System.Net.Mime;  
  9.   
  10. namespace BlazorCloudSQL.Server  
  11. {  
  12.     public class Startup  
  13.     {  
  14.         public void ConfigureServices(IServiceCollection services)  
  15.         {  
  16.             services.AddMvc();  
  17.   
  18.             services.AddResponseCompression(options =>  
  19.             {  
  20.                 options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[]  
  21.                 {  
  22.                     MediaTypeNames.Application.Octet,  
  23.                     WasmMediaTypeNames.Application.Wasm,  
  24.                 });  
  25.             });  
  26.             var connStr = "Server=<Your Server IP>; Port=3306; Database=sarathcloudsql; Uid=root; Pwd=<Your Password>; SslMode=Preferred;";  
  27.             services.Add(new ServiceDescriptor(typeof(CloudSQLContext), new CloudSQLContext(connStr)));  
  28.         }  
  29.   
  30.         public void Configure(IApplicationBuilder app, IHostingEnvironment env)  
  31.         {  
  32.             app.UseResponseCompression();  
  33.   
  34.             if (env.IsDevelopment())  
  35.             {  
  36.                 app.UseDeveloperExceptionPage();  
  37.             }  
  38.   
  39.             app.UseMvc(routes =>  
  40.             {  
  41.                 routes.MapRoute(name: "default", template: "{controller}/{action}/{id?}");  
  42.             });  
  43.   
  44.             app.UseBlazor<Client.Program>();  
  45.         }  
  46.     }  
  47. }  

For simplicity, I have hard-corded the MySQL connection details inside Startup class. You can even keep these connection details in a separate configuration file if needed.

We can create Books Controller now. Please add the below code to this Controller class.

BooksController.cs
  1. using BlazorCloudSQL.Server.DataAccess;  
  2. using BlazorCloudSQL.Shared.Models;  
  3. using Microsoft.AspNetCore.Mvc;  
  4. using System.Collections.Generic;  
  5. using System.Threading.Tasks;  
  6.   
  7. namespace BlazorCloudSQL.Server.Controllers  
  8. {  
  9.     [Route("api/[controller]")]  
  10.     public class BooksController : Controller  
  11.     {  
  12.         [HttpGet]  
  13.         public async Task<IEnumerable<Book>> GetAsync()  
  14.         {  
  15.             CloudSQLContext context = HttpContext.RequestServices.GetService(typeof(CloudSQLContext)) as CloudSQLContext;  
  16.             return await context.GetAllAsync();  
  17.         }  
  18.   
  19.         [HttpGet("{id}")]  
  20.         public async Task<Book> Get(string id)  
  21.         {  
  22.             CloudSQLContext context = HttpContext.RequestServices.GetService(typeof(CloudSQLContext)) as CloudSQLContext;  
  23.             return await context.FindOneAsync(id);  
  24.         }  
  25.   
  26.         [HttpPost]  
  27.         public async Task Post([FromBody] Book book)  
  28.         {  
  29.             if (ModelState.IsValid)  
  30.             {  
  31.                 CloudSQLContext context = HttpContext.RequestServices.GetService(typeof(CloudSQLContext)) as CloudSQLContext;  
  32.                 await context.InsertAsync(book);  
  33.             }  
  34.         }  
  35.   
  36.         [HttpPut]  
  37.         public async Task Put([FromBody] Book book)  
  38.         {  
  39.             if (ModelState.IsValid)  
  40.             {  
  41.                 CloudSQLContext context = HttpContext.RequestServices.GetService(typeof(CloudSQLContext)) as CloudSQLContext;  
  42.                 await context.UpdateAsync(book);  
  43.             }  
  44.         }  
  45.   
  46.         [HttpDelete("{id}")]  
  47.         public async Task Delete(string id)  
  48.         {  
  49.             CloudSQLContext context = HttpContext.RequestServices.GetService(typeof(CloudSQLContext)) as CloudSQLContext;  
  50.             await context.DeleteAsync(id);  
  51.         }  
  52.     }  
  53. }  

We have added all the CRUD operations in this Controller. We will call methods from CloudSQLContext class here.

Go to the “Client” project and modify “NavMenu.cshtml” Razor View inside the “Shared” folder.

NavMenu.cshtml
  1. <div class="top-row pl-4 navbar navbar-dark">  
  2.     <a class="navbar-brand" href="">Blazor Cloud SQL App</a>  
  3.     <button class="navbar-toggler" onclick=@ToggleNavMenu>  
  4.         <span class="navbar-toggler-icon"></span>  
  5.     </button>  
  6. </div>  
  7.   
  8. <div class=@(collapseNavMenu ? "collapse" : null) onclick=@ToggleNavMenu>  
  9.     <ul class="nav flex-column">  
  10.         <li class="nav-item px-3">  
  11.             <NavLink class="nav-link" href="" Match=NavLinkMatch.All>  
  12.                 <span class="oi oi-home" aria-hidden="true"></span> Home  
  13.             </NavLink>  
  14.         </li>  
  15.         <li class="nav-item px-3">  
  16.             <NavLink class="nav-link" href="/listbooks">  
  17.                 <span class="oi oi-plus" aria-hidden="true"></span> Book Details  
  18.             </NavLink>  
  19.         </li>  
  20.     </ul>  
  21. </div>  
  22.   
  23. @functions {  
  24. bool collapseNavMenu = true;  
  25.   
  26. void ToggleNavMenu()  
  27. {  
  28.     collapseNavMenu = !collapseNavMenu;  
  29. }  
  30. }  

We can create a new Razor View inside “Pages” folder for listing all the book details. Add the below code to the Razor View.

ListBooks.cshtml
  1. @using BlazorCloudSQL.Shared.Models  
  2.   
  3. @page "/listbooks"  
  4. @inject HttpClient Http  
  5.   
  6. <h4>Book Details</h4>  
  7. <p>  
  8.     <a href="/addbook">Create New Book</a>  
  9. </p>  
  10. @if (books == null)  
  11. {  
  12.     <p><em>Loading...</em></p>  
  13. }  
  14. else  
  15. {  
  16.     <table class='table'>  
  17.         <thead>  
  18.             <tr>  
  19.                 <th>Name</th>  
  20.                 <th>ISBN</th>  
  21.                 <th>Author</th>  
  22.                 <th>Price</th>  
  23.             </tr>  
  24.         </thead>  
  25.         <tbody>  
  26.             @foreach (var book in books)  
  27.             {  
  28.                 <tr>  
  29.                     <td>@book.Name</td>  
  30.                     <td>@book.ISBN</td>  
  31.                     <td>@book.Author</td>  
  32.                     <td>@book.Price</td>  
  33.                     <td>  
  34.                         <a href='/editbook/@book.Id'>Edit</a>  
  35.                         <a href='/deletebook/@book.Id'>Delete</a>  
  36.                     </td>  
  37.                 </tr>  
  38.             }  
  39.         </tbody>  
  40.     </table>  
  41. }  
  42. @functions {  
  43. Book[] books;  
  44.   
  45. protected override async Task OnInitAsync()  
  46. {  
  47.     books = await Http.GetJsonAsync<Book[]>("/api/books");  
  48. }  
  49. }      

Let's add three more Razor View files and add the below codes.

AddBook.cshtml
  1. @using BlazorCloudSQL.Shared.Models  
  2.   
  3. @page "/addbook"  
  4. @inject HttpClient Http  
  5. @inject Microsoft.AspNetCore.Blazor.Services.IUriHelper UriHelper  
  6.   
  7. <h4>Create Book</h4>  
  8. <hr />  
  9. <form>  
  10.     <div class="row">  
  11.         <div class="col-md-8">  
  12.             <div class="form-group">  
  13.                 <label for="Name" class="control-label">Name</label>  
  14.                 <input for="Name" class="form-control" bind="@book.Name" />  
  15.             </div>  
  16.             <div class="form-group">  
  17.                 <label for="ISBN" class="control-label">ISBN</label>  
  18.                 <input for="ISBN" class="form-control" bind="@book.ISBN" />  
  19.             </div>  
  20.             <div class="form-group">  
  21.                 <label for="Author" class="control-label">Author</label>  
  22.                 <input for="Author" class="form-control" bind="@book.Author" />  
  23.             </div>  
  24.             <div class="form-group">  
  25.                 <label for="Price" class="control-label">Price</label>  
  26.                 <input for="Price" class="form-control" bind="@book.Price" />  
  27.             </div>  
  28.         </div>  
  29.     </div>  
  30.     <div class="row">  
  31.         <div class="col-md-4">  
  32.             <div class="form-group">  
  33.                 <input type="button" class="btn btn-default" onclick="@(async () => await CreateBook())" value="Save" />  
  34.                 <input type="button" class="btn" onclick="@Cancel" value="Cancel" />  
  35.             </div>  
  36.         </div>  
  37.     </div>  
  38. </form>  
  39.   
  40. @functions {  
  41.   
  42. Book book = new Book();  
  43.   
  44. protected async Task CreateBook()  
  45. {  
  46.     await Http.SendJsonAsync(HttpMethod.Post, "/api/books", book);  
  47.     UriHelper.NavigateTo("/listbooks");  
  48. }  
  49.   
  50. void Cancel()  
  51. {  
  52.     UriHelper.NavigateTo("/listbooks");  
  53. }  
  54. }     

EditBook.cshtml

  1. @using BlazorCloudSQL.Shared.Models  
  2.   
  3. @page "/editbook/{id}"  
  4. @inject HttpClient Http  
  5. @inject Microsoft.AspNetCore.Blazor.Services.IUriHelper UriHelper  
  6.   
  7. <h4>Edit Book</h4>  
  8. <hr />  
  9.   
  10. <form>  
  11.     <div class="row">  
  12.         <div class="col-md-8">  
  13.             <div class="form-group">  
  14.                 <label for="Name" class="control-label">Name</label>  
  15.                 <input for="Name" class="form-control" bind="@book.Name" />  
  16.             </div>  
  17.             <div class="form-group">  
  18.                 <label for="ISBN" class="control-label">ISBN</label>  
  19.                 <input for="ISBN" class="form-control" bind="@book.ISBN" />  
  20.             </div>  
  21.             <div class="form-group">  
  22.                 <label for="Author" class="control-label">Author</label>  
  23.                 <input for="Author" class="form-control" bind="@book.Author" />  
  24.             </div>  
  25.             <div class="form-group">  
  26.                 <label for="Price" class="control-label">Price</label>  
  27.                 <input for="Price" class="form-control" bind="@book.Price" />  
  28.             </div>  
  29.         </div>  
  30.     </div>  
  31.     <div class="row">  
  32.         <div class="form-group">  
  33.             <input type="button" class="btn btn-default" onclick="@(async () => await UpdateBook())" value="Save" />  
  34.             <input type="button" class="btn" onclick="@Cancel" value="Cancel" />  
  35.         </div>  
  36.     </div>  
  37. </form>  
  38.   
  39. @functions {  
  40.   
  41. [Parameter]  
  42. string id { getset; }  
  43.   
  44. Book book = new Book();  
  45.   
  46. protected override async Task OnInitAsync()  
  47. {  
  48.     book = await Http.GetJsonAsync<Book>("/api/books/" + id);  
  49. }  
  50.   
  51. protected async Task UpdateBook()  
  52. {  
  53.     await Http.SendJsonAsync(HttpMethod.Put, "api/books", book);  
  54.     UriHelper.NavigateTo("/listbooks");  
  55.   
  56. }  
  57.   
  58. void Cancel()  
  59. {  
  60.     UriHelper.NavigateTo("/listbooks");  
  61. }  
  62. }       

DeleteBook.cshtml

  1. @using BlazorCloudSQL.Shared.Models  
  2.   
  3. @page "/deletebook/{id}"  
  4. @inject HttpClient Http  
  5. @inject Microsoft.AspNetCore.Blazor.Services.IUriHelper UriHelper  
  6.   
  7. <h4>Delete Book</h4>  
  8. <p>Are you sure you want to delete this Book with Id :<b> @id</b></p>  
  9. <hr />  
  10. <div class="col-md-4">  
  11.     <table class="table">  
  12.         <tr>  
  13.             <td>Name</td>  
  14.             <td>@book.Name</td>  
  15.         </tr>  
  16.         <tr>  
  17.             <td>ISBN</td>  
  18.             <td>@book.ISBN</td>  
  19.         </tr>  
  20.         <tr>  
  21.             <td>Author</td>  
  22.             <td>@book.Author</td>  
  23.         </tr>  
  24.         <tr>  
  25.             <td>Price</td>  
  26.             <td>@book.Price</td>  
  27.         </tr>  
  28.     </table>  
  29.     <div class="form-group">  
  30.         <input type="button" value="Delete" onclick="@(async () => await Delete())" class="btn btn-default" />  
  31.         <input type="button" value="Cancel" onclick="@Cancel" class="btn" />  
  32.     </div>  
  33. </div>  
  34.   
  35. @functions {  
  36.   
  37. [Parameter]  
  38. string id { getset; }  
  39.   
  40. Book book = new Book();  
  41.   
  42. protected override async Task OnInitAsync()  
  43. {  
  44.     book = await Http.GetJsonAsync<Book>("/api/books/" + id);  
  45. }  
  46.   
  47. protected async Task Delete()  
  48. {  
  49.     await Http.DeleteAsync("api/books/" + id);  
  50.     UriHelper.NavigateTo("/listbooks");  
  51. }  
  52.   
  53. void Cancel()  
  54. {  
  55.     UriHelper.NavigateTo("/listbooks");  
  56. }  
  57. }       

Let us modify the Index.cshtml as well.

Index.cshtml
  1. @page "/"  
  2.   
  3. <h4>Create a Single Page Blazor App with Google Cloud SQL </h4>  
  4.   
  5. <p>  
  6.     We will see how to create a Google Cloud SQL instance using the MySQL engine and will create a single page application in Blazor.  
  7. </p>  

We have completed all the coding part. Now, we can run the application in a browser.

Create a Blazor App with Google Cloud SQL using MySQL Engine
 
Click the “Book Details” link in the left side navigation bar and add a new book.
 
Create a Blazor App with Google Cloud SQL using MySQL Engine
 
I have added a new book. We can easily edit the book by clicking the “Edit” link in the grid.
 
Create a Blazor App with Google Cloud SQL using MySQL Engine
 
I have just modified the author name. We can add one more book and display all the books in the grid.
 
Create a Blazor App with Google Cloud SQL using MySQL Engine
 
Let us delete a book by clicking the Delete link in the grid. It will ask for a confirmation before deleting from the database.
 
Create a Blazor App with Google Cloud SQL using MySQL Engine
 
We have seen all the CRUD actions in our newly created Books app.

Conclusion

In this post, we have created a new project in Google Cloud console and a Google Cloud SQL instance with MySQL engine. We, then, connected the MySQL instance with MySQL Workbench Community Edition and created a new database. We created a table also in the same database. After that, we created a Blazor application in Visual Studio 2017 Community Edition and created a Book Data Entry app. 

We shall see more exciting features of Blazor framework in upcoming posts.