15. ASP.NET Core 5 – CRUD Using Blazor And Entity Framework Core

Ankit Sharma, 2020.05.28 Updated to .NET Core 3.2 Preview-1
Tutorial: https://www.c-sharpcorner.com/article/asp-net-core-crud-using-blazor-and-entity-framework-core/

Github: https://github.com/AnkitSharma-007/ASPCore.BlazorCrud

Deploy on IIS : https://www.c-sharpcorner.com/article/deploying-a-blazor-application-on-iis/

 

Employee CRUD module (app.)

(Record Management System)

Open MS SQL Server Management studio (tool simmilar to Oracle SQLDeveloper or PHPMyadmin) and create tblEmployee table (catalog) in eg WizLib DB. Connect params are :
Server type:     DB engine
Server name :  localhost\SQLEXPRESS
Auth : Win auth
User name :  SSPC2/ss

Create table tblEmployee( 
  EmployeeId int IDENTITY(1,1) NOT NULL, 
  Name varchar(20) NOT NULL, 
  City varchar(20) NOT NULL, 
  Department varchar(20) NOT NULL, 
  Gender varchar(6) NOT NULL 
)

STEP 1. same as in Calculator example (L:\3_sw_video\net_core\BlazorDemoCalc_AnkitSharma202005.html).

Be aware: Sharma’s tutorials are older than his Github code (.sln) which is in this article !

3 project files (in corresponding 3 dirs) created inside solution dir BlazorCrudEMP : see J:\netcore\source\repos\BlazorCrudEMP\BlazorCrud.sln

  1. BlazorCrud.Client – It has the client-side code and contains the pages that will be rendered on the browser.
  2. BlazorCrud.Server – It has the server-side codes such as DB related operations and web API.
  3. BlazorCrud.Shared – It contains the shared code that can be accessed by both client and server.

Execute the program – click F5 or on IIS while on client proj. – displays navig.menu links Home and Fetch Employees.
No more M, V and C dirs !

Original Counter and Fetch Data pages created automaticaly we deleted.

 

STEP 2. Adding Model to App

  1. Right-click on BlazorCrud.Shared project and then select Add >> New Folder and name the folder as Models. We will be adding our model class in this folder only.
  2. Right-click on Models folder and select Add >> Class. Name your class Employee. This class will contain our Employee model properties.
  3. Open Employee.cs
    J:\netcore\source\repos\BlazorCrudEMP\BlazorCrud\Shared\Models\Employee.cs and put the following code in it :
// J:\netcore\source\repos\BlazorCrudEMP\BlazorCrud\Shared\Models\Employee.cs
using System.ComponentModel.DataAnnotations;

namespace BlazorCrud.Shared.Models
{
    public class Employee
    {
        public int EmployeeId { get; set; }
        [Required]
        public string Name { get; set; }
        [Required]
        public string Gender { get; set; }
        [Required]
        public string Department { get; set; }
        [Required]
        public string City { get; set; }
    }
}

 

STEP 3. Creating DAL for App

DAL is Data Access Layer, here connect string and adapter CRUD functions for calling CRUD fns of lower level.

Right click on Models folder in BlazorCrud.Shared project  and select Add >> Class. Name your class EmployeeContext. This is our Entity Framework DB context class to interact with database. Open EmployeeContext.cs and put the following code into it.

using BlazorCrud.Shared.Models;
// J:\netcore\source\repos\BlazorCrudEMP\BlazorCrud\Shared\Models\EmployeeContext.cs
using Microsoft.EntityFrameworkCore;

namespace BlazorCrud.Server.DataAccess
{
    public class EmployeeContext : DbContext
    {
        public virtual DbSet<Employee> tblEmployee { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                //"ora7": "User Id=hr;Password=hr; Data Source=sspc2:1521/XE;"
                //optionsBuilder.UseSqlServer(@"Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=myTestDB;Data Source=ANKIT-LENOVO\SQLEXPRESS;");
                optionsBuilder.UseSqlServer(@"Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=WizLib;Data Source=localhost\SQLEXPRESS;");
            }
        }
    }
}

