You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MVC返回Json的LINQ联表查询结果无法被Ajax success方法接收

问题描述

我尝试将三张表关联的LINQ join查询结果通过控制器的Json Result返回给前端Ajax的success回调函数,但目前无法获取到任何返回值,success函数不会触发,只会执行error函数。该LINQ查询可以生成正确结果,在return Json(query)或return new JsonResult{ Data = query, JsonRequestBehavior = JsonRequestBehavior.AllowGet };处打断点时,query变量中已包含有效数据,问题在于查询结果无法从控制器成功传递到前端Ajax函数,我已尝试其他可行方案均未解决。

备注:我已创建专用的模型类存储联表查询结果。

控制器代码

[HttpPost]
public JsonResult getscore(int val)
{
    Debug.WriteLine("checking {0}", val);
    var g = val;
    List<Participant_info> p_details = context.Participant_info.ToList();
    List<Participant_enrolled> e_details = context.Participant_enrolled.ToList();
    List<Contest_marking> mark = context.Contest_marking.ToList();

    var query = (from p in p_details
                 join e in e_details on p.stud_id equals e.stud_id 
                
                 join m in mark on e.E_id equals m.E_id 
                 
                 select new ScoreViewModel
                 {
                     partVm = p,
                     enrollVm = e,
                     markVm = m
                 }).ToList();

    foreach (var u in query)
    {
        Debug.WriteLine("name {0} mark{1} Contest_id {2} ", u.partVm.stud_name, u.markVm.C1st_marks, u.enrollVm.Contest_id);
    }
    return Json(query, JsonRequestBehavior.AllowGet);
    //return new JsonResult { Data = query, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}

模型类代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace CEN_CONTEST_MGT_SYSTEM.Models
{
    public class ScoreViewModel
    {
        public Participant_info partVm { get; set; }
        public Participant_enrolled enrollVm { get; set; }
        public Contest_marking markVm { get; set; }
    }
}

视图层代码

@model IEnumerable<CEN_CONTEST_MGT_SYSTEM.Models.ScoreViewModel> 
@{
    ViewBag.Title = "score";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>score</h2>
@Html.DropDownList("Trial", "---  Tous  ---")
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js"></script>
<script type="text/javascript">
    $("#Trial").change(function () {
        val = $("#Trial").val();
        alert("fff" + val);
        $.ajax({
            type: "POST",
            url: "/judge_dashboard/getscore",
            data: JSON.stringify({'val': val}),
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            async: true,
            processData: false,
            cache: false,
            success: function (data) {
                alert("hello");
            },
            error: function () {
                alert("error");
                
            }
        })
    })
</script>
问题根因

90%以上概率是JSON序列化失败:你直接把EF实体对象放到ViewModel中返回,EF实体通常带有导航属性(比如Participant_info里可能包含关联的Participant_enrolled集合,Participant_enrolled又反过来关联Participant_info),序列化JSON时会触发循环引用,导致服务端抛出500异常,前端无法拿到合法JSON响应就会进入error回调。

解决方案
  • 方案1(最推荐):修改ViewModel,只返回前端需要的字段,不要直接存储EF实体对象
    调整ScoreViewModel定义,仅保留需要使用的属性:

    public class ScoreViewModel
    {
        public string StudName { get; set; }
        public decimal C1stMarks { get; set; }
        public int ContestId { get; set; }
        // 其他前端需要用到的字段按需添加即可
    }
    

    修改LINQ查询,直接为ViewModel属性赋值:

    var query = (from p in p_details
                 join e in e_details on p.stud_id equals e.stud_id 
                 join m in mark on e.E_id equals m.E_id 
                 select new ScoreViewModel
                 {
                     StudName = p.stud_name,
                     C1stMarks = m.C1st_marks,
                     ContestId = e.Contest_id
                     // 其他字段逐一赋值
                 }).ToList();
    

    这个方案既可以避免循环引用问题,也能减少不必要的数据传输,性能和安全性更好。

  • 方案2:先查看具体错误信息,定位问题
    修改前端ajax的error回调,输出详细错误内容:

    error: function (xhr, status, error) {
        console.log("错误状态码:" + xhr.status);
        console.log("错误详情:" + error);
        console.log("服务端返回内容:" + xhr.responseText);
        alert("请求出错,请打开浏览器控制台查看详情");
    }
    

    按F12打开浏览器开发者工具的控制台,就能看到具体错误类型,如果是500错误基本可以确认是序列化问题。

  • 方案3(临时兼容方案):配置JSON序列化忽略循环引用
    如果你一定要保留整个EF实体的结构,可以在项目的Global.asax.cs的Application_Start方法中添加配置:

    protected void Application_Start()
    {
        // 原有配置不变,新增下面一行
        GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
    }
    

    注意这个方案会返回很多冗余字段,不推荐长期使用。

  • 小优化:你的接口标记了[HttpPost],不需要加JsonRequestBehavior.AllowGet参数,这个参数仅用于GET请求返回JSON的场景,POST请求可以直接写return Json(query);。


内容的提问来源于stack exchange,提问作者Muneeba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 01:54:04