--- sidebar_position: 3 title: Creating a data service --- As we previously added the addition of an item, we now have two places in the code in our code where we access our local storage. In order to simplify the management of our code, we will therefore use the IOC & DI. In our framework, we are going to use the native IOC of AspNetCore, we are going to use the DI to manage our data. We have already used the AspNetCore IOC with properties using the `[Inject]` attribute, these being managed by the system or external libraries. ## Creating the data service interface We will therefore create a `Services` directory at the root of our site and create our interface. ```csharp title="Services/IDataService.cs" public interface IDataService { Task Add(ItemModel model); Task Count(); Task> List(int currentPage, int pageSize); } ``` Our interface contains the methods to manage our data. ## Creating the Data Service Implementation We will now create our class to manage our data locally. ```csharp title="Services/DataLocalService.cs" public class DataLocalService : IDataService { private readonly HttpClient _http; private readonly ILocalStorageService _localStorage; private readonly NavigationManager _navigationManager; private readonly IWebHostEnvironment _webHostEnvironment; public DataLocalService( ILocalStorageService localStorage, HttpClient http, IWebHostEnvironment webHostEnvironment, NavigationManager navigationManager) { _localStorage = localStorage; _http = http; _webHostEnvironment = webHostEnvironment; _navigationManager = navigationManager; } public async Task Add(ItemModel model) { // Get the current data var currentData = await _localStorage.GetItemAsync>("data"); // Simulate the Id model.Id = currentData.Max(s => s.Id) + 1; // Add the item to the current data currentData.Add(new Item { Id = model.Id, DisplayName = model.DisplayName, Name = model.Name, RepairWith = model.RepairWith, EnchantCategories = model.EnchantCategories, MaxDurability = model.MaxDurability, StackSize = model.StackSize, CreatedDate = DateTime.Now }); // Save the image var imagePathInfo = new DirectoryInfo($"{_webHostEnvironment.WebRootPath}/images"); // Check if the folder "images" exist if (!imagePathInfo.Exists) { imagePathInfo.Create(); } // Determine the image name var fileName = new FileInfo($"{imagePathInfo}/{model.Name}.png"); // Write the file content await File.WriteAllBytesAsync(fileName.FullName, model.ImageContent); // Save the data await _localStorage.SetItemAsync("data", currentData); } public async Task Count() { return (await _localStorage.GetItemAsync("data")).Length; } public async Task> List(int currentPage, int pageSize) { // Load data from the local storage var currentData = await _localStorage.GetItemAsync("data"); // Check if data exist in the local storage if (currentData == null) { // this code add in the local storage the fake data var originalData = await _http.GetFromJsonAsync($"{_navigationManager.BaseUri}fake-data.json"); await _localStorage.SetItemAsync("data", originalData); } return (await _localStorage.GetItemAsync("data")).Skip((currentPage - 1) * pageSize).Take(pageSize).ToList(); } } ``` You will notice that we use another way to inject dependencies into this class through the constructor. `ILocalStorageService` & `HttpClient` & `IWebHostEnvironment` & `NavigationManager` are automatically resolved by the IOC. ## Editing Pages Let's modify our pages to take into account our new service: ```csharp title="Pages/List.razor.cs" public partial class List { private List items; private int totalItem; [Inject] public IDataService DataService { get; set; } [Inject] public IWebHostEnvironment WebHostEnvironment { get; set; } private async Task OnReadData(DataGridReadDataEventArgs e) { if (e.CancellationToken.IsCancellationRequested) { return; } if (!e.CancellationToken.IsCancellationRequested) { items = await DataService.List(e.Page, e.PageSize); totalItem = await DataService.Count(); } } } ``` ```csharp title="Pages/Add.razor.cs" public partial class Add { /// /// The default enchant categories. /// private List enchantCategories = new List() { "armor", "armor_head", "armor_chest", "weapon", "digger", "breakable", "vanishable" }; /// /// The current item model /// private ItemModel itemModel = new() { EnchantCategories = new List(), RepairWith = new List() }; /// /// The default repair with. /// private List repairWith = new List() { "oak_planks", "spruce_planks", "birch_planks", "jungle_planks", "acacia_planks", "dark_oak_planks", "crimson_planks", "warped_planks" }; [Inject] public IDataService DataService { get; set; } [Inject] public NavigationManager NavigationManager { get; set; } private async void HandleValidSubmit() { await DataService.Add(itemModel); NavigationManager.NavigateTo("list"); } private async Task LoadImage(InputFileChangeEventArgs e) { // Set the content of the image to the model using (var memoryStream = new MemoryStream()) { await e.File.OpenReadStream().CopyToAsync(memoryStream); itemModel.ImageContent = memoryStream.ToArray(); } } private void OnEnchantCategoriesChange(string item, object checkedValue) { if ((bool)checkedValue) { if (!itemModel.EnchantCategories.Contains(item)) { itemModel.EnchantCategories.Add(item); } return; } if (itemModel.EnchantCategories.Contains(item)) { itemModel.EnchantCategories.Remove(item); } } private void OnRepairWithChange(string item, object checkedValue) { if ((bool)checkedValue) { if (!itemModel.RepairWith.Contains(item)) { itemModel.RepairWith.Add(item); } return; } if (itemModel.RepairWith.Contains(item)) { itemModel.RepairWith.Remove(item); } } } ``` ## Register the data service Now we have to define in the IOC of our application the resolution of our interface / class. Open the `Program.cs` file and add the following line: ```csharp title="Program.cs" ... builder.Services.AddScoped(); ... ``` Later we will implement data management through an API, it will simply be enough to create a new class `Services/DataApiService.cs` implementing the interface `IDataService` with API calls and modify the IOC with this new service.