当我从具有多个表单的视图提交表单时,为什么我的控制器会收到空值?使用 ASP.NET Core 5 MVC

Why do I receive null values in my controller when I submit a form from a view with multiple forms? With ASP.NET Core 5 MVC

我正在使用 ASP.NET Core 5 MVC 开发 Web 应用程序,在其中我试图从接收 IEnumerable(来自一个名为 Result 的模型),我用它动态填充每个表单的输入值。

但是,当我通过控制器从视图发送这些表单之一时,在控制器中我只从模型接收到一个对象,其中包含所有 null 或空值,这告诉我这个数据似乎是从未通过表格发送到我的控制器。

是否有更好的方法来完成此操作,或者如何将这些值从多个表单传递到我的控制器?如果我所做的已经完全错误,请提前道歉,我已经学习 ASP.NET Core MVC 几天了。

注意事项

我想要实现的是,用户可以在同一视图中输入属于同一模型的多个值,因为每个表单虽然相同,但都试图更新同一模型中的不同记录或列,或者table,所以当表单的提交发送到控制器时,视图不会改变,只有数据库中的记录随着视图中的每次提交而更新。如果有更好的方法或正确的方法来做到这一点,我愿意改变逻辑,因为正如我提到的,我使用框架的时间很少。

解释了问题和我的目标,我将更详细地解释提到的流程和代码:

  1. 从我的控制器的 Mechanical 方法中,我 return 对象列表到它们相应的视图,它们由 DataBaseContext:

     // CONTROLLER() that passes an enumerable list of Objects to View Mechanical.cshtml
     public IActionResult Mechanical()
     {
         IEnumerable<Result> objList = _db.Results;
         return View(objList);
     }
    
  2. Mechanical() 视图中,我得到了这个对象列表并通过 forEach() 循环对其进行迭代,其中我为每个对象创建了一个指向相同的控制器方法称为 Update(),我在其中获取 null 和空对象的值(这是我的问题):

// VIEW
@model IEnumerable<FatForm.Models.Result>

@if (Model.Count() > 0)
{
    @foreach(var result in Model)
    {
        <form method="post" asp-action="Update">
            <input asp-for="@result.Id" hidden />
            <input asp-for="@result.Type" hidden />
            <input asp-for="@result.FatId" hidden />
            <div class="border p-3">
                <div class="form-group row">
                    <h2 class="text-black-50 pl-3">Edit Result</h2>
                </div>
                <div class="row">
                    <div class="col-12">
                        <div class="form-group row">
                            <div class="col-3">
                                <label asp-for="@result.Section"></label>
                            </div>
                            <div class="col-3">
                                <label asp-for="@result.Procedure"></label>
                            </div>
                            <div class="col-3">
                                <label asp-for="@result.ResultDescription"></label>
                            </div>
                            <div class="col-3">
                                <label asp-for="@result.Passed"></label>
                            </div>
                        </div>
                        <div class="form-group row">
                            <div class="col-3">
                                <input asp-for="@result.Section" class="form-control" />
                            </div>
                            <div class="col-3">
                                <input asp-for="@result.Procedure" class="form-control" />
                            </div>
                            <div class="col-3">
                                <input asp-for="@result.ResultDescription" class="form-control" />
                                <span asp-validation-for="@result.ResultDescription" class="text-danger"></span>
                            </div>
                            <div class="col-3">
                                <input asp-for="@result.Passed" class="form-control" />
                                <span asp-validation-for="@result.Passed" class="text-danger"></span>
                            </div>
                        </div>
                        <div class="form-group row">
                            <div class="col-8 offset-2 row">
                                <div class="col">
                                    <input type="submit" class="btn btn-info w-75" value="Save" />
                                </div>
                            </div>
                        </div>

                    </div>
                </div>
            </div>
        </form>        
    }
}
else
{
    <p>No results created yet</p>
}

@section Scripts{
    @{
        <partial name="_ValidationScriptsPartial" />
    }
}
  1. 我应该将表单值发送到以下 Update() 控制器方法,在该方法中我将所有对象值设为空:

     // POST Update
     [HttpPost]
     [ValidateAntiForgeryToken]
     public IActionResult Update(Result obj)
     {
         if (ModelState.IsValid)
         {
             _db.Results.Update(obj);
             _db.SaveChanges();
             //return RedirectToAction("Index");
         }
    
         return View(obj);
     }
    

正如我在开头所解释的,我希望能帮助我指出我做错了什么或我应该以什么方式做错。预先感谢您的帮助。

这里需要在你的action方法参数中添加FromBody属性

public IActionResult Update([FromBody]Result obj)
{
   .....
}

模型绑定在源中查找名称模式 prefix.property_name。如果没有找到,它只查找 property_name 而没有 prefix.In 你的代码,asp-for 标签助手将生成如下名称:result.propertyName。它无法与后端匹配模型。您需要使用 [Bind(Prefix ="result")] 指定前缀:

[HttpPost]
[ValidateAntiForgeryToken]

public IActionResult Update([Bind(Prefix ="result")]Result obj)
{
    //do your stuff...
}

至于在操作中接收 IEnumerable 参数,首先您需要更改剃刀视图以将表单移到 foreach 循环之外,然后您需要将 asp-for 标签助手属性更改为 @Model.ToList()[index].PropertyName:

@model IEnumerable<Result>

@if (Model.Count() > 0)
{
    <form method="post" asp-action="Update">
        @for (int i = 0; i < Model.Count(); i++)
        {
            <input asp-for="@Model.ToList()[i].Id" hidden />
            <input asp-for="@Model.ToList()[i].Type" hidden />
            <input asp-for="@Model.ToList()[i].FatId" hidden />
            <div class="border p-3">
                <div class="form-group row">
                    <h2 class="text-black-50 pl-3">Edit Result</h2>
                </div>
                <div class="row">
                    <div class="col-12">
                        <div class="form-group row">
                            <div class="col-3">
                                <label asp-for="@Model.ToList()[i].Section"></label>
                            </div>
                            <div class="col-3">
                                <label asp-for="@Model.ToList()[i].Procedure"></label>
                            </div>
                            <div class="col-3">
                                <label asp-for="@Model.ToList()[i].ResultDescription"></label>
                            </div>
                            <div class="col-3">
                                <label asp-for="@Model.ToList()[i].Passed"></label>
                            </div>
                        </div>
                        <div class="form-group row">
                            <div class="col-3">
                                <input asp-for="@Model.ToList()[i].Section" class="form-control" />
                            </div>
                            <div class="col-3">
                                <input asp-for="@Model.ToList()[i].Procedure" class="form-control" />
                            </div>
                            <div class="col-3">
                                <input asp-for="@Model.ToList()[i].ResultDescription" class="form-control" />
                                <span asp-validation-for="@Model.ToList()[i].ResultDescription" class="text-danger"></span>
                            </div>
                            <div class="col-3">
                                <input asp-for="@Model.ToList()[i].Passed" class="form-control" />
                                <span asp-validation-for="@Model.ToList()[i].Passed" class="text-danger"></span>
                            </div>
                        </div>

                    </div>
                </div>
            </div>
        }
        <div class="form-group row">
            <div class="col-8 offset-2 row">
                <div class="col">
                    <input type="submit" class="btn btn-info w-75" value="Save" />
                </div>
            </div>
        </div>
    </form>
}
else
{
<p>No results created yet</p>
}

控制器:

[HttpPost]
[ValidateAntiForgeryToken]

public IActionResult Update(IEnumerable<Result> obj)
{
    return View("Mechanical", obj);
}

结果: