ASP.NET Core 6 MVC中View调用Controller返回JSON数据解析问题
ASP.NET Core 6 接口返回JSON及前端解析问题解决方案
问题描述
在ASP.NET Core 6控制器中编写接口后,视图通过AJAX调用能收到响应,但无法正确解析返回数据;此前依赖的JsonRequestBehavior.AllowGet在.NET 6中已被弃用,需要一个能返回任意动态对象的更优JSON方案,当前响应数据显示为undefined。
原控制器代码
public IActionResult GetAccountLevelAndCode(Int32 GroupAccountID, Int32 Companyid) { string AccountLevels = ""; string Returnerror; string ReturnBranches; DataTable AL = new GetDataClass().GetAccountNoAndAndLevels(GroupAccountID, Companyid, out Returnerror); //a = (GLChartOFAccountModel)AL.Rows[0].ConvertDataRowToObject(a); string Sql = @"select cab.BranchID from GLChartOFAccount ca inner join GLChartOfAccountBranchDetail cab on ca.GLCAID=cab.GLCAID where cab.GLCAID=" + GroupAccountID; DataTable dt = new DataTable(); dt = StaticClass.SelectAll(Sql).Tables[0]; AccountLevels = JsonConvert.SerializeObject(AL); ReturnBranches = JsonConvert.SerializeObject(dt); Returnerror = JsonConvert.SerializeObject(Returnerror); return Json(new { AccountLevels, ReturnBranches, Returnerror }); }
原视图AJAX调用代码
function GetAccountNoandLevel() { var DATA={"GroupAccountID" : $('#isParent').val(), Companyid : @Model.CompanyID } var execCode = true; $.ajax({ async: false, type: "POST", url: "/GLChartOFAccount/GetAccountLevelAndCode", data: DATA, dataType: "json", success: function (data) { try { var c = JSON.parse(data.AccountLevels) var b = JSON.parse(data.ReturnBranches) var er = JSON.parse(data.Returnerror) if (b.length>0) { $("#BrachIDs option").each(function () { var idParent = $(this).parent().attr("id"); this.disabled = true; }); var dataarray = ''; for (var i = 0; i < b.length; i++) { dataarray += b[i]["BranchID"] + ','; } dataarray = dataarray.replace(/,\s*$/, ""); var data = dataarray.split(","); $("#BrachIDs").val(data); $("#BrachIDs").change(); if (data.length > 0) { for (var i = 0; i < data.length; i++) { $("#BrachIDs option").filter("[value='" + data[i] + "']").attr('disabled', false); } } } else { $("#BrachIDs option").each(function () { var idParent = $(this).parent().attr("id"); this.disabled = false; }); $("#BrachIDs option:selected").removeAttr("selected"); } if (ShowErrorOK(er)) { $('#GLCode').val(''); }else{ RowToFillValues(c) } } catch (e) { //console.log(e + " GetAccountNoandLevel "); document.getElementById("DisplayErrorMessage").innerText = e.message; $('#btnTriggerMessage').click(); execCode = false; return false; console.log(e + " GetAccountNoandLevel "); console.log(e.message) } }, error: function (err) { //console.log(err.responseText); document.getElementById("DisplayErrorMessage").innerText = "AJAX error in request: " + JSON.stringify(err.statusText + " " + err.status) + " GetAccountNoandLevel::Unable To Get Details"; $('#btnTriggerMessage').click(); execCode = false; return false; console.log("AJAX error in request: " + JSON.stringify(err.statusText + " " + err.status) + " GetAccountNoandLevel::Unable To Get Details") } }); if (execCode) { } }
问题根源及优化方案
1. 控制器核心问题:双重序列化导致解析异常
原控制器中手动用JsonConvert.SerializeObject序列化DataTable和字符串,再通过Json()方法返回,相当于做了双重JSON序列化——前端拿到的是被转义后的字符串,而非直接可用的JSON对象,这会导致JSON.parse失败或解析出异常数据,最终出现undefined。
另外,.NET 6中Json()方法默认已允许GET/POST请求返回JSON,无需再使用已弃用的JsonRequestBehavior.AllowGet。
2. 优化后的控制器代码
直接返回包含DataTable和错误信息的匿名对象,由ASP.NET Core框架自动完成序列化:
public IActionResult GetAccountLevelAndCode(Int32 GroupAccountID, Int32 Companyid) { string returnError; DataTable accountLevels = new GetDataClass().GetAccountNoAndAndLevels(GroupAccountID, Companyid, out returnError); // 必须使用参数化查询避免SQL注入风险 string sql = @"select cab.BranchID from GLChartOFAccount ca inner join GLChartOfAccountBranchDetail cab on ca.GLCAID=cab.GLCAID where cab.GLCAID = @GroupAccountID"; // 假设StaticClass.SelectAll支持传入参数对象,若不支持需改用SqlCommand添加参数 DataTable branches = StaticClass.SelectAll(sql, new { GroupAccountID }).Tables[0]; return Json(new { AccountLevels = accountLevels, ReturnBranches = branches, ReturnError = returnError }); }
3. 优化后的前端AJAX代码
控制器返回的是直接可用的JSON对象,无需再调用JSON.parse,直接访问属性即可:
function GetAccountNoandLevel() { var DATA = {"GroupAccountID" : $('#isParent').val(), Companyid : @Model.CompanyID }; var execCode = true; $.ajax({ async: false, type: "POST", url: "/GLChartOFAccount/GetAccountLevelAndCode", data: DATA, dataType: "json", success: function (response) { try { const accountLevels = response.AccountLevels; const branches = response.ReturnBranches; const returnError = response.ReturnError; if (branches.length > 0) { $("#BrachIDs option").prop('disabled', true); const branchIds = branches.map(item => item.BranchID); $("#BrachIDs").val(branchIds).change(); branchIds.forEach(id => { $("#BrachIDs option[value='" + id + "']").prop('disabled', false); }); } else { $("#BrachIDs option").prop('disabled', false).removeAttr('selected'); } if (ShowErrorOK(returnError)) { $('#GLCode').val(''); } else { RowToFillValues(accountLevels); } } catch (e) { console.log("GetAccountNoandLevel 异常:", e); console.log("异常信息:", e.message); } }, error: function (err) { console.log("AJAX请求错误:", `状态: ${err.status} ${err.statusText}`, "GetAccountNoandLevel::无法获取详情"); } }); if (execCode) { // 后续逻辑 } }
优化说明:用
prop替代attr操作表单元素属性(符合jQuery最佳实践),用map简化数组转换,提升代码可读性。
内容的提问来源于stack exchange,提问作者Ahsan Raza
相关产品推荐
相关产品推荐

