Bind data to Blazor components using WebApiAdaptor and perform CRUD

1 Feb 202424 minutes to read

In this topic, you can learn how to retrieve data from WebApi Controller, bind to Grid component using WebApiAdaptor of SfDataManger, and perform CRUD operations.

You can use the WebApiAdaptor of SfDataManager to interact with Web APIs created with OData endpoint. The WebApiAdaptor is extended from the ODataAdaptor. Hence, to use WebApiAdaptor, the endpoint should understand the OData formatted queries sent along with the request.

To enable the OData query option for Web API, Refer to this documentation.

Prerequisite software

The following software are needed

  • Visual Studio 2022
  • .NET 7.0 or .NET 8.0.

Create the database

Open Visual Studio , select View -> SQL Server Object Explorer. Right-click on the Databases folder to create a new Database and name it as OrdersDetails.

Add new database in Blazor
Adding database name and location in Blazor

Right-click on the Tables folder of the created database and click Add New Table.

Add table in Blazor

Use the following query to add a new table named Orders.

Create Table Orders(
 OrderID BigInt Identity(1,1) Primary Key Not Null,
 CustomerID Varchar(100) Not Null,
 Freight int Null,
 OrderDate datetime null
)

Now, the Orders table design will look like below. Click on the Update button.

Database table design in Blazor

Now, click on Update Database.

Update database in Blazor

Create a new Blazor Web App

You can create a Blazor Web App using Visual Studio 2022 via Microsoft Templates or the Syncfusion Blazor Extension.

You need to configure the corresponding Interactive render mode and Interactivity location while creating a Blazor Web Application.

Generate DbContext and model class from the database

Now, you need to scaffold DbContext and model classes from the existing OrdersDetails database. To perform scaffolding and work with the SQL Server database in our application, install the following NuGet packages.If you have created a Blazor Web App with the Interactive render mode set to WebAssembly or Auto ensure to follow these steps:

  • Create the new project with Class Library template named as BlazorWebApp.Shared for DbContext and model class as shown below.
    Create Shared Project

Additionally, ensure that you have added a reference to the BlazorWebApp.Shared project in both the server-side and client-side projects of your web application.

  • Then, open the NuGet Package Manager and install the following packages in both the shared and server-side projects of your Blazor Web App.

Alternatively, you can utilize the following package manager command to achieve the same.

Install-Package Microsoft.EntityFrameworkCore.Tools -Version 7.0.11

Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 7.0.11

Once the above packages are installed, you can scaffold DbContext and Model classes. Run the following command in the Package Manager Console under the BlazorWebApp.Shared project.

Scaffold-DbContext “Server=localhost;Database=OrdersDetails;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False” Microsoft.EntityFrameworkCore.SqlServer -OutputDir Data

The above scaffolding command contains the following details for creating DbContext and model classes for the existing database and its tables.

  • Connection string: Server=localhost;Database=OrdersDetails;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False
  • Data provider: Microsoft.EntityFrameworkCore.SqlServer
  • Output directory: -OutputDir Data

After running the above command, OrdersDetailsContext.cs and Orders.cs files will be created under the Data folder of BlazorWebApp.Shared project as follows.

Data folder in BlazorWebApp.Shared

You can see that OrdersDetailsContext.cs file contains the connection string details in the OnConfiguring method.

using Microsoft.EntityFrameworkCore;

namespace BlazorWebApp.Shared.Data;

public partial class OrdersDetailsContext : DbContext
{
    public OrdersDetailsContext()
    {
    }

    public OrdersDetailsContext(DbContextOptions<OrdersDetailsContext> options)
        : base(options)
    {
    }

    public virtual DbSet<Order> Orders { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)=> optionsBuilder.UseSqlServer("Server=(localdb)\\MSSQLLocalDB;Database=OrdersDetails;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False");
  .....
}

Additionally ensure the connection strings added in the appsettings.json file of server side project of your Web App.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "OrdersDetailsDatabase": "Server=(localdb)\\MSSQLLocalDB;Database=OrdersDetails;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
  }
}
  • Now, the DbContext must be configured using connection string and registered as scoped service using the AddDbContext method in Program.cs of server side project only.
builder.Services.AddDbContext<OrdersDetailsContext>(option =>
                option.UseSqlServer(builder.Configuration.GetConnectionString("OrdersDetailsDatabase")));

Creating API Controller

The application is now configured to connect with the OrdersDetails database using Entity Framework. Now, it’s time to consume data from the OrdersDetails database. To do so, you need a Web API controller to serve data from the DbContext to the Blazor application.

To create a Web API controller, right-click the Controller folder in the Server side project and select Add -> New Item -> API controller with read/write actions to create a new Web API controller. We are naming this controller as OrdersController as it returns Orders table records.

