MudBlazor:GridState FilterDefinitions序列化失败无法发送至API
问题分析
错误核心原因很明确:MudBlazor的FilterDefinition<T>和GridState<T>包含组件内部引用(比如你给FilterDefinition.Column赋值的是MudDataGrid的列实例),这些对象里带有System.Action类型的事件委托,而默认JSON序列化器不支持序列化委托类型,导致调用PostAsJsonAsync直接传gridState时,序列化阶段就失败,API请求根本发不出去。
正确实现方式
别直接传递MudBlazor原生的GridState,自己定义一个用于API交互的DTO(数据传输对象),只保留后端需要的过滤、分页、排序参数,再从GridState和自定义过滤器里提取数据映射到DTO中。
步骤1:定义API专用的DTO类
// 单个过滤条件的DTO public class FilterDto { public string Field { get; set; } // 对应实体的属性名,比如"Name" public string Operator { get; set; } // 过滤操作符,比如"contains" public object Value { get; set; } // 过滤值 } // 网格请求状态DTO,用于传递给API public class GridStateRequestDto { public int Page { get; set; } public int PageSize { get; set; } public List<FilterDto> Filters { get; set; } = new(); // 可选:如果需要排序,添加以下属性 public string SortField { get; set; } public bool SortDescending { get; set; } }
步骤2:修改代码,映射数据到DTO
替换原来直接序列化gridState的逻辑,改为构建干净的DTO对象:
// 构建自定义过滤条件的DTO var filterDto = new FilterDto { Field = "Name", // 对应Person实体的属性名 Operator = "contains", Value = "bob" }; // 从gridState提取分页信息,加上自定义过滤器 var requestDto = new GridStateRequestDto { Page = gridState.Page, PageSize = gridState.PageSize, Filters = new List<FilterDto> { filterDto } // 如果需要排序,从gridState.SortDefinitions里提取对应字段和排序方向 }; // 发送API请求,序列化DTO(无组件引用,可正常完成序列化) await httpClient.PostAsJsonAsync("/api/v1/people", requestDto);
补充说明
- 为什么不能直接用
FilterDefinition<T>?因为它的Column属性是MudBlazor的IColumn<T>实例,这个对象持有对MudDataGrid组件的引用,里面包含大量无法序列化的UI相关成员(比如事件委托、渲染状态)。 - 如果要复用MudDataGrid自带UI生成的过滤条件,同样需要从
gridState.FilterDefinitions里提取属性名、操作符、值,映射到FilterDto中,而非直接传递FilterDefinition对象。
替代方案:复用ServerData内置参数(适用UI触发的过滤场景)
如果你的过滤是通过MudDataGrid的UI过滤器触发的,其实可以直接在ServerData委托里接收GridState<T>参数,MudBlazor会自动处理UI触发的过滤/分页/排序,你只需要在委托里把GridState转成DTO再调用API:
private async Task<GridData<Person>> ServerDataApiCaller(GridState<Person> state) { var requestDto = new GridStateRequestDto { Page = state.Page, PageSize = state.PageSize, Filters = state.FilterDefinitions.Select(fd => new FilterDto { Field = ((PropertyColumn<Person>)fd.Column).Property.Name, // 从PropertyColumn获取实体属性名 Operator = fd.Operator, Value = fd.Value }).ToList() }; var response = await httpClient.PostAsJsonAsync("/api/v1/people", requestDto); var result = await response.Content.ReadFromJsonAsync<GridData<Person>>(); return result ?? new GridData<Person>(); }
内容的提问来源于stack exchange,提问作者AlbertSY
相关产品推荐
相关产品推荐