Do not forget to put your own connection string.

Right click on BlazorCrud.Server project and then select Add >> New Folder and name the folder DataAccess. We will be adding our classes to handle database related operations inside this folder only. Add class to DataAccess folder and name it as EmployeeDataAccessLayer.

// J:\netcore\source\repos\BlazorCrudEMP\BlazorCrud\Server\DataAccess\EmployeeDataAccessLayer.cs
// This class will handle our CRUD related DB operations
using BlazorCrud.Server.Interfaces;
using BlazorCrud.Shared.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BlazorCrud.Server.DataAccess
{
    public class EmployeeDataAccessLayer: IEmployee
    {
        EmployeeContext db = new EmployeeContext();

        //To Get all employees details   
        public IEnumerable<Employee> GetAllEmployees()
        {
            try
            {
                return db.tblEmployee.ToList();
            }
            catch
            {
                throw;
            }
        }

        //To Add new employee record     
        public void AddEmployee(Employee employee)
        {
            try
            {
                db.tblEmployee.Add(employee);
                db.SaveChanges();
            }
            catch
            {
                throw;
            }
        }

        //To Update the records of a particluar employee    
        public void UpdateEmployee(Employee employee)
        {
            try
            {
                db.Entry(employee).State = EntityState.Modified;
                db.SaveChanges();
            }
            catch
            {
                throw;
            }
        }

        //Get the details of a particular employee    
        public Employee GetEmployeeData(int id)
        {
            try
            {
                Employee employee = db.tblEmployee.Find(id);
                return employee;
            }
            catch
            {
                throw;
            }
        }

        //To Delete the record of a particular employee    
        public void DeleteEmployee(int id)
        {
            try
            {
                Employee emp = db.tblEmployee.Find(id);
                db.tblEmployee.Remove(emp);
                db.SaveChanges();
            }
            catch
            {
                throw;
            }
        }
    }
}

And hence our data access layer is complete.

 

 

Now, we will proceed to create our web API Controller.

STEP 4. Adding web API Controller to App

Right click on BlazorCrud.Server/Controllers folder and select Add >> New Item. An “Add New Item” dialog box will open. Select ASP.NET from the left panel, then select “API Controller Class” from templates panel and put the name as EmployeeController. Press OK.

EmployeeController class calls methods of EmployeeDataAccessLayer class and pass on data to client side.

// J:\netcore\source\repos\BlazorCrudEMP\BlazorCrud\Server\Controllers\EmployeeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BlazorCrud.Server.Interfaces;
using BlazorCrud.Shared.Models;
using Microsoft.AspNetCore.Mvc;

// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860

namespace BlazorCrud.Server.Controllers
{
    [Route("api/[controller]")]
    public class EmployeeController : Controller
    {
        private readonly IEmployee objemployee;

        public EmployeeController(IEmployee _objemployee)
        {
            objemployee = _objemployee;
        }

        [HttpGet]
        [Route("Index")]
        public IEnumerable<Employee> Index()
        {
            return objemployee.GetAllEmployees();
        }

        [HttpPost]
        [Route("Create")]
        public void Create([FromBody] Employee employee)
        {
            if (ModelState.IsValid)
                objemployee.AddEmployee(employee);
        }

        [HttpGet]
        [Route("Details/{id}")]
        public Employee Details(int id)
        {

            return objemployee.GetEmployeeData(id);
        }

        [HttpPut]
        [Route("Edit")]
        public void Edit([FromBody]Employee employee)
        {
            if (ModelState.IsValid)
                objemployee.UpdateEmployee(employee);
        }

        [HttpDelete]
        [Route("Delete/{id}")]
        public void Delete(int id)
        {
            objemployee.DeleteEmployee(id);
        }
    }
}

We are done with our backend logic. So, we will now proceed to code our client side.

 

STEP 5. Adding Razor Views to App

Right click on BlazorCrud.Client/Pages folder and then select Add >> New Item. An “Add New Item” dialog box will open, select Web from the left panel, then select “Razor View” from templates panel and name it FetchEmployee.cshtml.

