I am developing a Server-Side Blazor app in which a user inputs excel files with data. The app goes over each excel file, checks if it is valid and creates output files (based on excel file content) for user to download.
There is a table that displays IEnumerable<IExcelFile>, a list of objects with following parameters: FileName, FileType, Package (not for display). I would like to call a method that iterates over each IExcelFile and take some actions for each excel (check if valid, process). When the method is running I would like FileType of each IExcelFile to indicate, on which step of the process a particular file is. e.g. When method starts all IExcelFiles have a "Queued" FileType, when one of IExcelFiles is processed it's FileType changes to "Processing", when an exception is thrown for one excel file it's FileType changes to "Error" and so on.
I am able to change those parameters just before and after running this method but not when the method is running. Below is the code:
Table:
<table class="table table-hover">
<thead>
<tr>
<th>FileName</th>
<th>FileType</th>
<th style="width: 10px;"></th>
</tr>
</thead>
<tbody>
@if (excelFiles != null && excelFiles.Count() > 0)
{
foreach (var excelFile in excelFiles)
{
<tr>
<td>@excelFile.FileName</td>
<td>@excelFile.FileType.ToString()</td>
<td>
@if (!IsLoading)
{
<button class="btn btn-close" @onclick="() => DeleteExcelFile(excelFile)"></button>
}
</td>
</tr>
}
}
else
{
<tr>
<td colspan="3">
No files provided
</td>
</tr>
}
</tbody>
</table>
Processing excel file starts when the user clicks a "Start" button:
@if (!IsLoading)
{
<div class="mb-3">
<label for="formFileMultiple" class="form-label">Select excel files from your drive</label>
@for (int i = 0; i < numberOfInputFiles; i++)
{
<InputFile @key="i" OnChange="UploadExcelFiles" multiple style="@GetInputFileStyle(i)" class="form-control" type="file" id="formFileMultiple"></InputFile>
}
</div>
@if (IsDownloadAvailable)
{
<button type="button" class="btn btn-success" @onclick="DownloadDubCards">Download</button>
<button type="button" class="btn btn-primary" @onclick="ClearExcelFileList">Clear</button>
}
else
{
<button type="button" class="btn btn-primary" @onclick="GenerateDubCards">Start</button>
<button type="button" class="btn btn-primary" @onclick="ClearExcelFileList">Clear</button>
}
}
else
{
<div class="spinner-border text-primary" role="status" style="left: 50%; position: absolute; width: 3rem; height: 3rem;">
<span class="visually-hidden">Loading...</span>
</div>
}
And the method that is processing the excel files:
private void GenerateDubCards()
{
foreach (var excelFile in excelFiles)
{
excelFile.FileType = IExcelFile.Type.Queued;
}
foreach (var excelFile in excelFiles)
{
try
{
excelFile.FileType = IExcelFile.Type.Processing;
List<IDubCardSet> tempDubCardSets = dubCardGenerator.CalculateDubCardSetsFromExcelFile(excelFile);
dubCardSets = dubCardGenerator.AddDubCardSets(tempDubCardSets);
foreach (var dubCardSet in dubCardSets.Where(dcs => dcs.DubCards.Count == 0))
{
dubCardGenerator.CreateDubCards(dubCardSet);
}
excelFile.FileType = IExcelFile.Type.Completed;
}
catch (Exception ex)
{
excelFile.FileType = IExcelFile.Type.Error;
AppLogger.GetInstance().Info(ex.Message);
Modal.Open("Something went wrong!", ex.Message);
}
}
IsDownloadAvailable = true;
}
So basically after this method runs I just see all excel files have a FileType "Complete", but when the method runs I see no other values in between (even when debugging step by step).
Additional context that I hope is irrelevant for this issue:
- This is a child component but no parameters are passed from the parent to child nor are any parameters from child shared with or dependent on parent.
- This components has other methods that use
StateHasChanged()like deleting or adding list elements that work properly.
I tried changing method from private void to async Task, call StateHasChanged() anywhere but with no success. I tried pretty much any related solutions on Stack Overflow, but it didn't work. Any help would be much appreciated, Thanks.
