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

ASP.NET Core MVC视图传对象至控制器数据丢失问题

问题分析与解决方案

问题核心

ASP.NET Core MVC视图中每行对应一个ConnectorDto实体,表单提交到Connectors控制器的Modify方法时,控制器接收的ConnectorDto对象中Id、EntityFromId、EntityToId、CreatedAt、LastUpdatedAt等字段为默认值,但浏览器Payload显示这些字段已携带有效数据,使用[FromForm]特性后问题仍未解决。

原因排查

从浏览器Payload可以看出:

  1. 字段命名不一致:存在entity.EntityFromType这种带前缀的字段,而其他字段是Id、EntityFromId,导致模型绑定无法正确映射到ConnectorDto的属性。
  2. DateTime格式不兼容:提交的日期格式为09.07.2023+17%3A12%3A20,不符合.NET默认的日期解析格式,导致CreatedAt、LastUpdatedAt绑定失败。
  3. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 23:04:58