3
votes

Scenario:

I'm currently creating a basic server side Blazor crud application, Blazor being something I have just started experimenting with.

I've encountered an issue with a back button when navigating back from an edit page to an index page. The issue is as follows:

  1. I edit a record and make some changes to a field without saving
  2. I click the back button which navigates back to the index page
  3. The record that I made changes to within the list of records shows the changes I made in the edit form, however I did not hit save.
  4. I refresh the page and the record returns back to it's original state.

I have tried using a button with an on click and an the following:

<a href="/branches" class="btn btn-sm btn-secondary mr-2"><i class="oi oi-arrow-circle-left"></i> Back</a>

Question:

Any ideas where I'm going wrong?

Index:

@page "/branches"
@inject BranchRepository repository

<GenericList List="branches">    
  <WholeListTemplate>
    <table class="table table-hover">
        <thead>
            <tr>
                <th>Name</th>
                <th>Code</th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            @foreach (var item in branches)
            {
                <tr>
                    <td>@item.sName</td>
                    <td>@item.sBranchNumber</td>
                    <td><a href="/branch/edit/@item.Id" class="btn btn-sm btn-warning">Edit</a></td>
                </tr>
            }
        </tbody>
    </table>
  </WholeListTemplate>
</GenericList>

@code {
  List<Core.Entities.Branch> branches;

  protected async override Task OnInitializedAsync()
  {
    branches = null;
    branches = await repository.GetAllBranches();
  }
}

Edit:

@page "/branch/edit/{id:int}"

@inject NavigationManager navigationManager
@inject BranchRepository repository

<h2>Edit Branch</h2>
<hr />

@if(branch != null)
{
  <BranchEditForm Branch="branch" OnValidSubmit="Update" />
}

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

  private Branch branch;

  protected override void OnInitialized()
  {
    branch = repository.GetById(Id);
  }

  private void Update()
  {
    repository.Update(branch);
    navigationManager.NavigateTo("branches");
  }
}

BranchEditForm:

<EditForm Model="Branch" OnValidSubmit="OnValidSubmit">
   <DataAnnotationsValidator />
    <div class="form-row">
      <div class="form-group col-md-6">
         <label>
            Name
         </label>
         <InputText class="form-control" @bind-Value="@Branch.sName" />
         <ValidationMessage For="@(() => Branch.sName)" />
      </div>
       <div class="form-group col-md-6">
         <label>
            Branch Number
         </label>
         <InputText class="form-control" @bind-Value="@Branch.sBranchNumber" />
         <ValidationMessage For="@(() => Branch.sBranchNumber)" />
       </div>
     </div>

    <a href="/branches" class="btn btn-sm btn-secondary mr-2"><i class="oi oi-arrow-circle-left"></i> Back</a>
    <button type="submit" class="btn btn-sm btn-success"><i class="oi oi-document"></i> Save</button>
</EditForm>

@code {
   [Parameter] public Branch Branch { get; set; }
   [Parameter] public EventCallback OnValidSubmit { get; set; }
}
1
Does your repo cache objects? I.e. does getbyid return the same object that is shown in the list or are you doing some sort of refetch? I'm wondering if you are editing an instance which is then still displayed on the previous page since blazor is pretty much stateful - Charleh
It does look like my object is cached, my .GetById() method does retrieve the same object in the list. Could it be the way I have set up EF Core and registered my DbContext and repository. The only refetch that is triggered is to get my list for the index with an OnInitilized(). - Daya Bhogal
What is the repository lifetime ? - agua from mars
@aguafrommars I'm using AddScoped to register my repository so the lifetime is forever. I tried using AddSingleton however, because I'm using DbContext this has not been possible. I have used AddTransient but that made no difference. - Daya Bhogal
Have you considered discarding the edits when the edit page is closed if the save button isn't clicked? Wondering if that will help. It does sound like you are editing an instance which is displayed on the previous page. - Charleh

1 Answers

1
votes

Cause

DbContext cached the changes made to the entity

Solution

Through helpful comments, I looked into DbContext caching in EF Core and found a useful post https://codethug.com/2016/02/19/Entity-Framework-Cache-Busting/.

Through this I found out a way to reload an entity or a collection of entities generically:

One Entity

    public async Task ReloadEntity<TEntity>(TEntity entity)
    {
        if (entity != null) await context.Entry(entity).ReloadAsync();

        return;
    }

Multiple Entities

Note - According to the post linked above, this is ideal for a handful of entities. Performance problems may occur if large lists are passed in

    public async Task ReloadEntities<TEntity>(List<TEntity> entities)
    {
        if (entities.Count() > 0)
        {
            foreach (var entity in entities) if (entity != null) await context.Entry(entity).ReloadAsync();
        }

        return;
    }