在ASP.NET Core 2.2中通过Ajax获取子模型数据的问题
我来帮你快速定位并解决这个问题——你遇到的Ajax返回undefined的情况,大概率是后端序列化配置、实体类属性定义,或者前端上下文的问题,咱们一步步排查修复:
1. 先排查请求本身是否正常
首先打开浏览器开发者工具(按F12),切换到Network标签页,触发展开菜单的操作,找到SubMenu的请求:
- 如果请求状态码不是200:检查
url: "/User/SubMenu"是否正确(确保你的控制器是UserController,且SubMenu方法标记了[HttpGet],虽然默认允许GET,但显式标记更稳妥);另外确认pid参数是否正确传递。 - 如果状态码是200但返回内容为空/格式错误:问题出在后端的Json序列化环节。
2. 修复后端序列化问题
最可能的原因:实体类属性没有公共getter
先检查AuthDepartment类的属性定义,确保DepartId、DepatName、NavUrl这些字段是公共且带有get访问器的,比如:
public class AuthDepartment { public int DepartId { get; set; } public string DepatName { get; set; } //注意你这里拼写是DepatName,前端要和这个一致 public string NavUrl { get; set; } public int ParentMenuId { get; set; } //其他属性... }
如果属性是私有或者没有getter,Json序列化器会直接忽略它们,导致返回空数组或者无效的JSON结构。
简化控制器返回逻辑,避免中间对象干扰
你当前的控制器代码是把查询结果赋值给subcomp._InstanceDepartment再返回,这个中间对象UserSecurityMains的_InstanceDepartment如果是私有字段(下划线开头通常是私有命名约定),序列化器也会忽略它。直接返回查询到的列表更稳妥:
[HttpGet] //显式标记为GET请求 public JsonResult SubMenu(string pid) { System.Threading.Thread.Sleep(1000); int pID = 0; int.TryParse(pid, out pID); using (QAEntities context = new QAEntities()) { var subDepartments = context.AuthDepartment .Where(x => x.ParentMenuId.Equals(pID)) .OrderBy(c => c.DepatName) .ToList(); //直接返回列表,跳过中间对象 return Json(subDepartments); } }
处理可能的循环引用问题
如果AuthDepartment类有导航属性(比如关联父部门的属性),可能会触发循环引用,导致序列化失败。可以在Startup.cs中配置Json序列化忽略循环引用:
public void ConfigureServices(IServiceCollection services) { services.AddMvc() .AddJsonOptions(options => { options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; }); }
3. 修复前端Ajax的上下文和错误处理
确保this1的上下文正确
在Ajax的success回调中,this的上下文会发生变化,如果你之前的this1是点击的元素,一定要在请求前保存它的引用,避免DOM操作失效:
// 假设点击事件是绑定在.collapsible上的 $('.collapsible').click(function() { var $currentElement = $(this); // 保存当前点击元素的引用 var pid = $currentElement.attr('pid'); $.ajax({ url: "/User/SubMenu", type: "GET", data: { pid: pid }, // 明确传递pid参数 dataType: "json", beforeSend: function() { $currentElement.addClass("loadingP"); }, success: function (d) { $currentElement.removeClass("loadingP"); console.log(d); // 先在控制台打印d,确认是否有数据 if (d && d.length > 0) { var $ul = $("<ul></ul>"); $.each(d, function (i, ele) { $ul.append( $("<li></li>").append( `<span class='collapse collapsible' data-loaded='false' pid='${ele.DepartId}'> </span>` + `<span><a href='${ele.NavUrl}'>${ele.DepatName}</a></span>` ) ); }); $currentElement.parent().append($ul); $currentElement.addClass('collapse').toggleClass('collapse expand'); $currentElement.closest('li').children('ul').slideDown(); } else { // 处理无数据的情况 } }, error: function(xhr, status, error) { console.error("请求出错:", status, error); // 打印错误信息,快速排查问题 $currentElement.removeClass("loadingP"); } }); });
增加error回调能帮你快速发现请求失败的原因,比如参数错误、路径错误等。
4. 最后验证数据传递
在控制器的SubMenu方法里设置断点,查看pid的值是否正确,以及查询到的subDepartments是否有数据——如果后端能查到数据,那按照上面的步骤调整后,前端应该能正常获取到JSON数据了。
内容的提问来源于stack exchange,提问作者PatsonLeaner

