ASP.NET WebForm绑定API数据到GridView时遇IEnumerable类型错误
ASP.NET WebForm GridView绑定Web API数据报错排查与解决
Error: Target type System.Collections.IEnumerable is not a value type or a non-abstract class. Parameter name: targetType.
一、GridView控件代码
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" AllowPaging="False" AllowSorting="True" OnSelectedIndexChanged="GridView1_SelectedIndexChanged" CssClass="table table-striped table-bordered"> <HeaderStyle CssClass="header-style" /> <Columns> <asp:BoundField DataField="id" HeaderText="ID" SortExpression="id" ControlStyle-CssClass="text-center" /> <asp:BoundField DataField="Type" HeaderText="类型" SortExpression="Type" ControlStyle-CssClass="text-center" /> <asp:BoundField DataField="PlantLineProcess" HeaderText="产线流程" SortExpression="PlantLineProcess" ControlStyle-CssClass="text-center" /> <asp:BoundField DataField="DefectLocation" HeaderText="缺陷位置" SortExpression="DefectLocation" ControlStyle-CssClass="text-center" /> <asp:BoundField DataField="Defect" HeaderText="缺陷类型" SortExpression="Defect" ControlStyle-CssClass="text-center" /> <asp:BoundField DataField="Description" HeaderText="描述" SortExpression="Description" ControlStyle-CssClass="text-center" /> <asp:BoundField DataField="NMR_Number" HeaderText="NMR编号" SortExpression="NMR_Number" ControlStyle-CssClass="text-center" /> <asp:BoundField DataField="Quantity" HeaderText="数量" SortExpression="Quantity" ControlStyle-CssClass="text-center" /> <asp:BoundField DataField="Status" HeaderText="状态" SortExpression="Status" ControlStyle-CssClass="text-center" /> <asp:BoundField DataField="Date" HeaderText="日期" SortExpression="Date" ControlStyle-CssClass="text-center" /> </Columns> </asp:GridView>
二、Page_Load中的C#代码
if (!Page.IsPostBack) { try { string apiUrl = "https://itapps/nmrapi/api/nmr"; HttpClient httpClient = new HttpClient(); HttpResponseMessage response = await httpClient.GetAsync(apiUrl); string jsonData = await response.Content.ReadAsStringAsync(); // 判断JSON是数组还是单个对象 dynamic responseData = JsonConvert.DeserializeObject(jsonData); dynamic data; if (responseData is JArray) { data = responseData; } else { data = responseData.data; } // 准备绑定用的DataTable DataTable table = new DataTable(); table.Columns.Add("id", typeof(int)); table.Columns.Add("Type", typeof(string)); table.Columns.Add("PlantLineProcess", typeof(string)); table.Columns.Add("DefectLocation", typeof(string)); table.Columns.Add("Defect", typeof(string)); table.Columns.Add("Description", typeof(string)); table.Columns.Add("NMR_Number", typeof(string)); table.Columns.Add("Quantity", typeof(int)); table.Columns.Add("Status", typeof(string)); table.Columns.Add("Date", typeof(string)); foreach (var item in data) { table.Rows.Add(item.id, item.Type, item.PlantLineProcess, item.DefectLocation, item.Defect, item.Description, item.NMR_Number, item.Quantity, item.Status, item.Date); } GridView1.DataSource = data; GridView1.DataBind(); } catch (Exception ex) { lblMessage.Text = "Error: " + ex.Message; } }
三、API返回的JSON结构
{ "success":true, "message":null, "data":"[{\"id\":1,\"Type\":\"Neeraj\",\"SerialNo\":\"DFR45566678\",\"PlantLineProcess\":\"new jackpot\",\"Date\":\"0001-01-01T00:00:00\",\"DefectLocation\":\"First Corner\",\"Defect\":\"AOL\",\"Description\":\"my description\",\"NMR_Number\":\"7383\",\"Quantity\":10,\"Status\":0},{\"id\":2,\"Type\":\"Jack\",\"SerialNo\":\"BL11099035474\",\"PlantLineProcess\":\"new jackpot\",\"Date\":\"0001-01-01T00:00:00\",\"DefectLocation\":\"First Corner\",\"Defect\":\"AOL\",\"Description\":\"my description\",\"NMR_Number\":\"7383\",\"Quantity\":1,\"Status\":0},{\"id\":3,\"Type\":\"Jack\",\"SerialNo\":\"BL11099035474\",\"PlantLineProcess\":\"new jackpot\",\"Date\":\"0001-01-01T00:00:00\",\"DefectLocation\":\"First Corner\",\"Defect\":\"AOL\",\"Description\":\"my description\",\"NMR_Number\":\"7383\",\"Quantity\":1,\"Status\":0}]" }
四、错误原因分析
- API返回的
data字段是字符串类型:从JSON结构可见,data的值是被引号包裹的JSON数组字符串,而非直接的数组对象。代码直接将该字符串当作可枚举对象遍历、绑定,而字符串不属于IEnumerable类型,触发类型不匹配错误。 - 代码逻辑冗余矛盾:代码创建了DataTable并填充数据,但最终绑定的是未处理的
data变量,DataTable未被实际使用。 - dynamic类型隐藏问题:dynamic编译时不做类型校验,无法提前发现
data是字符串而非数组的问题。
五、解决方案
步骤1:定义强类型实体类
用强类型替代dynamic,避免类型模糊问题:
public class NMRData { public int id { get; set; } public string Type { get; set; } public string PlantLineProcess { get; set; } public string DefectLocation { get; set; } public string Defect { get; set; } public string Description { get; set; } public string NMR_Number { get; set; } public int Quantity { get; set; } public int Status { get; set; } public string Date { get; set; } public string SerialNo { get; set; } } public class APIResponse { public bool success { get; set; } public string message { get; set; } public string data { get; set; } }
步骤2:修正Page_Load数据解析与绑定逻辑
if (!Page.IsPostBack) { try { string apiUrl = "https://itapps/nmrapi/api/nmr"; using (HttpClient httpClient = new HttpClient()) { HttpResponseMessage response = await httpClient.GetAsync(apiUrl); response.EnsureSuccessStatusCode(); // 校验请求是否成功 string jsonData = await response.Content.ReadAsStringAsync(); // 先反序列化为API响应对象 APIResponse apiResponse = JsonConvert.DeserializeObject<APIResponse>(jsonData); // 将data字段的字符串反序列化为实体数组 List<NMRData> nmrList = JsonConvert.DeserializeObject<List<NMRData>>(apiResponse.data); // 直接绑定实体集合到GridView GridView1.DataSource = nmrList; GridView1.DataBind(); } } catch (Exception ex) { lblMessage.Text = "错误: " + ex.Message; } }
关键说明
- 正确解析嵌套JSON字符串:先将整个API响应反序列化为
APIResponse对象,再把data字段的字符串内容反序列化为可枚举的实体集合,满足GridView的数据源要求。 - 用using管理HttpClient:避免资源泄漏问题。
- 强类型替代dynamic:编译阶段即可发现类型错误,减少运行时异常。
- 直接绑定实体集合:GridView支持直接绑定
IEnumerable<T>类型,无需手动创建DataTable(若需DataTable可额外转换)。
内容的提问来源于stack exchange,提问作者Guru
相关产品推荐
相关产品推荐