This will add a FetchEmployee.cshtml page to our BlazorCrud.Client/Pages folder. Similarly add 3 more pages AddEmployee.cshtml, EditEmployee.cshtml and DeleteEmployee.cshtml.

Let’s add codes to these pages

5.1 V FetchEmployee.razor (was .cshtml)

This page will be displaying all the employee records present in the database. Additionally, we will also provide action methods Edit and Delete on each record. Open FetchEmployee.cshtml and put the following code in it.

@* J:\netcore\source\repos\BlazorCrudEMP\BlazorCrud\Client\Pages\FetchEmployee.razor *@
@page "/fetchemployee"
@using BlazorCrud.Shared.Models
@inject HttpClient Http


<h1>Employee Data</h1>
<p>This component demonstrates fetching Employee data from the server.</p>

<p>
    <a href="/addemployee">Create New</a>
</p>

@if (empList == null)
{
<p><em>Loading...</em></p> }
            else
            {
<table class='table'>
    <thead>
        <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Gender</th>
            <th>Department</th>
            <th>City</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var emp in empList)
        {
<tr>
    <td>@emp.EmployeeId</td>
    <td>@emp.Name</td>
    <td>@emp.Gender</td>
    <td>@emp.Department</td>
    <td>@emp.City</td>
    <td>
        <a href='/editemployee/@emp.EmployeeId'>Edit</a>  |
        <a href='/delete/@emp.EmployeeId'>Delete</a>
    </td>
</tr>}
    </tbody>
</table>}


@code { Employee[] empList;

  protected override async Task OnInitializedAsync()
  {
     empList = await Http.GetJsonAsync<Employee[]>("/api/Employee/Index");
  }
}

Let’s understand this code

On the top, we have included Blazor.Shared.Models namespace so that we can use our Employee model class in this page.

We are defining the route of this page using @page directive. So, in this application, if we append “/fetchemployee” to base URL then we will be redirected to this page.

We are also injecting HttpClient service to enable web API call.

Then we have defined the HTML part to display all the employees record in a tabular manner. We have also added two action links for Edit and Delete which will navigate to EditEmployee.cshtml and DeleteEmployee.cshtml pages.

At the bottom of the page, we have a @code (eas functions) section which contains our business logic. We have created an array variable empList of type Employee and populating it inside OnInitAsync method by calling our web API. This will bind to our HTML table on the page load.

 

5.2 V AddEmployee.razor

This page is used to create a new employee record.

@* J:\netcore\source\repos\BlazorCrudEMP\BlazorCrud\Client\Pages\AddEmployee.razor *@
@page "/addemployee"
@using BlazorCrud.Shared.Models
@inject HttpClient Http
@inject NavigationManager urlNavigationManager

<h1>Create Employee</h1>
<hr />

<EditForm Model="@emp" OnValidSubmit="CreateEmployee">
    <DataAnnotationsValidator />
    <div class="form-group row">
        <label class="control-label col-md-12">Name</label>
        <div class="col-md-4">
            <input class="form-control" @bind="emp.Name" />
        </div>
        <ValidationMessage For="@(() => emp.Name)" />
    </div>
    <div class="form-group row">
        <label class="control-label col-md-12">Gender</label>
        <div class="col-md-4">
            <select class="form-control" @bind="emp.Gender">
                <option value="">-- Select Gender --</option>
                <option value="Male">Male</option>
                <option value="Female">Female</option>
            </select>
        </div>
        <ValidationMessage For="@(() => emp.Gender)" />
    </div>
    <div class="form-group row">
        <label class="control-label col-md-12">Department</label>
        <div class="col-md-4">
            <input class="form-control" @bind="emp.Department" />
        </div>
        <ValidationMessage For="@(() => emp.Department)" />
    </div>
    <div class="form-group row">
        <label class="control-label col-md-12">City</label>
        <div class="col-md-4">
            <input class="form-control" @bind="emp.City" />
        </div>
        <ValidationMessage For="@(() => emp.City)" />
    </div>
    <div class="form-group">
        <button type="submit" class="btn btn-primary">Save</button>
        <button class="btn btn-light" @onclick="Cancel">Cancel</button>
    </div>
