ASP.NET Core MVC DateTime变量AppEndDate显示非预期值问题
问题根因
核心错误出在HttpGet接口读取最新配置的查询逻辑:
- 现有代码分别对
AppStartDate、AppEndDate两个字段单独取全表最大值,没有从同一条最新记录中读取两个日期值。 - 业务逻辑是始终保留最新一条配置记录,但最新记录的
AppEndDate不一定是全表最大的:比如旧配置是2022-06-01至2022-06-30,新配置改成2022-06-10至2022-06-20,此时Max(i=>i.AppStartDate)取到新记录的2022-06-10(显示正常),但Max(i=>i.AppEndDate)会取到旧记录的2022-06-30(也就是你看到的30-06-2022旧值),和新记录的开始日期拼接后就出现了显示错误。
另外还有两个附带bug:
- HttpGet方法中初始化了
ParentVM模型对象,但返回视图时没有传入,会导致表单asp-for绑定默认值异常。 - HttpPost方法中手动给WC静态字段赋值属于多余操作,且静态字段本身存在应用重启丢失、多实例部署不一致的风险,同时现有取Max(Id)删数据的逻辑存在并发报错、空引用风险。
修复方案
1. 修正HttpGet的查询逻辑
替换原来分别取两个字段最大值的代码,改为直接读取Id最大的最新一条完整记录,两个日期都从该记录取值,同时修正视图传参:
[HttpGet] public async Task <IActionResult> AppPeriod(bool IsSuccess=false) { ParentForApply ParentVM = new ParentForApply(); // 直接取最新的配置记录,不需要单独Count查询 var latestConfig = await _db.AppDuration.OrderByDescending(i => i.Id).FirstOrDefaultAsync(); if (latestConfig == null) { WC.AppStartDate = DateTime.MinValue; WC.AppEndDate = DateTime.MinValue; } else { // 两个日期都从同一条最新记录取,避免跨记录拼接 WC.AppStartDate = latestConfig.AppStartDate; WC.AppEndDate = latestConfig.AppEndDate; } ViewBag.IsDurationSet = IsSuccess; // 把模型传入视图 return View(ParentVM); }
2. 修正HttpPost的提交逻辑
去掉多余的静态字段赋值,优化删旧数据的逻辑,避免空引用和并发问题:
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> AppPeriod(ParentForApply ParentVM) { // 直接查最新记录删除,不需要单独取MaxId var oldConfig = await _db.AppDuration.OrderByDescending(i => i.Id).FirstOrDefaultAsync(); if (oldConfig != null) { _db.AppDuration.Remove(oldConfig); } AppDurationPeriod app = new AppDurationPeriod() { AppStartDate = ParentVM.AppPeriod.AppStartDate, AppEndDate = ParentVM.AppPeriod.AppEndDate }; await _db.AppDuration.AddAsync(app); await _db.SaveChangesAsync(); // 不需要手动给WC赋值,Redirect后Get请求会自动加载最新数据库值 return RedirectToAction("AppPeriod",new { IsSuccess = true}); }
3. 可选优化
不建议用静态类WC存储全局配置值,静态值会在IIS应用池回收、服务重启后丢失,多实例部署时不同实例的静态值还会不一致,生产环境建议改用内存缓存、分布式缓存存储配置,或者每次需要时直接从数据库读取最新值。
内容的提问来源于stack exchange,提问作者Azhar Qureshi
相关产品推荐
相关产品推荐

