将JavaScript变量传入C#用于SQL查询并返回结果至JS的问题
问题根源:ASP.NET页面生命周期的执行顺序坑到你了!
你遇到的问题本质是服务器端代码和客户端代码的执行时机不匹配:
- 当页面第一次加载时,服务器就已经把
<%=this.ucount%>解析成了初始值(也就是999999999,因为此时invoicenumberhidden还没被JS赋值),这个值直接硬编码到了生成的JavaScript里。 - 等你点击按钮运行
refreshHtml()时,JS确实把选中的行ID塞进了文本框,但此时jsucount已经是页面加载时就固定好的旧值,根本不会重新去调用服务器端的ucount属性。
另外提一句:你原来的SQL拼接写法有严重的SQL注入风险,后面的解决方案里我会帮你改成参数化查询,一定要重视这个问题!
最优解决方案:用AJAX异步调用后台方法
这种方式不需要页面刷新,直接把选中的ID传给服务器获取统计结果,是最流畅的用户体验。
第一步:把统计逻辑改成可被AJAX调用的后台方法
在你的后台代码里添加一个[WebMethod]标记的静态方法(必须是静态的才能被AJAX调用):
using System.Web.Services; public partial class YourPageName : System.Web.UI.Page { [WebMethod] public static int GetUniqueCount(int invoiceNumber) { // 用参数化查询替代字符串拼接,彻底避免SQL注入 string commandText = @"SELECT COUNT(*) AS distinct_count FROM (SELECT DISTINCT [inv_section],[invoice_number], [cust_po] FROM [Indigo].[dbo].[invoice_items] WHERE invoice_number=@InvoiceNumber) AS I;"; string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["Indigo2.Properties.Settings.Constr"].ConnectionString; using (SqlConnection conn = new SqlConnection(connectionString)) using (SqlCommand cmd = new SqlCommand(commandText, conn)) { cmd.Parameters.AddWithValue("@InvoiceNumber", invoiceNumber); conn.Open(); // ExecuteScalar直接返回统计结果,不需要先ExecuteNonQuery(那是执行增删改的) int uniqueCount = (int)cmd.ExecuteScalar(); conn.Close(); return uniqueCount; } } // 原来的ucount属性如果没有其他地方用到,可以删掉了 }
注意:你原来代码里的
cmd.ExecuteNonQuery()是多余的,ExecuteScalar就可以直接获取COUNT的结果,不需要这一步。
第二步:修改JavaScript代码,用AJAX调用这个方法
function refreshHtml() { // 获取JQGrid选中的行ID var grid = jQuery("#<%= JQGrid1.ClientID %>"); var rowKey = grid.getGridParam("selrow"); // 先判断有没有选中行 if (!rowKey) { alert("请先选择一行数据!"); return; } // 发起AJAX请求 $.ajax({ type: "POST", // 这里要替换成你的页面文件名,比如你的页面叫Invoice.aspx,就写~/Invoice.aspx/GetUniqueCount url: "<%= Page.ResolveUrl("~/YourPageName.aspx/GetUniqueCount") %>", // 把参数转成JSON格式,注意参数名要和后台方法的参数名完全一致 data: JSON.stringify({ invoiceNumber: parseInt(rowKey) }), contentType: "application/json; charset=utf-8", dataType: "json", success: function(response) { // ASP.NET的WebMethod会把返回值包装在d属性里 var jsucount = response.d; alert(jsucount); // 这里可以继续写你需要的HTML刷新逻辑 }, error: function(xhr, status, error) { alert("获取统计数据失败:" + error); } }); }
为什么原来的方式行不通?再理一遍执行顺序
- 用户请求页面 → 服务器跑完所有后台代码(包括
ucount属性)→ 生成带有硬编码值的HTML/JS → 发送给客户端。 - 客户端加载页面后,JS可以操作DOM(比如给文本框赋值),但这时候服务器已经完成了本次请求的处理,除非发起新的请求(AJAX或者页面回传),否则服务器不会重新执行任何代码。
备选方案:通过页面回传获取值(不推荐,体验差)
如果你实在不想用AJAX,也可以这么做:
- 让JS先设置隐藏字段的值,然后让按钮触发页面回传。
- 在服务器端的
btnDownloadButton_Click事件里计算统计值,把结果存到ViewState或者Session里。 - 页面回传后,在客户端用
<%= ViewState["UniqueCount"] %>获取结果。
不过这种方式会导致整个页面刷新,用户体验远不如AJAX,所以优先推荐第一种方案。
内容的提问来源于stack exchange,提问作者user3580480
相关产品推荐
相关产品推荐

