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

ASP.NET MVC中使用DataTables加载数据库数据失败求助

问题排查:ASP.NET MVC + DataTables 加载数据失败

用户问题

我是编程新手,正在基于C#的ASP.NET MVC项目中尝试用DataTables从数据库加载数据。按照修改后的代码返回数据后,页面一直显示加载状态无法完成加载,还出现了错误提示。以下是相关控制器代码:

namespace believe.Controllers {
public class ProductController : Controller
{
private readonly IUnitOfWork _context;
private readonly IWebHostEnvironment _hostEnvironment;
public ProductController(IUnitOfWork context, IWebHostEnvironment hostEnvironment)
{
_context = context;
_hostEnvironment = hostEnvironment;
}

    public IActionResult Index()
    {
       
        return View();
    }
    //GET
   
  
    public IActionResult Delete(int? id)
    {
        if (id is null or 0)
        {
            return NotFound();
        }
        var obj = _context.Product.GetFirstOrDefault(c => c.Id == id);
        return View(obj);
    }
    [HttpPost]
    public IActionResult DeletePOST(int? id)
    {
        var obj = _context.Product.GetFirstOrDefault(c => c.Id == id);
        if (obj == null)
        {
            return NotFound();
        }
        _context.Product.Remove(obj);
       _context.Save();
        TempData["success"] = "Category deleted successfully";
        return RedirectToAction("Index");   
    }
    public IActionResult UpSert(int? id)
    {

        //Product product = new();
        //IEnumerable < SelectListItem > CategoryList = _context.Category.GetAll().Select(u=>new SelectListItem { Text = u.Name, Value = u.Id.ToString() });
        // IEnumerable<SelectListItem> CoverTypeList = _context.CoverType.GetAll().Select(u => new SelectListItem { Text = u.Name, Value = u.Id.ToString() });
        ProductVM productVM = new()
        {
            Product = new(),
         CategoryList =    _context.Category.GetAll().Select(u => new SelectListItem { Text = u.Name, Value = u.Id.ToString() }),
         CoverTypeList =  _context.CoverType.GetAll().Select(u => new SelectListItem { Text = u.Name, Value = u.Id.ToString() })


        };
        
        if (id is null or 0)
        {
            //create product

            //ViewBag.CategoryList = CategoryList;
            //ViewBag.CoverTypeList = CoverTypeList;  
            return View(productVM);
        }
        else
        {
            //update product
        }
      ;
        return View(productVM);
    }
    [HttpPost]
    public IActionResult UpSert(ProductVM obj, IFormFile? file)
    {
        

        if(ModelState.IsValid)
        {
            string wwwRootPath = _hostEnvironment.WebRootPath;
            if(file !=null)
            {
                string fileName = Guid.NewGuid().ToString();
                var uploads = Path.Combine(wwwRootPath, @"images\products");
                var extension = Path.GetExtension(file.FileName);
                using(var fileStreams = new FileStream(Path.Combine(uploads, fileName + extension),

FileMode.Create))
{
file.CopyTo(fileStreams);
}
obj.Product.ImageUrl = @"\images\products" + fileName + extension;
}

            _context.Product.Add(obj.Product);
            _context.Save();
            TempData["success"] = "Product  update successfully";
            return RedirectToAction("Index");
        }
        return View(obj);
        
    }
    #region API CALLS
    [HttpGet]
    public IActionResult GetAll()
    {
        var productList = _context.Product.GetAll();
        return Json(productList); 
    }
        

    #endregion
}

错误原因分析

从代码和常见场景判断,问题出在两个核心点:

  1. DataTables格式不兼容:DataTables要求返回的JSON必须包含data属性来承载表格数据数组,但你的GetAll方法直接返回实体列表,没有按要求包装,导致DataTables无法识别数据结构。
  2. 循环引用序列化失败:_context.Product.GetAll()返回的Product实体可能关联了Category、CoverType等对象,JSON序列化时会触发循环引用错误,服务器无法正常返回数据,页面因此一直处于加载状态。

解决方案

方案1:使用DTO(推荐)

通过创建数据传输对象,只返回表格需要的字段,避免关联对象和序列化问题:

  1. 创建ProductDTO类:
public class ProductDTO
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public string ImageUrl { get; set; }
    // 根据你的DataTables列添加其他需要的字段
}
  1. 修改GetAll方法,映射实体到DTO并包装格式:
[HttpGet]
public IActionResult GetAll()
{
    var productList = _context.Product.GetAll()
        .Select(p => new ProductDTO
        {
            Id = p.Id,
            Name = p.Name,
            Price = p.Price,
            ImageUrl = p.ImageUrl
            // 映射其他字段
        }).ToList();
    return Json(new { data = productList });
}

方案2:配置序列化忽略循环引用(快速调试用)

如果不想创建DTO,可直接配置序列化规则:

  1. 在.NET 6+的Program.cs中添加配置:
builder.Services.AddControllersWithViews()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
    });
  1. 修改GetAll方法包装数据格式:
[HttpGet]
public IActionResult GetAll()
{
    var productList = _context.Product.GetAll().ToList();
    return Json(new { data = productList });
}

额外检查

确认前端DataTables的AJAX配置正确指向/Product/GetAll,且columns字段名与后端返回字段完全匹配,示例:

$(document).ready(function() {
    $('#productTable').DataTable({
        "ajax": "/Product/GetAll",
        "columns": [
            { "data": "id" },
            { "data": "name" },
            { "data": "price" },
            // 其他列配置
        ]
    });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 00:15:35