Now, replace the Web API controller with the following code which contains code to handle CRUD operations in the Orders table.

using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WebAPICRUDServerApp.Data;

namespace WebAPICRUDServerApp
{
    [Route("api/[controller]")]
    [ApiController]
    public class OrdersController : ControllerBase
    {
        private OrdersDetailsContext _context;
        public OrdersController(OrdersDetailsContext context)
        {
            _context = context;
        }
        // GET: api/<OrdersController>
        [HttpGet]
        public object Get()
        {
            return new { Items = _context.Orders, Count = _context.Orders.Count() };
        }
        // POST api/<OrdersController>
        [HttpPost]
        public void Post([FromBody] Orders book)
        {
            _context.Orders.Add(book);
            _context.SaveChanges();
        }
        // PUT api/<OrdersController>
        [HttpPut]
        public void Put(long id, [FromBody] Orders book)
        {
            Orders _book = _context.Orders.Where(x => x.OrderId.Equals(book.OrderId)).FirstOrDefault();
            _book.CustomerId = book.CustomerId;
            _book.Freight = book.Freight;
            _book.OrderDate = book.OrderDate;
            _context.SaveChanges();
        }
        // DELETE api/<OrdersController>
        [HttpDelete("{id}")]
        public void Delete(long id)
        {
            Orders _book = _context.Orders.Where(x => x.OrderId.Equals(id)).FirstOrDefault();
            _context.Orders.Remove(_book);
            _context.SaveChanges();
        }
    }
}
  • Now, open Program.cs file and add AddControllers & MapControllers method as follows.
......
builder.Services.AddControllers();
....
app.MapControllers();
.....

Create Blazor Server Application

You can create a Blazor Server App using Visual Studio via Microsoft Templates or the Syncfusion Blazor Extension.

Generate DbContext and model class from the database

Now, you need to scaffold DbContext and model classes from the existing OrdersDetails database. To perform scaffolding and work with the SQL Server database in our application, install the following NuGet packages.

Run the following commands in the Package Manager Console.

Install-Package Microsoft.EntityFrameworkCore.Tools -Version 7.0.11

Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 7.0.11
Scaffold-DbContext “Server=localhost;Database=OrdersDetails;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False” Microsoft.EntityFrameworkCore.SqlServer -OutputDir Data

The above scaffolding command contains the following details for creating DbContext and model classes for the existing database and its tables.

  • Connection string: Server=localhost;Database=OrdersDetails;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False
  • Data provider: Microsoft.EntityFrameworkCore.SqlServer
  • Output directory: -OutputDir Data

After running the above command, OrdersDetailsContext.cs and Orders.cs files will be created under the WebAPICRUDServerApp.Data folder as follows.

Data folder in Blazor

You can see that OrdersDetailsContext.cs file contains the connection string details in the OnConfiguring method.

using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;

namespace WebAPICRUDServerApp.Data
{
    public partial class OrdersDetailsContext : DbContext
    {
        public OrdersDetailsContext()
        {
        }

        public OrdersDetailsContext(DbContextOptions<OrdersDetailsContext> options)
            : base(options)
        {
        }

        public virtual DbSet<Order> Orders { get; set; } = null!;

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseSqlServer("Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=OrdersDetails;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False");
            }
        }

        ...
    }
}

It is not recommended to have a connection string with sensitive information in the OrdersDetailsContext.cs file, so the connection string is moved to the appsettings.json file.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "OrdersDetailsDatabase": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=OrdersDetails;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
  }
}

Now, the DbContext must be configured using connection string and registered as scoped service using the AddDbContext method in Program.cs file in .NET 6 and .NET 7 application.

builder.Services.AddDbContext<OrdersDetailsContext>(option =>
                option.UseSqlServer(builder.Configuration.GetConnectionString("OrdersDetailsDatabase")));

Creating API Controller

The application is now configured to connect with the OrdersDetails database using Entity Framework. Now, it’s time to consume data from the OrdersDetails database. To do so, you need a Web API controller to serve data from the DbContext to the Blazor application.

To create a Web API controller, right-click the Controller folder in the Server project and select Add -> New Item -> API controller with read/write actions to create a new Web API controller. We are naming this controller as OrdersController as it returns Orders table records.

Now, replace the Web API controller with the following code which contains code to handle CRUD operations in the Orders table.

using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WebAPICRUDServerApp.Data;

