DataManager / Custom Adapter - Blazor WebAssembly Project - Best Practice

Hello Team,

I am working on a Blazor Web Assembly project with Offline Feature. The datasource is a WebApi and each request I also need to send a bearer Authorise Token in request header.

What is the correct way to implement a class with CustomAdaptor so that it can be reuse by multiple component with OFFLINE feature:-
  1. I have create an Index.razor component.
  2. I am using three controls in component, Dropdown control "Country", Dropdown control "Employee" and a Gridview showing "TaskList"
  3. Country object consuming from webapi https://xxxyyyxx.com/api/countires, I have also created CountryCustomAdaptor
  4. Employee object consuming from webapi https://xxxyyyxx.com/api/employees, I have also created EmployeeCustomAdaptor
  5. Task object consuming from webapi https://xxxyyyxx.com/api/userTask, I have also created TaskListCustomAdaptor
  1. I have second page Index.razor to perform CRUD operation for Country Object
  2. Country object consuming from webapi https://xxxyyyxx.com/api/countires, I am using above CountryCustomAdaptor
  1. I have third page Index.razor to perform CRUD operation for employee Object
  2. Employee object consuming from webapi https://xxxyyyxx.com/api/employees, , I am using above EmployeeCustomAdaptor
As you can see I am using Country & Employee object in multiple pages, what is the best way to create a class with Custom Adaptor so that client application doesn't perform multiple webapi requests for each page request?


In my TaskList gridview, one of the column is Employee, and in edit template I want to access list of employees from a EmployeeCustomAdaptor, how can i do that?  
below is example where grid is bind to TaskListCustomAdaptor and inside EditTemplate i want to use EmployeeCustomAdaptor

<SfGrid TValue="TaskList" ID="Grid">

 

    <SfDataManager AdaptorInstance="@typeof(TaskListCustomAdaptor)"Adaptor="Adaptors.CustomAdaptor"></SfDataManager>

 

       <GridColumns>

        <GridColumn Field=@nameof(TaskList.Employee) HeaderText="Employee" Width="150">

             <EditTemplate>

                @{

                    List<Employee> employee = EmployeeCustomAdaptor

                   

                    foreach (Employee emp in employee)

                          {

                             .........

                             ...custom code

                          }

                 }

              </EditTemplate>

        </GridColumn>

       <GridColumns>

</SfGrid>



last question: how can i access multiple CustomAdaptor in one compound code section like below:

@code
{
     List<Employee> emp = EmployeeCustomAdaptor;
     List<Country> country = CountryCustomAdaptor;
}


Many thx,
Navneet


3 Replies 1 reply marked as answer

RS Renjith Singh Rajendran Syncfusion Team August 19, 2020 02:14 PM UTC

Hi Navneet, 

Greetings from Syncfusion support. 

We have analyzed your query. Based on your scenario we suggest you to register these custom adaptors as service using AddSingleton and now you can access these across pages. And in OnInitializedAsync or inside these adaptors you can make a web api request to get data during initial loading alone and store that data in any local property and use data from local property for next operation. 

In below code, we have loaded the data from the API service on initial loading in the OnInitializedAsync method and stored this in local variables(Orders, Employees). And use this initially loaded data in the CustomAdaptor. Please refer the code below, 

 
<SfGrid TValue="TaskList" ID="Grid"  AllowPaging="true" Toolbar="@(new List<string>() { "Add""Delete""Update""Cancel" })"> 
    <SfDataManager AdaptorInstance="@typeof(TaskListCustomAdaptor)" Adaptor="Adaptors.CustomAdaptor"></SfDataManager> 
    ... 
    <GridColumns> 
        <GridColumn Field=@nameof(TaskList.OrderID) HeaderText="Order ID" IsPrimaryKey="true" TextAlign="@TextAlign.Center" Width="140"></GridColumn> 
        <GridColumn Field=@nameof(TaskList.CustomerID) HeaderText="Customer Name" Width="150"> 
            <EditTemplate> 
                @{ 
                    var task = (context as TaskList); 
                    <SfDropDownList TValue="string" @bind-Value="@task.CustomerID" TItem="Employee"> 
                        <SfDataManager AdaptorInstance="@typeof(EmployeeCustomAdaptor)" Adaptor="Adaptors.CustomAdaptor"></SfDataManager> 
                        <DropDownListFieldSettings Value="FirstName"></DropDownListFieldSettings> 
                    </SfDropDownList> 
                } 
            </EditTemplate> 
        </GridColumn> 
    </GridColumns> 
</SfGrid> 
 
@code{ 
    public static List<TaskList> Orders { getset; } 
    public static List<Employee> Employees { getset; } 
 
    protected async override Task OnInitializedAsync() 
    { 
        Orders = await Http.GetFromJsonAsync<List<TaskList>>("https://ej2services.syncfusion.com/production/web-services/api/Orders"); 
        Employees = await Http.GetFromJsonAsync<List<Employee>>("https://ej2services.syncfusion.com/production/web-services/api/Employees"); 
    } 
    ...  
    public class TaskListCustomAdaptor : DataAdaptor 
    { 
        public override object Read(DataManagerRequest dm, string key = null) 
        { 
            IEnumerable<TaskList> DataSource = Orders; 
            ... 
            return dm.RequiresCounts ? new DataResult() { Result = DataSource, Count = count } : (object)DataSource; 
        } 
        ... 
    } 
    public class EmployeeCustomAdaptor : DataAdaptor 
    { 
        public override object Read(DataManagerRequest dm, string key = null) 
        { 
            IEnumerable<Employee> DataSource = Employees; 
            ... 
            return dm.RequiresCounts ? new DataResult() { Result = DataSource, Count = count } : (object)DataSource; 
        } 
    } 
} 


We have prepared a sample based on this scenario. Please download the sample form the link below, 
Documentations :  
 
Query : The datasource is a WebApi and each request I also need to send a bearer Authorise Token in request header. 
HttpClient must be provided with the authorization token if you want to use Authorization. Kindly refer the below code example to add authentication header to the global HttpClient object. 

Please use the below code example to add the authentication token, 

@using System.Net.Http.Headers@inject HttpClient Http
... 
 
@code{ 
   protected async override Task OnInitializedAsync() 
    { 
       Http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer""{OAUTH TOKEN}");    //add authentication token, instead of highlighted
     } 
} 
 

Please get back to us if you need further assistance. 

Regards, 
Renjith Singh Rajendran 


Marked as answer

NS Navneet Saraswat August 27, 2020 05:50 AM UTC

Thx Ranjith,

How can i pass authorise token in SfDataManager / CustomAdaptor's  header.

Many thx,
Navneet


RS Renjith Singh Rajendran Syncfusion Team August 28, 2020 12:53 PM UTC

Hi Navneet, 

We suggest you to pass the authorize token as header using Headers property of SfDatamanager. Now you can passing the authorize token along with SfDataManager Url. Refer our UG documentation for your reference  

The above can be used for all the other adaptors like WebApi, OData adaptors etc. but this can’t be used with CustomAdaptor. As in CustomAdaptor, you will using Blazor HttpClient to fetch the data from service. So you can follow the previously suggested solution to pass authorization token for the corresponding service.  


Please get back to us if you need further assistance. 

Regards, 
Renjith Singh Rajendran 


Loader.
Up arrow icon