jQuery客户端填充GridView回发数据丢失,求数据持久化最优方案
我之前也碰到过一模一样的场景——客户端用jQuery动态填充的GridView数据,一到回发就全丢了,折腾了好一阵才找到几个靠谱的解决方案,给你梳理下:
方案一:用隐藏域存序列化JSON(最推荐,简单易维护)
这是我现在最常用的方法,核心思路是把客户端GridView里的所有数据打包成JSON字符串,塞进一个服务器端隐藏域,回发时服务器直接读取这个隐藏域的值再解析就行。
步骤拆解:
- 先在ASPX页面加个服务器端隐藏域:
<asp:HiddenField ID="hdnGridData" runat="server" />
- 写个jQuery方法,把GridView数据转成JSON:
function saveGridDataToHiddenField() { var gridRows = []; // 跳过表头,遍历数据行 $('.grid-view tr:not(:first)').each(function() { var rowData = {}; // 假设每个td都加了data-field属性标记字段名,比如data-field="PaymentMonth" $(this).find('td').each(function() { var fieldName = $(this).data('field'); rowData[fieldName] = $(this).text().trim(); }); gridRows.push(rowData); }); // 把JSON字符串存到隐藏域,怕特殊字符的话可以加encodeURIComponent $('#<%= hdnGridData.ClientID %>').val(encodeURIComponent(JSON.stringify(gridRows))); }
- 回发前调用这个方法,比如绑定到提交按钮的点击事件:
$('#<%= btnSubmit.ClientID %>').click(function() { saveGridDataToHiddenField(); });
- 服务器端解析数据:
protected void btnSubmit_Click(object sender, EventArgs e) { var encodedJson = hdnGridData.Value; if (!string.IsNullOrEmpty(encodedJson)) { var jsonData = HttpUtility.UrlDecode(encodedJson); // 用Newtonsoft.Json或者System.Text.Json转成实体列表 var paymentPlans = JsonConvert.DeserializeObject<List<MonthlyPayment>>(jsonData); // 后续业务逻辑处理 } }
这个方法对现有代码改动最小,数据量不大的话完全够用,维护起来也省心。
方案二:填充服务器端控件(适合服务器端GridView的动态修改)
如果你用的是服务器端GridView控件,只是客户端动态添加行或修改单元格内容,那直接把数据塞进GridView里的服务器端控件(比如TextBox)就行——ASP.NET会自动跟踪这些控件的状态,回发时能直接获取值。
比如你的GridView列用TemplateField:
<asp:GridView ID="gvPaymentPlan" runat="server"> <Columns> <asp:TemplateField HeaderText="付款月份"> <ItemTemplate> <asp:TextBox ID="txtMonth" runat="server" CssClass="month-input"></asp:TextBox> </ItemTemplate> </asp:TemplateField> <asp:TemplateField HeaderText="付款金额"> <ItemTemplate> <asp:TextBox ID="txtAmount" runat="server" CssClass="amount-input"></asp:TextBox> </ItemTemplate> </asp:TemplateField> </Columns> </asp:GridView>
客户端计算后填充数据:
// 用你代码里的totalmonths和totalamount计算 for(var i=0; i<totalmonths; i++){ var currentMonth = moment(today).add(i, 'month').format('YYYY-MM'); var monthlyAmount = ((amountdue / totalmonths) + ((amountdue / totalmonths) * processingfee)).toFixed(2); // 克隆模板行(可以提前放一个隐藏的模板行) var newRow = $('#gvPaymentPlan tr.template-row').clone().removeClass('template-row'); newRow.find('.month-input').val(currentMonth); newRow.find('.amount-input').val(monthlyAmount); $('#gvPaymentPlan').append(newRow); }
回发时服务器直接遍历GridView行拿值:
protected void btnSubmit_Click(object sender, EventArgs e) { foreach(GridViewRow row in gvPaymentPlan.Rows) { var month = ((TextBox)row.FindControl("txtMonth")).Text; var amount = ((TextBox)row.FindControl("txtAmount")).Text; // 处理数据 } }
这种方法完全利用ASP.NET的状态机制,不需要额外做数据序列化,适合原本就是服务器端GridView的场景。
方案三:动态生成服务器端控件(不推荐,太繁琐)
如果是完全客户端生成的表格,也可以在回发前给每个单元格对应创建一个服务器端隐藏域,把值塞进去。但这种方法会生成大量零散的控件,服务器端取值要一个个找,维护起来特别麻烦,除非特殊情况不建议用。
注意事项
- 如果数据量特别大,隐藏域可能会有长度限制,这时候可以考虑用AJAX提前把数据提交到服务器存到Session或临时表,回发时直接从服务器读取。
- 序列化JSON时记得处理特殊字符,避免解析失败,用
encodeURIComponent和HttpUtility.UrlDecode配对使用更稳妥。
内容的提问来源于stack exchange,提问作者Prescott Chartier
相关产品推荐
相关产品推荐

