ASP.NET MVC 保存列表<T> 到数据库

ASP.NET MVC Save List<T> to database

我在将列表项保存到数据库时遇到问题。当要保存一个字段时(在 HTTP POST Create 中),某些列表属性不必保存,因此我允许 nullabe 用于此类。但是,我从表单中检索并保存了一个字段。由于 classes 很复杂,我将在此处限制 post 的代码(我将使用一个字段,因为生成的异常是相同的)。

StringValues 是几个 List 字段继承自的 Class,例如本例中的 TestPlanChecklist。

public class TestPlanChecklist:StringValues
{
}

public class StringValues
{
    [Key]
    public int id { get; set; }

    public int ChangeRequestsID { get; set; }
    public string Value { get; set; }

    public ChangeRequests ChangeRequests { get; set; }
}

我模型的一部分class

    public class ChangeRequests
{

    [Required]
    public List<TestPlanChecklist> TestPlanChecklist { get; set; }

    [Required]
    public List<PostActivityChecklist> PostActivityChecklist { get; set; }

    [Required]
    public List<CMBApproval> CMBApproval { get; set; }

    [Required]
    public List<TechnicalFeasibility> TechnicalFeasibility { get; set; }

}

在我的创建视图中,这是为 TestPlanChecklist 字段呈现文本框的代码

<div class="form-group">
            @Html.LabelFor(model => model.TestPlanChecklist, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                <div>
                    <label class="numbers"> 1 </label>                        
                    <input type="text" class="TestPlanChecklist" name="TestPlan" />

                    <input type="button" value="+" class="roundButton" onclick="add('TestPlanChecklist', 'TestPlan')" />
                    <input type="button" value="-" class="roundButton" onclick="removeElement('TestPlan')" />
                </div>

                <div>
                    <label class="numbers"> 2 </label>
                    <input type="text" class="TestPlanChecklist" name="TestPlan" />
                </div>
                <div>  
                    <label class="numbers"> 3 </label>
                    <input type="text" class="TestPlanChecklist" name="TestPlan" />
                </div>

                @Html.ValidationMessageFor(model => model.TestPlanChecklist, "", new { @class = "text-danger" })
            </div>
        </div>

    </div>

和HttpPost创建方法

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "TestPlanChecklist,PostActivityChecklist,PostActivityChecklist,CMBApproval,TechnicalFeasibility")] ChangeRequests changeRequests,
      string[] TestPlan)
    {            
        changeRequests.TestPlanChecklist = new List<TestPlanChecklist>();


        foreach (var test in TestPlan)
            changeRequests.TestPlanChecklist.Add(new TestPlanChecklist { Value = test });

        //SendEmails(TechnicalFeasibility, User.Identity.Name, ChangeUrgency, Priority, DescriptionOfChange, Reason);

        //SendEmails(CMBApproval, User.Identity.Name, ChangeUrgency, Priority, DescriptionOfChange, Reason);


        if (ModelState.IsValid)
        {
            db.ChangeRequests.Add(changeRequests);
            db.SaveChanges();
            return RedirectToAction("List");
        }

        return View(changeRequests);
    }

请注意,我只使用一个字段来问这个问题,这就是为什么我删除了用于初始化其他列表字段的代码的原因。

ModelState.IsValid

returns 错误。我意识到所有 List 字段都有一个错误,它表明无法从 System.String 类型转换为特定的 class。这很有趣,因为我只分配了一个从表单中检索到的字段值,其余的都可以为空,这很有意义。

我哪里错了?

提前致谢。

您可以检查验证的错误。

var errores = new List<ModelError>();
foreach (ModelState modelState in ViewData.ModelState.Values)
{
    foreach (ModelError error in modelState.Errors)
    {
        errores.Add(error);
    }
}

ModelState.IsValid 检查验证规则,在您的案例中来自 DataAnnotations [Required] ChangeRequests ViewModel 中的属性。

如果您想使用此验证并使您的某些 List 属性可为空,您应该删除此属性。

您收到 ModelState 错误,因为 ChangeRequest 具有 [Required] 属性并由 Mvc 验证。我不清楚您为什么要使用该动作签名,但这是一种不好的方法。您应该直接依赖 ViewModels 而不是 Models

public ActionResult Create(ChangeRequestViewModel viewModel)
{
    if(ModelState.IsValid == false) return View(viewModel); 
    var changeRequest = new ChangeRequest();
    foreach(var testPlan in viewModel.TestPlans) {
         changeRequest.TestPlanChecklist.Add(new TestPlanChecklist { Value = testPlan }
    }
    // ...
}