namespace WebAPICRUDServerApp
{
    [Route("api/[controller]")]
    [ApiController]
    public class OrdersController : ControllerBase
    {
        private OrdersDetailsContext _context;
        public OrdersController(OrdersDetailsContext context)
        {
            _context = context;
        }
        // GET: api/<OrdersController>
        [HttpGet]
        public object Get()
        {
            return new { Items = _context.Orders, Count = _context.Orders.Count() };
        }
        // POST api/<OrdersController>
        [HttpPost]
        public void Post([FromBody] Orders book)
        {
            _context.Orders.Add(book);
            _context.SaveChanges();
        }
        // PUT api/<OrdersController>
        [HttpPut]
        public void Put(long id, [FromBody] Orders book)
        {
            Orders _book = _context.Orders.Where(x => x.OrderId.Equals(book.OrderId)).FirstOrDefault();
            _book.CustomerId = book.CustomerId;
            _book.Freight = book.Freight;
            _book.OrderDate = book.OrderDate;
            _context.SaveChanges();
        }
        // DELETE api/<OrdersController>
        [HttpDelete("{id}")]
        public void Delete(long id)
        {
            Orders _book = _context.Orders.Where(x => x.OrderId.Equals(id)).FirstOrDefault();
            _context.Orders.Remove(_book);
            _context.SaveChanges();
        }
    }
}
  • For .NET 6 and .NET 7 applications open Program.cs file and add MapDefaultControllerRoute method as follows.
......

app.UseRouting();

app.MapDefaultControllerRoute();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

Add Syncfusion Blazor DataGrid package

To add Blazor DataGrid component in the app, open the NuGet package manager in Visual Studio (Tools → NuGet Package Manager → Manage NuGet Packages for Solution), search and install Syncfusion.Blazor.Grid and Syncfusion.Blazor.Themes.

If you utilize WebAssembly or Auto render modes in the Blazor Web App need to be install Syncfusion Blazor components NuGet packages within the client project.

Alternatively, you can utilize the following package manager command to achieve the same.

Install-Package Syncfusion.Blazor.Grid -Version 25.1.35
Install-Package Syncfusion.Blazor.Themes -Version 25.1.35

NOTE

Syncfusion Blazor components are available in nuget.org. Refer to NuGet packages topic for available NuGet packages list with component details.

