ASP.Net Core 2.0 JSON缺失大括号问题及Create代码排查请求
我来帮你解决这两个问题,结合ASP.NET Core 2.0的特性给你具体方案:
返回的JSON没有大括号,通常是因为你返回的是原始数据类型(字符串、数字等),而不是一个对象。ASP.NET Core默认会直接序列化原始值,不会自动包裹成JSON对象。这里有几个解决思路:
确保返回对象而非原始值:
比如你之前可能写了这样的代码:// 错误:返回单个字符串,无大括号 public IActionResult GetStatus() { return Ok("success"); }改成返回一个匿名对象或者自定义类实例,就能得到带大括号的JSON:
// 正确:返回对象,自动包裹大括号 public IActionResult GetStatus() { return Ok(new { Status = "success", Message = "操作完成" }); }全局配置JSON格式化器(可选):
如果需要统一调整JSON序列化规则(比如美化格式、忽略空值),可以在Startup.cs的ConfigureServices方法里配置:services.AddMvc() .AddJsonOptions(options => { // 开启格式化缩进,让JSON更易读 options.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented; // 忽略值为null的字段,减少JSON体积 options.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore; });注意:ASP.NET Core 2.0默认使用Newtonsoft.Json,这个配置不会改变“原始值不包裹大括号”的默认行为,只是优化序列化细节。
检查Action返回类型:
如果你的Action返回的是JsonResult,确保传入的是对象而非原始值:public JsonResult GetData() { // 正确:传入对象 return Json(new { Id = 1, Name = "Test Vehicle" }); }
从你给出的截断代码来看,有几个明显的问题和优化点:
修复Regex.Replace的截断问题:
代码里vehicle.ConductionStic...明显是拼写错误或者代码截断,应该补全为vehicle.ConductionSticker,同时确保正则表达式完整。比如如果是要去除非字母数字字符,应该写成:vehicle.ConductionSticker = Regex.Replace(vehicle.ConductionSticker, @"[^a-zA-Z0-9]", "");完善事务的提交与回滚逻辑:
你已经开启了数据库事务,但目前代码里没有提交事务的逻辑,也没有异常时的回滚处理。如果不提交,所有数据库操作都不会生效;异常时不回滚会浪费数据库连接资源。补全后的代码应该是:using (var transaction = await _context.Database.BeginTransactionAsync()) { try { if (ModelState.IsValid) { // 补全你的业务逻辑,比如添加实体到上下文 if (!String.IsNullOrEmpty(vehicle.ConductionSticker)) { vehicle.ConductionSticker = Regex.Replace(vehicle.ConductionSticker, @"[^a-zA-Z0-9]", ""); } _context.Vehicles.Add(vehicle); await _context.SaveChangesAsync(); // 提交事务 await transaction.CommitAsync(); return RedirectToAction(nameof(Index)); } } catch (Exception ex) { // 异常时回滚事务 await transaction.RollbackAsync(); // 给用户返回错误信息 ModelState.AddModelError(string.Empty, "创建车辆失败:" + ex.Message); } } // 如果ModelState无效或者出错,返回视图 return View(vehicle);优化ModelState验证的位置:
目前你是在事务开启后才验证ModelState,建议提前到事务之前,避免无效的事务资源占用:public async Task<IActionResult> Create([Bind("ModelID,ConductionSticker,Vin,EngineNumber,Cost,Date,Description,RowVersion")] Vehicle vehicle) { // 先验证ModelState,无效直接返回视图 if (!ModelState.IsValid) { return View(vehicle); } // 移除不必要的模拟延迟(生产代码不需要Task.Delay) // await Task.Delay(2000); using (var transaction = await _context.Database.BeginTransactionAsync()) { // ...后续事务逻辑 } }替换Bind属性为DTO(更安全灵活):
使用Bind属性虽然能限制参数绑定,但如果Vehicle实体后续添加新字段,容易遗漏或者出现安全问题。建议用**DTO(数据传输对象)**来接收请求参数,再映射到实体:// 定义DTO类,只包含需要的字段 public class VehicleCreateDto { public int ModelID { get; set; } public string ConductionSticker { get; set; } public string Vin { get; set; } public string EngineNumber { get; set; } public decimal Cost { get; set; } public DateTime Date { get; set; } public string Description { get; set; } public byte[] RowVersion { get; set; } } // 修改Action接收DTO public async Task<IActionResult> Create(VehicleCreateDto dto) { if (!ModelState.IsValid) { return View(dto); } // 映射DTO到Vehicle实体 var vehicle = new Vehicle { ModelID = dto.ModelID, ConductionSticker = dto.ConductionSticker, Vin = dto.Vin, // 映射其他字段... }; // ...后续事务逻辑 }
内容的提问来源于stack exchange,提问作者Marco Torrecampo

