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

ASP.NET控制器传值到视图回传时其余字段为null如何解决

问题根因

HTTP表单提交只会发送<form>标签内部带name属性的有效输入控件的值,你当前表单中仅存在绑定Name属性的输入框,Id、Cas、Room字段没有任何对应的表单项,提交请求时不会携带这三个字段的值,后端模型绑定自然无法给这几个字段赋值,和POST Action中[Bind]特性的白名单配置无关。
另外你的form标签存在笔误:多写了一个空的asp-属性,会影响ASP.NET Core标签助手的正常渲染,需要删除。
额外注意:Room是自定义复杂引用类型,即使你添加<input type="hidden" asp-for="Room" />也无法完成绑定,模型绑定器需要匹配Room.属性名格式的多个值才能填充复杂类型对象。

解决方案

你可以根据数据安全需求,选择以下两种方案:

方案1:添加隐藏域传递非编辑字段(适合非敏感数据)

在表单内部为不需要用户编辑、需要回传的字段添加隐藏输入框,复杂类型Room建议通过外键ID传递,不要直接传递整个对象。

  1. 建议先给ReservationModel补充外键字段(如果尚未定义):
public class ReservationModel
{
    [Key]
    public int Id { get; set; }

    public string Name { get; set; }

    public DateTime Cas { get; set; }

    // 新增关联Room的外键
    public int RoomId { get; set; }
    public RoomModel Room { get; set; }
}

如果你不想加外键,也可以为Room的每个需要保留的属性单独加隐藏域,比如<input type="hidden" asp-for="Room.Id" />,但这种方式繁琐易漏字段,不推荐。
2. 修改视图代码,添加对应隐藏域,删除无效的asp-笔误:

@model ReservationModel

<form asp-controller="Home" asp-action="CreateReservation" method="post">
    <!-- 隐藏域回传非编辑字段 -->
    <input type="hidden" asp-for="Id" />
    <input type="hidden" asp-for="Cas" />
    <input type="hidden" asp-for="RoomId" />

    <input required="required" type="text" class="form-control scan" placeholder="Name"
           asp-for="Name" />
    <span asp-validation-for="Name" class="text-danger"></span>
    <input type="submit" class="model-close button btn btn-primary primary-btn"
           style="width:auto;" value="Add" />
</form>
  1. 对应修改POST Action的[Bind]白名单,加入RoomId,移除无法直接绑定的Room:
[HttpPost]
[Route("Home/Room/Create_reservation")]
public async Task<IActionResult> CreateReservation([Bind("Name","RoomId","Cas","Id")] ReservationModel reservationModel)
{
    if (!ModelState.IsValid)
    {
        // 校验不通过时返回视图,需要将模型传回
        return View(reservationModel);
    }
    // 根据RoomId查询对应Room对象,赋值给reservationModel.Room后执行保存逻辑
    return RedirectToAction("Index");
}

注意:隐藏域的值可以被用户通过浏览器开发者工具随意篡改,POST接口必须做合法性校验,比如校验当前用户是否有权限操作对应ID的预约、RoomId是否合法、Cas时间是否在允许预约范围内,避免越权操作。

方案2:后端重新查询关联数据(适合敏感字段,安全性更高)

如果Id、Cas、Room属于不希望被用户篡改的敏感数据,就不要把这些值放到前端,提交时只传用户输入的Name字段,后端根据上下文重新查询原始数据再合并:

  1. GET Action中将需要保留的唯一标识存入TempData(支持跨单次请求传递):
[HttpGet]
[Route("Home/Room/Create_reservation")]
public async Task<IActionResult> CreateReservation(DateTime date)
{
    ReservationModel reservation = await _reservation.PrepareModel(date, _id);
    // 存储原始数据标识
    TempData["ReservationId"] = reservation.Id;
    TempData["ReservationCas"] = reservation.Cas.ToString("o"); // 日期用ISO标准格式序列化
    TempData["RoomId"] = reservation.Room.Id;
    return View(reservation);
}
  1. 视图不需要加任何隐藏域,仅保留Name输入框即可,记得删除form标签中无效的asp-笔误。
  2. POST Action中仅接收Name字段,从TempData取出原始标识组装完整模型:
[HttpPost]
[Route("Home/Room/Create_reservation")]
public async Task<IActionResult> CreateReservation(string Name)
{
    // 校验TempData中的原始标识是否合法
    if (!int.TryParse(TempData["ReservationId"]?.ToString(), out int resId)
        || !DateTime.TryParse(TempData["ReservationCas"]?.ToString(), out DateTime cas)
        || !int.TryParse(TempData["RoomId"]?.ToString(), out int roomId))
    {
        // 数据过期或非法时重定向到预约入口
        return RedirectToAction("Index");
    }
    // 查询关联的Room信息
    var room = await _dbContext.Rooms.FindAsync(roomId);
    var reservationModel = new ReservationModel
    {
        Id = resId,
        Cas = cas,
        Room = room,
        Name = Name
    };
    // 执行校验、保存逻辑
    return RedirectToAction("Success");
}

该方案完全避免了前端篡改敏感字段的风险,适合数据安全要求高的场景。

内容的提问来源于stack exchange,提问作者fikus

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 16:33:41