</EditForm>

@code { Employee emp = new Employee();

   protected async Task CreateEmployee()
   {
      await Http.SendJsonAsync(HttpMethod.Post, "/api/Employee/Create", emp);
      urlNavigationManager.NavigateTo("/fetchemployee");
   }

   void Cancel()
   {
      urlNavigationManager.NavigateTo("/fetchemployee");
   }
 }

In this page the route is “/addemployee”.

We are also injecting urlNavigationManager (was “Microsoft.AspNetCore.Blazor.Services.IUriHelper”) service to enable URL redirection. The HTML part will generate a form to get inputs from the user. The attribute “bind” is used to bind the value entered in the textbox to the properties of Employee object.

In the @code (was functions) section we have defined two methods :

  1.  CreateEmployee will be invoked on clicking “Submit” button and send a POST request to our API along with the Employee object emp.
  2. Cancel method will be invoked on clicking cancel button and redirect the user back to FetchEmployee page.

5.3 V EditEmployee.razor

@* J:\netcore\source\repos\BlazorCrudEMP\BlazorCrud\Client\Pages\EditEmployee.razor *@
@page "/editemployee/{empID:int}"
@using BlazorCrud.Shared.Models
@inject HttpClient Http
@inject NavigationManager urlNavigationManager

<h2>Edit Employee</h2>
<hr />

<EditForm Model="@emp" OnValidSubmit="UpdateEmployee">
    <DataAnnotationsValidator />
    <div class="form-group row">
        <label class="control-label col-md-12">Name</label>
        <div class="col-md-4">
            <input class="form-control" @bind="emp.Name" />
        </div>
        <ValidationMessage For="@(() => emp.Name)" />
    </div>
    <div class="form-group row">
        <label class="control-label col-md-12">Gender</label>
        <div class="col-md-4">
            <select asp-for="Gender" class="form-control" @bind="emp.Gender">
                <option value="">-- Select Gender --</option>
                <option value="Male">Male</option>
                <option value="Female">Female</option>
            </select>
        </div>
        <span><ValidationMessage For="@(() => emp.Gender)" /></span>
    </div>
    <div class="form-group row">
        <label class="control-label col-md-12">Department</label>
        <div class="col-md-4">
            <input class="form-control" @bind="emp.Department" />
        </div>
        <span><ValidationMessage For="@(() => emp.Department)" /></span>
    </div>
    <div class="form-group row">
        <label class="control-label col-md-12">City</label>
        <div class="col-md-4">
            <input class="form-control" @bind="emp.City" />
        </div>
        <span><ValidationMessage For="@(() => emp.City)" /></span>
    </div>
    <div class="form-group">
        <button type="submit" class="btn btn-primary">Save</button>
        <button class="btn btn-light" @onclick="Cancel">Cancel</button>
    </div>
</EditForm>

@code { [Parameter]
    public int empID { get; set; }

    Employee emp = new Employee();

    protected override async Task OnInitializedAsync()
    {
        emp = await Http.GetJsonAsync<Employee>("/api/Employee/Details/" + empID);
    }

    protected async Task UpdateEmployee()
    {
        await Http.SendJsonAsync(HttpMethod.Put, "api/Employee/Edit", emp);
        urlNavigationManager.NavigateTo("/fetchemployee");
    }

    void Cancel()
    {
        urlNavigationManager.NavigateTo("/fetchemployee");
    }
}

In this page we have defined the route as “/editemployee/{empID}”. empID is an URL parameter of type string declared in @code section. We will use the [Parameter] attribute to mark the variable as a parameter. To navigate to this page, we need to pass the employee id in the URL which will be captured in empID variable. If we do not mark the variable with the [Parameter] attribute, we will get an error “Object of type ‘BlazorCrud.Client.Pages.EditEmployee’ has a property matching the name ’empID’, but it does not have [ParameterAttribute] applied.”. This will not allow empID to bind to the employee id value passed in the parameter.

