Grid excel export throwing internal null reference exception when exporting all pages
Hello,
I have a blazor grid in web assembly using version 23.2.7 and it's throwing the following internal null reference exception:
blazor.web.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: Object reference not set to an instance of an object.
System.NullReferenceException: Object reference not set to an instance of an object.
at Syncfusion.Blazor.Grids.Internal.GridExcelExport`1.<ExecuteResult>d__157[[PantryManager.Shared.ViewModels.Clients.ClientListDTO, PantryManager.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
at Syncfusion.Blazor.Grids.Internal.GridExcelExport`1.<ExportHelper>d__154[[PantryManager.Shared.ViewModels.Clients.ClientListDTO, PantryManager.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
at Syncfusion.Blazor.Grids.Internal.GridExcelExport`1.<ExcelExport>d__155[[PantryManager.Shared.ViewModels.Clients.ClientListDTO, PantryManager.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
at Syncfusion.Blazor.Grids.SfGrid`1.<ExportToExcelAsync>d__62[[PantryManager.Shared.ViewModels.Clients.ClientListDTO, PantryManager.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
at PantryManager.Client.Pages.StaffApp.Client.ClientList.ExportToExcelHandler() in PantryManager\PantryManager\Client\Pages\StaffApp\Client\ClientList.razor:line 240
Here is the code that runs when an export button is clicked:
public async Task ExportToExcelHandler()
{
await ClientListDataGridRef.ExportToExcelAsync(new ExcelExportProperties() { ExportType = ExportType.AllPages });
}
If I change the ExportType to CurrentPage, then the export works as expected and is downloaded. Here is my Grid definition:
<SfGrid ID="@(PantryManagerGrid.ClientListGrid.ToString())" @key="gridKey" @ref="ClientListDataGridRef" TValue="ClientListDTO" AllowExcelExport="true" Height="100%" ContextMenuItems="@ContextMenuItems" AllowSelection="true" AllowPaging="true" AllowSorting="true" AllowFiltering="true" AllowReordering="true" AllowResizing="true" ShowColumnChooser="true">
<GridTemplates>
<ToolbarTemplate>
<SfToolbar>
<ToolbarEvents Clicked="ToolbarClickHandler"></ToolbarEvents>
<ToolbarItems>
<ToolbarItem @ref="ClientListNewButton" Type="@ItemType.Button" Text="New" PrefixIcon="fa-solid fa-plus" Id="ClientClistNewButton" TooltipText="New Client"></ToolbarItem>
<ToolbarItem Disabled="@(SelectedClient == null)" @ref="ClientListEditButton" Type="@ItemType.Button" Text="@(canEdit ? "Edit" : "View")" PrefixIcon="@(canEdit ? Constants.EditIcon : Constants.ViewIcon)" Id="ClientListEditButton" TooltipText="Edit Client"></ToolbarItem>
<ToolbarItem Visible="canDelete" Disabled="@(SelectedClient == null)" @ref="ClientListDeleteButton" Type="@ItemType.Button" Text="Delete" PrefixIcon="@(Constants.DeleteIcon)" Id="ClientListDeleteButton" TooltipText="Delete Client"></ToolbarItem>
<ToolbarItem Disabled="@(ClientListDataGridRef.FilterSettings.Columns.IsEmpty())" Type="@ItemType.Button" Text="Clear Filters" PrefixIcon="@(Constants.ClearFilterIcon)" Id="ClientListClearFilterButton" TooltipText="Clear Grid Filters"></ToolbarItem>
<ToolbarItem>
<SfButton OnClick="ExportToExcelHandler">Export to Excel</SfButton>
</ToolbarItem>
<ToolbarItem>
<GridMenu DataGrid="ClientListDataGridRef" OnGridResetToSystemDefault="@((grid) => {gridKey++; StateHasChanged();})" GridName="@(PantryManagerGrid.ClientListGrid)" TItem="ClientListDTO"></GridMenu>
</ToolbarItem>
</ToolbarItems>
</SfToolbar>
</ToolbarTemplate>
</GridTemplates>
<GridSelectionSettings Type="Syncfusion.Blazor.Grids.SelectionType.Single" Mode="Syncfusion.Blazor.Grids.SelectionMode.Row"></GridSelectionSettings>
<GridEvents OnRecordDoubleClick="RecordDoubleClickHandler" OnActionComplete="GridActionCompletedHandler" ResizeStopped="ColumnResizeStoppedHandler" ContextMenuOpen="OnContextMenuOpen" ContextMenuItemClicked="OnContextMenuClick" RowSelected="RowSelectedhandler" OnToolbarClick="ToolbarClickHandler" TValue="ClientListDTO"></GridEvents>
<SfDataManager @ref="ClientListDataManagerRef" Adaptor="Adaptors.CustomAdaptor" AdaptorInstance="@typeof(ClientListAdaptor)"></SfDataManager>
<GridFilterSettings Type="Syncfusion.Blazor.Grids.FilterType.Menu"></GridFilterSettings>
<GridPageSettings PageSize="50" PageSizes="@PagerDropdown" PageCount="3"></GridPageSettings>
<GridSortSettings>
<GridSortColumns>
<GridSortColumn Field="LastName" Direction="Syncfusion.Blazor.Grids.SortDirection.Ascending"></GridSortColumn>
</GridSortColumns>
</GridSortSettings>
<GridColumns>
<GridColumn Field="@nameof(ClientListDTO.ClientID)" IsPrimaryKey="true" Visible="false" ShowInColumnChooser="false"></GridColumn>
<GridColumn Field=@nameof(ClientListDTO.ClientNo) HeaderText="Client #" Width="80">
<FilterTemplate>
<StringColumnFilter GridRef="@ClientListDataGridRef" ColumnFieldName="ClientNo" GridTValue="ClientListDTO"></StringColumnFilter>
</FilterTemplate>
</GridColumn>
<GridColumn Field=@nameof(ClientListDTO.LastName) HeaderText="Last Name" Width="100">
<FilterTemplate>
<StringColumnFilter GridRef="@ClientListDataGridRef" ColumnFieldName="LastName" GridTValue="ClientListDTO"></StringColumnFilter>
</FilterTemplate>
</GridColumn>
<GridColumn Field=@nameof(ClientListDTO.FirstName) HeaderText="First Name" Width="100">
<FilterTemplate>
<StringColumnFilter GridRef="@ClientListDataGridRef" ColumnFieldName="FirstName" GridTValue="ClientListDTO"></StringColumnFilter>
</FilterTemplate>
</GridColumn>
<GridColumn Field=@nameof(ClientListDTO.DateOfBirth) HeaderText="Date of Birth" Format="d" Width="100">
<FilterTemplate>
<DateColumnFilter GridRef="@ClientListDataGridRef" ColumnFieldName="DateOfBirth" GridTValue="ClientListDTO"></DateColumnFilter>
</FilterTemplate>
</GridColumn>
<GridColumn Field=@nameof(ClientListDTO.StreetAddress1) HeaderText="Address 1" Width="150">
<FilterTemplate>
<StringColumnFilter GridRef="@ClientListDataGridRef" ColumnFieldName="StreetAddress1" GridTValue="ClientListDTO"></StringColumnFilter>
</FilterTemplate>
</GridColumn>
<GridColumn Field=@nameof(ClientListDTO.City) HeaderText="City" Width="100">
<FilterTemplate>
<StringColumnFilter GridRef="@ClientListDataGridRef" ColumnFieldName="City" GridTValue="ClientListDTO"></StringColumnFilter>
</FilterTemplate>
</GridColumn>
<GridColumn Field=@nameof(ClientListDTO.PrimaryPhone) HeaderText="Phone" Width="80">
<FilterTemplate>
<PhoneColumnFilter GridRef="@ClientListDataGridRef" ColumnFieldName="PrimaryPhone" GridTValue="ClientListDTO"></PhoneColumnFilter>
</FilterTemplate>
<Template>
@{
var phone = (context as ClientListDTO)?.PrimaryPhone;
@(phone?.ToPhoneNumberFormat())
}
</Template>
</GridColumn>
<GridColumn Field=@nameof(ClientListDTO.PrimaryEmail) Visible="false" HeaderText="Email" Width="100">
<FilterTemplate>
<StringColumnFilter GridRef="@ClientListDataGridRef" ColumnFieldName="Primary Email" GridTValue="ClientListDTO"></StringColumnFilter>
</FilterTemplate>
</GridColumn>
<GridColumn Field=@nameof(ClientListDTO.Notes) HeaderText="Notes" Width="100">
<FilterTemplate>
<StringColumnFilter GridRef="@ClientListDataGridRef" ColumnFieldName="Notes" GridTValue="ClientListDTO"></StringColumnFilter>
</FilterTemplate>
<Template>
@{
var note = (context as ClientListDTO)?.Notes;
<span class="col-ellipsis-text" title="@note">@note</span>
}
</Template>
</GridColumn>
<GridColumn Field=@nameof(ClientListDTO.DriversLicenseNo) Visible="false" HeaderText="License No" Width="70">
<FilterTemplate>
<StringColumnFilter GridRef="@ClientListDataGridRef" ColumnFieldName="DriversLicenseNo" GridTValue="ClientListDTO"></StringColumnFilter>
</FilterTemplate>
</GridColumn>
<GridColumn Field=@nameof(ClientListDTO.ZipCode) Visible="false" HeaderText="Zip Code" Width="70">
<FilterTemplate>
<StringColumnFilter GridRef="@ClientListDataGridRef" ColumnFieldName="ZipCode" GridTValue="ClientListDTO"></StringColumnFilter>
</FilterTemplate>
</GridColumn>
<GridColumn Field=@nameof(ClientListDTO.County) Visible="false" HeaderText="County" Width="100">
<FilterTemplate>
<StringColumnFilter GridRef="@ClientListDataGridRef" ColumnFieldName="County" GridTValue="ClientListDTO"></StringColumnFilter>
</FilterTemplate>
</GridColumn>
<GridColumn Field=@nameof(ClientListDTO.ResidenceType) Visible="false" HeaderText="Residence Type" Width="100">
<FilterTemplate>
<StringColumnFilter GridRef="@ClientListDataGridRef" ColumnFieldName="ResidenceType" GridTValue="ClientListDTO"></StringColumnFilter>
</FilterTemplate>
</GridColumn>
<GridColumn Field=@nameof(ClientListDTO.VerificationDate) HeaderText="Verification Date" Format="d" Width="100">
<FilterTemplate>
<DateColumnFilter GridRef="@ClientListDataGridRef" ColumnFieldName="VerificationDate" GridTValue="ClientListDTO"></DateColumnFilter>
</FilterTemplate>
</GridColumn>
<GridColumn Field=@nameof(ClientListDTO.LastVisitDateTime) HeaderText="Last Visit" Width="100">
<FilterTemplate>
<DateColumnFilter GridRef="@ClientListDataGridRef" ColumnFieldName="LastVisitDateTime" GridTValue="ClientListDTO"></DateColumnFilter>
</FilterTemplate>
</GridColumn>
<GridColumn Field=@nameof(ClientListDTO.TotalVisits) HeaderText="Total Visits" Width="70">
<FilterTemplate>
<DateColumnFilter GridRef="@ClientListDataGridRef" ColumnFieldName="TotalVisits" GridTValue="ClientListDTO"></DateColumnFilter>
</FilterTemplate>
</GridColumn>
</GridColumns>
</SfGrid>
The grid is using a custom data adaptor. Here is the ReadAsync() method:
public async override Task<object> ReadAsync(DataManagerRequest dataManagerRequest, string key = null)
{
if (_userSettingsService.GetSuppressGridRead(PantryManagerGrid.ClientListGrid))
{
return new DataResult() { Result = new List<ClientListDTO>(), Count = 0 }; // Return empty when suppressed
}
DataGridRequest customRequest = new DataGridRequest();
customRequest.Skip = dataManagerRequest.Skip;
customRequest.Take = dataManagerRequest.Take;
if (dataManagerRequest.Sorted.IsNotEmpty())
{
//syncfusion has the sorts in reverse for some reason in its internal collection, reverse it first
IEnumerable<Sort> reversedSorts = dataManagerRequest.Sorted.AsEnumerable().Reverse();
customRequest.SortDescriptors = reversedSorts.Select(s => new DataGridSortDescriptor() { Name = s.Name, Direction = s.Direction == "ascending" ? SortDirection.ASC : SortDirection.DESC }).ToList();
}
if (dataManagerRequest.Where != null && dataManagerRequest.Where.Any() && dataManagerRequest.Where[0].predicates.Any())
{
customRequest.FilterDescriptors = dataManagerRequest.Where[0].predicates.Select(w => ConvertToFilterDescriptor(w)).ToList();
}
ClientListDataResult result = await _clientService.GetClientList(customRequest);
//convert to local time
foreach (var client in result.ClientList)
{
if (client.LastVisitDateTime.HasValue)
{
client.LastVisitDateTime = (await _timeZoneService.ConvertUtcToLocal(client.LastVisitDateTime)).Value;
}
}
DataResult dataResult = new DataResult()
{
Result = result.ClientList,
Count = result.Count
};
return dataResult;
}
When I export all pages, the Skip and Take on the DataManagerRequest object are both 0. I set the take to Int32.MaxValue on the server and I have verified that the JSON data being returned to the client from the server is the exact same when exporting all pages vs current page only. There are 26 records in the database, and the grid page size is 50, so I would expect both export spreadsheets to show the same 26 records.
Since this is an internal exception, and the only difference that I can perceive between the working and not working scenarios is changing the enum from AllPages to CurrentPage, I'm not sure what else I can do here. Any insight into what is going on here would be much appreciated.
Thank you!
Hi Enoch,
Greetings from Syncfusion.
We have prepared a simple sample as per your shared code snippet but we could not able to replicate the reported issue at our end. Kindly check the attached sample for your reference.
If you still face difficulties then Kindly share the below requested details from your end.
- Share us the entire Grid code snippet along with class.
- Share us the video demonstration of the reported issue.
- If possible share us a simple issue reproduceable sample or try to reproduce the reported issue on the above attached sample.
The above requested details will be very helpful in achieving you requirement.
Regards,
Monisha
Attachment: BlazorApp1_15b1fd1d.zip
Hi Monisha,
I have attached a minimal reproduction of the issue. You'll need to give the grid a second to load its data after the invalid license key message pops up. Then click the Export button at the top to produce the exception.
Thank you for your help with this!
Attachment: SyncfusionIssueSample_4706aadb.zip
Hi Enoch,
We have confirmed this as an issue and logged the defect report “Null Reference Exception throws on Exporting Excel with All pages” for the same and this fix will be included in our upcoming patch release which is expected to be rolled out on or before 3rd January, 2024.
You can now track the current status of your request, review the proposed resolution timeline, and contact us for any further inquiries through this link.
Disclaimer: “Inclusion of this solution in the weekly release may change due to other factors including but not limited to QA checks and works reprioritization”
Regards,
Monisha
Hi Enoch,
Sorry for the confusion.
We would like to inform that while exporting all pages in DataGrid we suggest you to pass the datasource alone instead of passing both the datasource and count.
To resolve the reported issue kindly try the below highlighted suggestion from your end.
|
public async override Task<object> ReadAsync(DataManagerRequest dataManagerRequest, string key = null) {
List<ClientListDTO> clients = new List<ClientListDTO>();
clients.Add(new ClientListDTO() { ClientID = 1, FirstName = "Bob1", LastName = "Smith1" });
clients.Add(new ClientListDTO() { ClientID = 2, FirstName = "Bob2", LastName = "Smith2" });
clients.Add(new ClientListDTO() { ClientID = 3, FirstName = "Bob3", LastName = "Smith3" });
return dataManagerRequest.RequiresCounts ? new DataResult() {
Result = clients,
Count = clients.Count
} : (object)clients;
} |
Please let us know if you face any difficulties or if you have further queries.
Regards,
Monisha
Hi Monisha,
That worked! Thank you for the solution.
Hi Enoch,
Welcome. We are glad to hear that the reported issue has been resolved at your end. Kindly get back to us if you have further queries. As always we will be happy to assist you.
Regards,
Monisha
Has this been fixed, please? I have the same problem in 24.2.9
Returning different types based on a request parameter is a nasty practice in C# and this bug is a sideeffect of doing so.
Hi liero,
Before proceeding with the reporting of the problem, we require some additional
clarification from your end. Please share the following details to proceed
further on our end:
- To analyze the reported issue, could you please share a simple and reproducible sample with duplicate data that demonstrates the problem? This will assist us in identifying the issue more efficiently and providing a resolution.
- Could you please share the video demonstration of the issue with replication steps?
- Could you please share when you performed the operation and the time you faced the error?
The details requested above will be very helpful in validating the reported query on our end and providing a solution as soon as possible. Thanks for your understanding.
Regards,
Prathap S
- 8 Replies
- 4 Participants
-
EN Enoch
- Dec 11, 2023 10:09 PM UTC
- Mar 20, 2024 10:45 AM UTC