Open ~/_Imports.razor file and import the following namespace.

  • RAZOR
  • @using Syncfusion.Blazor
    @using Syncfusion.Blazor.Grids

    Now, register the Syncfusion Blazor Service in the ~/Program.cs file of your App.

    For a Blazor Web App with WebAssembly or Auto (Server and WebAssembly) interactive render mode, register the Syncfusion Blazor service in both ~/Program.cs files of your web app.

    ....
    using Syncfusion.Blazor;
    ....
    builder.Services.AddSyncfusionBlazor();
    ....

    Themes provide life to components. Syncfusion Blazor has different themes. They are:

    • Fabric
    • Bootstrap
    • Material
    • High Contrast

    In this demo application, the latest theme will be used.

    • For Blazor Web App, refer stylesheet inside the <head> of ~/Components/App.razor file for .NET 8.

    • For Blazor WebAssembly application, refer stylesheet inside the <head> element of wwwroot/index.html file.
    • For Blazor Server application, refer stylesheet inside the <head> element of
      • ~/Pages/_Host.cshtml file for .NET 7.
      • ~/Pages/_Layout.cshtml file for .NET 6.
  • CSHTML
  • <link href="_content/Syncfusion.Blazor.Themes/bootstrap5.css" rel="stylesheet" />

    Also, Include the script reference at the end of the <body> of ~/Components/App.razor(For Blazor Web App) or Pages/_Host.cshtml (for Blazor Server App) file as shown below:

    <body>
        ....
        <script src="_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js" type="text/javascript"></script>
    </body>

    Add Syncfusion Blazor DataGrid component to an application

    In previous steps, you have successfully configured the Syncfusion Blazor package in the application. Now, you can add the grid component to the to the .razor page inside the Pages folder.

    If you have set the interactivity location to Per page/component in the web app, ensure that you define a render mode at the top of the Syncfusion Blazor component-included razor page as follows:

    @* Your App render mode define here *@
    @rendermode InteractiveAuto
    <SfGrid TValue="Orders"></SfGrid>

    Binding data to Blazor DataGrid component using WebApiAdaptor

    To consume data from the WebApi Controller, you need to add the SfDataManager with WebApiAdaptor. Refer to the following documentation for more details on WebApiAdaptor.

    <SfGrid TValue="Orders">
        <SfDataManager Url="api/Orders" Adaptor="Adaptors.WebApiAdaptor"></SfDataManager>
    </SfGrid>

    Grid columns can be defined by using the GridColumn component. We are going to create columns using the following code.

    <SfGrid TValue="Orders">
        <SfDataManager Url="api/Orders" Adaptor="Adaptors.WebApiAdaptor"></SfDataManager>
        <GridColumns>
            <GridColumn Field=@nameof(Orders.OrderId) HeaderText="Order ID" IsPrimaryKey="true" Visible="false" TextAlign="TextAlign.Right" Width="120"></GridColumn>
            <GridColumn Field=@nameof(Orders.CustomerId) HeaderText="Customer Name" Width="150"></GridColumn>
            <GridColumn Field=@nameof(Orders.OrderDate) HeaderText=" Order Date" Format="d" Type="ColumnType.Date" TextAlign="TextAlign.Right" Width="130"></GridColumn>
            <GridColumn Field=@nameof(Orders.Freight) HeaderText="Freight" Format="C2" TextAlign="TextAlign.Right" Width="120"></GridColumn>
        </GridColumns>
    </SfGrid>

    When you run the application, the Get() method will be called in your API controller.

    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using WebAPICRUDServerApp.Data;
    
    namespace WebAPICRUDServerApp
    {
        [Route("api/[controller]")]
        [ApiController]
        public class OrdersController : ControllerBase
        {
            private OrdersDetailsContext _context;
            public OrdersController(OrdersDetailsContext context)
            {
                _context = context;
            }
            // GET: api/<OrdersController>
            [HttpGet]
            public object Get()
            {
                return new { Items = _context.Orders, Count = _context.Orders.Count() };
            }
            ...
        }
    }

    The response object from the Web API should contain the properties, Items and Count, whose values are a collection of entities and the total count of the entities, respectively.

    The sample response object should look like this:

    {
        "Items": [{..}, {..}, {..}, ...],
        "Count": 830
    }
    

    Handling CRUD operations with our Syncfusion Blazor DataGrid component

    You can enable editing in the grid component using the GridEditSettings component. Grid provides various modes of editing options such as Inline/Normal, Dialog, and Batch editing.

    Here, we are using Inline edit mode and used Toolbar property to show toolbar items for editing.
    We have added the DataGrid Editing and Toolbar code with previous Grid model.

    <SfGrid TValue="Orders" Toolbar="@(new List<string>() { "Add", "Edit", "Delete", "Cancel", "Update" })">
        <SfDataManager Url="api/Orders" Adaptor="Adaptors.WebApiAdaptor"></SfDataManager>
        <GridEditSettings AllowAdding="true" AllowDeleting="true" AllowEditing="true" Mode="EditMode.Normal"></GridEditSettings>
        <GridColumns>
            <GridColumn Field=@nameof(Orders.OrderId) HeaderText="Order ID" IsPrimaryKey="true" Visible="false" TextAlign="TextAlign.Right" Width="120"></GridColumn>
            <GridColumn Field=@nameof(Orders.CustomerId) HeaderText="Customer Name" Width="150"></GridColumn>
            <GridColumn Field=@nameof(Orders.OrderDate) HeaderText=" Order Date" Format="d" Type="ColumnType.Date" TextAlign="TextAlign.Right" Width="130"></GridColumn>
            <GridColumn Field=@nameof(Orders.Freight) HeaderText="Freight" Format="C2" TextAlign="TextAlign.Right" Width="120"></GridColumn>
        </GridColumns>
    </SfGrid>

    NOTE

    Normal editing is the default edit mode for the DataGrid component. Set the IsPrimaryKey property of Column as true for a particular column, whose value is a unique value for editing purposes.

    Insert a row

    To insert a new row, click the Add toolbar button. The new record edit form will look like below.

    Insert Operation in Blazor

    Clicking the Update toolbar button will insert the record in the Orders table by calling the following POST method of the Web API.

    public void Post([FromBody] Orders book)
    {
        _context.Orders.Add(book);
        _context.SaveChanges();
    }

    Insert Operation in Blazor

    Update a row

    To edit a row, select any row and click the Edit toolbar button. The edit form will look like below. Edit the Customer Name column.

    Update Operation in Blazor

    Clicking the Update toolbar button will update the record in the Orders table by calling the following PUT method of the Web API.

    public void Put(long id, [FromBody] Orders book)
    {
        Orders _book = _context.Orders.Where(x => x.OrderId.Equals(book.OrderId)).FirstOrDefault();
        _book.CustomerId = book.CustomerId;
        _book.Freight = book.Freight;
        _book.OrderDate = book.OrderDate;
        _context.SaveChanges();
    }

    Update Operation in Blazor

    Delete a row

    To delete a row, select any row and click the Delete toolbar button. Deleting operation will send a DELETE request to the Web API with the selected record`s primary key value to remove the corresponding record from the Orders table.

    public void Delete(long id)
    {
        Orders _book = _context.Orders.Where(x => x.OrderId.Equals(id)).FirstOrDefault();
        _context.Orders.Remove(_book);
        _context.SaveChanges();
    }

    NOTE

    Find the sample from this Github location.