The HTML part is similar to that of AddEmployee.cshtml page. The attribute “bind” is used for two-way binding; i.e., binding edited textbox values to employee object properties and vice versa.

Inside the @code section we are fetching the employee records in OnInitAsync method based on the employeeID passed in the parameter. This will bind to the fields in the form on page load itself.

UpdateEmployee method will send a PUT request to our API along with the Employee object emp. The Cancel method will be invoked on clicking cancel button and redirect the user back to FetchEmployee page.

5.4 V DeleteEmployee.razor

@* J:\netcore\source\repos\BlazorCrudEMP\BlazorCrud\Client\Pages\DeleteEmployee.razor  *@
@page "/delete/{empID:int}"
@using BlazorCrud.Shared.Models
@inject HttpClient Http
@inject NavigationManager urlNavigationManager

<h2>Delete Employee</h2>
<h3>Are you sure you want to delete employee with id : @empID</h3>
<br />

<div class="col-md-4">
    <table class="table">
        <tr>
            <td>Name</td>
            <td>@emp.Name</td>
        </tr>
        <tr>
            <td>Gender</td>
            <td>@emp.Gender</td>
        </tr>
        <tr>
            <td>Department</td>
            <td>@emp.Department</td>
        </tr>
        <tr>
            <td>City</td>
            <td>@emp.City</td>
        </tr>
    </table>
    <div class="form-group">
        <button class="btn btn-danger" @onclick="(async () => await Delete())">Delete</button>
        <button class="btn btn-light" @onclick="Cancel">Cancel</button>
    </div>
</div>

@code { [Parameter]
    public int empID { get; set; }

    Employee emp = new Employee();

    protected override async Task OnInitializedAsync()
    {
        emp = await Http.GetJsonAsync<Employee>("/api/Employee/Details/" + empID);
    }

    protected async Task Delete()
    {
        await Http.DeleteAsync("api/Employee/Delete/" + Convert.ToInt32(empID));
        urlNavigationManager.NavigateTo("/fetchemployee");
    }

    void Cancel()
    {
        urlNavigationManager.NavigateTo("/fetchemployee");
    }
}

The route for this page is also parametrized since we are fetching the record of the employee on page load.

The HTML part will display the employee data and ask the user for a confirmation to delete the employee record.

Inside the @code section we are fetching the employee records in OnInitAsync method based on the employeeID passed in the parameter. This will display the employee records as the page loads.

The Delete method will be invoked on clicking “Delete” button, which will send a delete request to our API along with the employee ID of the employee to be deleted. On successful deletion the user will be navigated back to FetchEmployee page.

Navigation menu for our module (app.)

Open BlazorCrud.Client/Shared/ NavMenu.razor file and put the following code in it.

@* J:\netcore\source\repos\BlazorCrudEMP\BlazorCrud\Client\Shared\NavMenu.razor *@
<div class="top-row pl-4 navbar navbar-dark">
    <a class="navbar-brand" href="">BlazorCrud</a>
    <button class="navbar-toggler" @onclick="ToggleNavMenu">
        <span class="navbar-toggler-icon"></span>
    </button>
</div>

<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
    <ul class="nav flex-column">

        <li class="nav-item px-3">
            <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
                <span class="oi oi-home" aria-hidden="true"></span> Home
            </NavLink>
        </li>

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

    </ul>
</div>

@code { private bool collapseNavMenu = true;

    private string NavMenuCssClass => collapseNavMenu ? "collapse" : null;

    private void ToggleNavMenu()
    {
        collapseNavMenu = !collapseNavMenu;
    }
}

 

URL R : https://localhost:5001/fetchemployee – URL has “/fetchemployee” appended to it as we have defined it using @page directive.

URL C : https://localhost:5001/addemployee

URL U and D : https://localhost:5001/editemployee/2 – simmilar to releteemployee/2

 

 

WPF :

https://www.youtube.com/watch?v=LUKp76CNmJY         https://goo.gl/Axoeja

