【问题标题】:ModelState validation not working with DropDownList and nested objectsModelState 验证不适用于 DropDownList 和嵌套对象
【发布时间】:2013-02-22 14:55:12
【问题描述】:

在我们的应用程序中,我们有一个域层,其中包含带有用于验证的 DataAnnotations 的类。

我们在 ASP.NET MVC ui 层的模型中使用这些类。

例如:

领域层:

public class Company
{
    public int Id { get; set; }

    [Required]
    [StringLength(50)]
    public string Description { get; set; }

    // ... some model logic abreviated
}

public class Supplier 
{
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }

    [Required]
    public Company Company { get; set; }

    // ... some model logic abreviated
}

在我们的 ASP.NET MVC 表示层中:

public class SupplierEditModel
{
    public Supplier Supplier { get; set; }
    public IEnumerable<Company> Company { get; set; }
    public int SelectedCompany { get; set; }

    // ... some model logic abreviated
}

在这种情况下,我们有一个包含公司 DropDownList 的页面。该列表是这样绑定的:

@Html.DropDownListFor(m => m.SelectedCompany, new SelectList(Model.Companies, "Id", "Description", Model.SelectedCompany))

我们的问题出在控制器的 POST 方法上,当我们检查 ModelState.IsValid 时,模型无效,因为 Supplier.Company 为空。然后我们可以使用 SelectedCompany 获取公司,但我们的问题是这意味着我们不能做这样的事情:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(SupplierEditModel model)
{
    if (ModelState.IsValid)
    {
        model.CreateSupplier(_supplierService);
        return RedirectToAction("Index");
    }

    return RedirectToAction("Create");
}

我们想在创建供应商之前使用验证。

【问题讨论】:

  • 您可以在检查IsValid之前从ModelState中删除CompanyModelState.Remove("Supplier.Company")
  • @Zabavsky 您应该将此作为答案提交,我会投票并接受它(取决于其他答案)。
  • 我将其发布为答案。

标签: asp.net-mvc asp.net-mvc-4 data-annotations


【解决方案1】:

我看到你有(至少)两个选择:

如果您的视图中不需要 Supplier.Company,您可以展平您的视图模型并省略它。

public class SupplierEditModel
{
    public int SupplierId { get; set; }
    public string Name { get; set; }
    public Company Company { get; set; }
    public IEnumerable<Company> Company { get; set; }
    public int SelectedCompany { get; set; }

    // ... some model logic abreviated
}

(注意:您的数据注释应该在视图模型上,而不是域模型上。)

您可以在检查IsValid 属性之前清除ModelState 错误

ModelState.Remove(string key, ModelState);

这里的最佳做法可能是使用扁平模型,原因有两个。第一,通常只发送视图需要的内容,仅此而已。如果视图没有对 Supplier.Company 做任何事情,那么它不应该是模型的一部分。第二,使用 ModelState.Remove 方法虽然有效,但可能被某些人认为有点笨拙。您可能会在代码审查中受到一些破坏;)

【讨论】:

    【解决方案2】:

    您可以在检查IsValid 之前从ModelState 中删除CompanyModelState.Remove("Supplier.Company")

    【讨论】:

      【解决方案3】:
         public class OrderViewModel
          {
              [Display(Name = "Customer")]
              [Required(ErrorMessage = "Please select customer.", AllowEmptyStrings = false)]
              public string CustomerName { get; set; }
      
              public IEnumerable<CustomerViewModel> Customers { get; set; }
          }
      
      
         public class CustomerViewModel
          {
              public string CustomerID { get; set; }
              public string CompanyName { get; set; }
          }
      
           <div class="form-group">
              @Html.LabelFor(m => m.CustomerName, new { @class = "col-md-2 control-label" })
              <div class="col-md-10">
                  @Html.DropDownListFor(m => m.CustomerName, new SelectList(Model.Customers, "CustomerId", "CompanyName"), "- Please Select -", new { @class = "form-control" })
                  @Html.ValidationMessageFor(model => model.CustomerName, null, new { @class = "text-danger" })
              </div>
          </div>
      

      【讨论】:

      • 最好解释答案,然后只给出代码。
      猜你喜欢
      • 1970-01-01
      • 2020-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-10
      • 2019-05-16
      • 1970-01-01
      • 2014-03-17
      相关资源
      最近更新 更多