使用ContentPart读取设置参数、保存至ContentItem并更新设置参数的问题排查
问题根因与修复方案
你的代码存在两个核心逻辑错误,按顺序修复即可:
1. 错误调用TryUpdateModelAsync覆盖手动赋值
TryUpdateModelAsync的作用是从当前HTTP请求的表单数据中读取字段,覆盖到模型对象。新建内容项首次提交时,你的隐藏字段IncrementalId是空值,调用该方法会直接把你刚刚自增赋值的model.IncrementalId覆盖为null,导致后续保存失败。
这个字段是后台逻辑生成的,不需要从表单获取输入,直接删除updater.TryUpdateModelAsync相关代码即可。
2. 异步上下文同步阻塞导致死锁
你读取站点设置时用了.GetAwaiter().GetResult()同步阻塞调用,在ASP.NET Core的异步上下文环境中极容易触发死锁,这就是你调用UpdateSiteSettingsAsync后方法直接中断、不执行后续返回逻辑的原因,把读取逻辑改成标准异步await写法即可。
修正后代码
public override async Task<IDisplayResult> UpdateAsync(IncrementalPart model, IUpdateModel updater) { // 仅当IncrementalId不存在时生成(IncrementalId为int?类型) if (!model.IncrementalId.HasValue) { // 异步读取站点设置,避免死锁 var incrementalSettings = await _siteService.GetSiteSettingsAsync(); var settings = incrementalSettings.As<IncrementalSettings>(); // 自增后赋值给模型 model.IncrementalId = ++settings.LastId; // 更新站点设置 incrementalSettings.Alter<IncrementalSettings>(nameof(IncrementalSettings), isett => isett.LastId = model.IncrementalId.GetValueOrDefault()); await _siteService.UpdateSiteSettingsAsync(incrementalSettings); } return Edit(model); }
补充注意事项
- 你视图里的
IncrementalId隐藏字段保留即可,编辑内容项时该字段已有值,不会进入生成逻辑,隐藏字段会携带现有值提交,避免重复生成ID。 - 高并发场景下建议给站点设置的更新逻辑加分布式锁,避免多个请求同时拿到相同的
LastId生成重复编号,低并发场景当前写法可正常使用。
内容的提问来源于stack exchange,提问作者Jesús Alejandre
相关产品推荐
相关产品推荐