https://www.youtube.com/watch?v=NiGsgctfiYM           https://goo.gl/fAUCRh

 

14. ASP.NET CORE 5 : Blazor Getting Started : Calculator module

Ankit Sharma, 2020.05.28 Updated to .NET Core 3.2 Preview-1

Tutorial: https://www.c-sharpcorner.com/article/getting-started-with-blazor/

Github: https://github.com/AnkitSharma-007/ASPCore.BlazorDemo

Calculator module using Blazor

Prerequisites
  • Install .NET Core  SDK from here  or SDK preview
  • Install Visual Studio Community 2019  Latest with the ASP.NET and web development workload selected from here or preview
  • Entity Framework Core Tools >> NuGet or on command-line tools: dotnet tool install –global dotnet-ef
    (Install ASP.NET Core Blazor Language Services extension from here not needed (needed in VS2019) older ?))
  • SQL Server 2012 or above

STEP 1. 

  1. VS2019 >> File >> New >> Project
  2. Select Blazor App C# (older : .NET Core inside Visual C# menu from the left panel)
  3. Select Blazor App (older : “ASP.NET Core Web Application”) from available project types.
  4. Put the name of the project as BlazorDemoCalc and J:\netcore\source\repos
  5. Click “Blazor WebAssembly App”, “ASP.NET Core hosted”, “Progressive web app”

 

STEP 2. Client proj, Pages folder. We will be adding our view pages to this folder only. These pages will be rendered on the web.

Execute the program – displays navigation links Home, Counter, Fetch data in navigation menu are displayed.

  1. Right click on Pages folder in Client proj >> select Add >> New Item
  2.  “Add New Item” dialog box will open. Selected is Visual C# from the left panel (old : select Web) ,
  3. select Razor Component from templates panel and put the name as Calculator (old : Razor View – empty)

J:\netcore\source\repos\BlazorDemoCalc\BlazorDemo\Pages\Calculator.razor

@page "/calculator"

<h1>Basic Calculator Demo Using Blazor</h1>
<hr />
<div>
    <div class="row">
        <div class="col-md-3">
            <p>First Number</p>
        </div>
        <div class="col-md-4">
            <input placeholder="Enter First Number" @bind="@num1" />
        </div>
    </div>
    <br />
    <div class="row">
        <div class="col-md-3">
            <p>Second Number</p>
        </div>
        <div class="col-md-4">
            <input placeholder="Enter Second Number" @bind="@num2" />
        </div>
    </div>
    <br />
    <div class="row">
        <div class="col-md-3">
            <p>Result</p>
        </div>
        <div class="col-md-4">
            <input readonly @bind="@finalresult" />
        </div>
    </div>
    
    <br />
    <div class="row">
        <div class="col-md-2">
            <button @onclick="AddNumbers" class="btn btn-light">Add (+)</button>
        </div>
        <div class="col-md-2">
            <button @onclick="SubtractNumbers" class="btn btn-primary">Subtract (−)</button>
        </div>
        <div class="col-md-2">
            <button @onclick="MultiplyNumbers" class="btn btn-success ">Multiply (X)</button>
        </div>
        <div class="col-md-2">
            <button @onclick="DivideNumbers" class="btn btn-info">Divide (/)</button>
        </div>
    </div>
</div>

@code {
    string num1;
    string num2;
    string finalresult;
    void AddNumbers()
    {
        finalresult = (Convert.ToDouble(num1) + Convert.ToDouble(num2)).ToString();
    }
    void SubtractNumbers()
    {
        finalresult = (Convert.ToDouble(num1) - Convert.ToDouble(num2)).ToString();
    }
    void MultiplyNumbers()
    {
        finalresult = (Convert.ToDouble(num1) * Convert.ToDouble(num2)).ToString();
    }
    void DivideNumbers()
    {
        if (Convert.ToDouble(num2) != 0)
        {
            finalresult = (Convert.ToDouble(num1) / Convert.ToDouble(num2)).ToString();
        }
        else
        {
            finalresult = "Cannot Divide by Zero";
        }
    }
}

