ASP.NET Core MVC视图传对象至控制器数据丢失问题
问题分析与解决方案
问题核心
ASP.NET Core MVC视图中每行对应一个ConnectorDto实体,表单提交到Connectors控制器的Modify方法时,控制器接收的ConnectorDto对象中Id、EntityFromId、EntityToId、CreatedAt、LastUpdatedAt等字段为默认值,但浏览器Payload显示这些字段已携带有效数据,使用[FromForm]特性后问题仍未解决。
原因排查
从浏览器Payload可以看出:
- 字段命名不一致:存在
entity.EntityFromType这种带前缀的字段,而其他字段是Id、EntityFromId,导致模型绑定无法正确映射到ConnectorDto的属性。 - DateTime格式不兼容:提交的日期格式为
09.07.2023+17%3A12%3A20,不符合.NET默认的日期解析格式,导致CreatedAt、LastUpdatedAt绑定失败。 - foreach循环的模型绑定缺陷:使用
foreach (var entity in Model)遍历集合时,生成的表单字段没有索引标识,ASP.NET Core无法正确识别集合项的绑定关系。
解决方案
1. 修复视图的模型绑定逻辑
将foreach循环改为for循环,利用索引生成正确的表单字段名,确保模型绑定能正确识别每个实体的属性:
@model List<Models.DTO.DBO.ConnectorDto> @for (int i = 0; i < Model.Count; i++) { <tr> <form asp-controller="Connectors" asp-action="Modify"> <th> <input type="text" readonly name="Id" value="@Model[i].Id"/> </th> <th> @Html.DropDownListFor(model => model[i].EntityFromType, Enum.GetValues(typeof(Enumerators.ObjectType)).Cast<Enumerators.ObjectType>().Select(enumValue => new SelectListItem { Text = enumValue.ToString(), Value = ((int)enumValue).ToString(), Selected = Model[i].EntityFromType == enumValue })) </th> <th> <input type="text" name="EntityFromId" value="@Model[i].EntityFromId" /> </th> <th> @Html.DropDownListFor(model => model[i].EntityToType, Enum.GetValues(typeof(Enumerators.ObjectType)).Cast<Enumerators.ObjectType>().Select(enumValue => new SelectListItem { Text = enumValue.ToString(), Value = ((int)enumValue).ToString(), Selected = Model[i].EntityToType == enumValue })) </th> <th> <input type="text" name="EntityToId" value="@Model[i].EntityToId" /> </th> <th> <input type="datetime" readonly name="CreatedAt" value="@Model[i].CreatedAt.ToString("yyyy-MM-ddTHH:mm:ss")" /> </th> <th> <input type="datetime" readonly name="LastUpdatedAt" value="@Model[i].LastUpdatedAt.ToString("yyyy-MM-ddTHH:mm:ss")" /> </th> <th> <input name="submit" type="submit" value="Zmodyfikuj" /> </th> </form> <th> <form asp-controller="Connectors" asp-action="Remove"> <input name="remove" type="submit" value="Usuń" /> <input type="hidden" name="entityId" value="@Model[i].Id" /> </form> </th> </tr> }
2. 调整模型的DateTime字段绑定
在Base类的DateTime属性上添加[DisplayFormat]特性,指定可接受的输入格式:
public abstract class Base { [DatabaseGenerated(DatabaseGeneratedOption.Identity)] [Key] public int Id { get; set; } [DisplayFormat(DataFormatString = "{0:yyyy-MM-ddTHH:mm:ss}", ApplyFormatInEditMode = true)] public DateTime CreatedAt { get; set; } = DateTime.Now; [DisplayFormat(DataFormatString = "{0:yyyy-MM-ddTHH:mm:ss}", ApplyFormatInEditMode = true)] public DateTime LastUpdatedAt { get; set; } public Enumerators.ObjectType ObjectType { get; set; } }
3. 优化控制器的参数绑定
在Modify方法的参数上明确添加[FromForm]特性,并确保参数名称与表单字段对应:
[HttpPost("Modify")] public IActionResult Modify([FromForm] ConnectorDto entity) { return ConnectorService.Update(entity) ? Index() : Error("修改失败"); }
额外说明
- 移除了
DropDownListFor中手动设置的@name属性,让HtmlHelper自动生成正确的字段名,避免命名冲突。 - 将DateTime格式改为ISO标准格式(
yyyy-MM-ddTHH:mm:ss),确保.NET能正确解析提交的日期值。 - 使用
for循环替代foreach,解决集合项的模型绑定识别问题,确保每个实体的字段能正确映射到ConnectorDto对象。
内容的提问来源于stack exchange,提问作者Zygmunt Kołodziejczyk
相关产品推荐
相关产品推荐

