ASP.NET C#中asmx.cs文件DateTime转换报错:无法识别有效DateTime字符串
问题原因及解决方法
核心问题
<input type="date">原生返回的是ISO标准格式(yyyy-MM-dd),但后端用dd/MM/yyyy格式解析,格式完全不匹配。- 前端对日期值做了
JSON.stringify处理,导致传到后端的参数是带双引号的字符串(比如"2024-05-20"),进一步触发解析失败。 - 未处理日期控件为空的情况,空值传入后直接触发解析报错。
解决方案
1. 前端AJAX代码修改
去掉JSON.stringify,直接传递日期控件的原始value值,同时处理空值,还修复了DataTable重复初始化和HTML标签错误:
$("#btnSubmit").click(function (e) { var fromDate = document.getElementById("<%=dtp_from.ClientID%>").value || ""; var toDate = document.getElementById("<%=dtp_to.ClientID%>").value || ""; var dataToSend = { param1: fromDate, param2: toDate }; $.ajax({ type: "POST", url: "FillGridMethod.asmx/CashBookList", data: dataToSend, dataType: "json", success: function (data) { var datatableVariable = $('#gv_Datatable').DataTable({ dom: 'Bfrtip', destroy: true, // 避免重复初始化报错 data: data, columns: [ { 'data': 'Id', visible: false }, { 'data': 'cashbookdate', 'render': function (date) { var date = new Date(parseInt(date.substr(6))); var month = date.getMonth() + 1; return date.getDate() + "/" + month + "/" + date.getFullYear(); } }, { 'data': 'cashbookaccname' }, { 'data': 'cashbookdescription' }, { 'data': 'cashbookreceipt' }, { 'data': 'cashbookpayment' }, { 'data': 'Balance' }, { "render": function (data, type, row) { return "<a href='#' class='btn btn-success' onclick=DeleteCustomer('" + row.Id + "')>View</a>"; } }, { "render": function (data, row) { return "<a href='#' class='btn btn-danger'>Delete</a>"; } }] }); }, error: function(xhr, status, error) { console.log("请求错误:" + error); // 便于调试 } }); });
2. 后端WebMethod修改
- 改用
yyyy-MM-dd格式解析日期,匹配前端传入的标准格式。 - 增加空值判断和安全解析逻辑,避免空值或非法格式报错。
- 替换SQL拼接为参数化查询,彻底解决SQL注入风险:
[WebMethod(enableSession: true)] public void CashBookList(string param1, string param2) { DateTime? fromDate = null; DateTime? toDate = null; // 安全解析起始日期 if (!string.IsNullOrEmpty(param1)) { DateTime.TryParseExact(param1, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime parsedFrom); fromDate = parsedFrom; } // 安全解析结束日期 if (!string.IsNullOrEmpty(param2)) { DateTime.TryParseExact(param2, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime parsedTo); toDate = parsedTo; } var cashBook = new List<CashBookModel>(); string constr = cn.ConnectionString; using (SqlConnection con = new SqlConnection(constr)) { StringBuilder qryFillGrid = new StringBuilder(); qryFillGrid.Append("select cashbookid, cashbookdate, cashbookaccname, cashbookdescription, cashbookreceipt, cashbookpayment, Balance from tbl_cashbook "); qryFillGrid.Append("where BranchID = @BranchID "); SqlCommand cmd = new SqlCommand(qryFillGrid.ToString(), con); cmd.Parameters.AddWithValue("@BranchID", HttpContext.Current.Session["BranchID"]); // 添加AccountMode过滤条件 if (HttpContext.Current.Session["AccountMode"]?.ToString() != "ALL") { qryFillGrid.Append("and AccountMode = @AccountMode "); cmd.Parameters.AddWithValue("@AccountMode", HttpContext.Current.Session["AccountMode"].ToString()); } // 添加日期过滤条件 if (fromDate.HasValue) { qryFillGrid.Append("and CONVERT(date, cashbookdate) >= @FromDate "); cmd.Parameters.AddWithValue("@FromDate", fromDate.Value.Date); if (toDate.HasValue) { qryFillGrid.Append("and CONVERT(date, cashbookdate) <= @ToDate "); cmd.Parameters.AddWithValue("@ToDate", toDate.Value.Date); } } else { qryFillGrid.Append("and CONVERT(date, cashbookdate) = @TodayDate "); cmd.Parameters.AddWithValue("@TodayDate", DateTime.Now.Date); } qryFillGrid.Append("order by cashbookdate, cashbookid desc "); cmd.CommandText = qryFillGrid.ToString(); con.Open(); var dr = cmd.ExecuteReader(); while (dr.Read()) { var cashBookModel = new CashBookModel { Id = Convert.ToInt32(dr[0]), cashbookdate = Convert.ToDateTime(dr[1]), cashbookaccname = dr[2].ToString(), cashbookdescription = dr[3].ToString(), cashbookreceipt = Convert.ToDecimal(service.IfNullThen(dr[4], 0)), cashbookpayment = Convert.ToDecimal(service.IfNullThen(dr[5], 0)), Balance = Convert.ToDecimal(service.IfNullThen(dr[6], 0)), }; cashBook.Add(cashBookModel); } } var js = new JavaScriptSerializer(); Context.Response.Write(js.Serialize(cashBook)); }
额外说明
- 参数化查询既消除了SQL注入风险,也简化了日期条件的处理逻辑,无需复杂的字符串转换拼接。
- 前端新增的
destroy: true确保多次点击按钮时,DataTable能重新初始化而不报错。
内容的提问来源于stack exchange,提问作者s.k.Soni
相关产品推荐
相关产品推荐

