You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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}]"
}

四、错误原因分析

  1. API返回的data字段是字符串类型:从JSON结构可见,data的值是被引号包裹的JSON数组字符串,而非直接的数组对象。代码直接将该字符串当作可枚举对象遍历、绑定,而字符串不属于IEnumerable类型,触发类型不匹配错误。
  2. 代码逻辑冗余矛盾:代码创建了DataTable并填充数据,但最终绑定的是未处理的data变量,DataTable未被实际使用。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 07:17:36