Let’s understand Calculator.razor

On the top, we are defining the route of this page using @page directive. So in this module, if we append “/calculator” to base URL then we will be redirected to this page.

Then we have defined the HTML section to read two numbers from the user and display the result in another textbox. The attribute “bind is used to bind the value entered in the textbox to the variables we have defined. We also created four buttons to perform our basic arithmetic operations. We are calling our business logic methods on button click.

At the bottom of the page, we have a @code (was functions) section which contains all our business logic. We have declared three variables, two variables to read the value from the user and another one to display the result. We have also defined four methods to handle addition, subtraction, multiplication, and division. The “bind” attribute will work only for string variables not for floating point values. Hence, we need to convert a string to double to perform our arithmetic operations.

 

 

STEP 3.  Add the link to our “calculator” page in the navigation menu, open /Shared/NavMenu.razor page

J:\netcore\source\repos\BlazorDemoCalc\BlazorDemo\Shared\NavMenu.razor

and put the following BLUE COLORED code into it.

<div class="top-row pl-4 navbar navbar-dark">
    <a class="navbar-brand" href="">BlazorDemoCalcDev</a>
    <button class="navbar-toggler" @onclick="ToggleNavMenu">
        <span class="navbar-toggler-icon"></span>
    </button>
</div>

<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
    <ul class="nav flex-column">
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
                <span class="oi oi-home" aria-hidden="true"></span> Home
            </NavLink>
        </li>
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="counter">
                <span class="oi oi-plus" aria-hidden="true"></span> Counter
            </NavLink>
        </li>
        <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>

        <li class="nav-item px-3">
            <NavLink class="nav-link" href="calculator">
                <span class="oi oi-plus" aria-hidden="true"></span> Calculator
            </NavLink>
        </li>
    </ul>
</div>

@code {
    private bool collapseNavMenu = true;

    private string NavMenuCssClass => collapseNavMenu ? "collapse" : null;

    private void ToggleNavMenu()
    {
        collapseNavMenu = !collapseNavMenu;
    }
}

 

What is Blazor

Blazor framework is not supported by versions below Visual Studio 2017 v15.7. Microsoft defined Blazor as an experimental project and it was in alpha phase as of March 30, 2018. Blazor is new free, open source .NET Web framework for creating client-side applications using C# / Razor and HTML that runs in the browser with WebAssembly, see http://webassembly.org/

What is WebAssembly

WebAssembly (abbreviated Wasm) is low-level assembly-like language with a compact binary format that can run in modern web browser. Since it is a low-level binary code, it cannot be read/written by humans but we can compile the code from other languages to WebAssembly to facilitate their execution on the browser. It is a subset of JavaScript and is designed to complement and run alongside JavaScript. It enables us to run code written in multiple language on the web at near native speed.
WebAssembly is developed as a web standard and is supported by all the major browsers without plugins.

Why use Blazor

Blazor makes web development easier and more productive by providing a full stack web development with .NET. It runs in all browsers on the real .NET runtime and have full support for .NET Standard without the need of any extra plugin. Blazor is fast, have reusable components and is open-source with a great support from the community.
Blazor also supports features of a SPA framework such as:
  • Routing
  • Layouts
  • Forms and validation
  • JavaScript interop
  • Build on save during development
  • Server-side rendering
  • Dependency Injection

Using .NET for developing Client-side application has multiple advantages :

  1. .NET offers a range of API and tools across all platform that are stable and easy to use.
  2. The modern languages such as C# and F# offer a lot of features that make programming easier and interesting for developers.
  3. The availability of one of the best IDE in form of Visual Studio provides a great .NET development experience across multiple platforms such as Windows, Linux, and MacOS.
  4. .NET provides features such as speed, performance, security, scalability, and reliability in web development that makes full stack development easier.

 

 

See Fluxor https://github.com/mrpmorris/fluxor

https://medium.com/pipelinespace/setting-up-a-ci-cd-pipeline-in-azure-devops-for-blazor-and-deploy-to-azure-c262c58d8172