使用流畅的验证不引人注意地验证复杂视图模型 - MVC3

时间:2014-02-03 16:33:21

标签: c# asp.net-mvc-3 fluentvalidation

我想弄清楚为什么我的FluentValidation不会不引人注意地验证我的一些View Model属性。

我通过NuGet安装了MVC3的FluentValidation包:

  Install-Package FluentValidation.MVC3

结果:

<package id="FluentValidation" version="5.0.0.1" targetFramework="net45" />
<package id="FluentValidation.MVC3" version="5.0.0.1" targetFramework="net45" />

未验证的属性是在我的View模型中声明的 Guitar 类对象的某些成员。 Guitar.ProductionYear属性获取不显眼的验证代码,但吉他对象的其他2个属性不是。

public Guitar Guitar1 { get; set; }
public Guitar Guitar2 { get; set; }
public Guitar Guitar3 { get; set; }

我阅读了FluentValidation文档,现在特别关注limitations regarding FluentValidation's client-side validation of lists,但这不是一个列表,所以我希望有人可以看到错误和/或提供一些建议。

我也尝试使用自定义吉他对象验证器,但仍然得到相同的结果

观察

  • 正在生成客户端验证并触发属性FirstName,LasteName,Phone和Email

  • 我注意到当这些对象没有被用户填写时,ModelState对这些对象无效,但我不知道为什么没有生成客户端验证并随后触发。
  • < BR />

  • Guitar 对象的生成表单HTML缺少不显眼的验证属性。 FirstName,LastName,Email和Phone等其他属性正在验证
  • 示例

        <!-- Unobtrusive JS generated-->
            <input type="text" value="" name="FirstName" id="FirstName" data-val-required="'First Name' must not be empty." data-val="true" class="input-validation-error">
            <div class="messageBottom"> 
                    <span data-valmsg-replace="true" data-valmsg-for="FirstName" class="field-validation-error"><span for="FirstName" generated="true" class="">'First Name' must not be empty.</span>
       </span>
     </div>
    
        <!-- Unobtrusive JS Partially generated for Guitar object-->
       <input type="text" value="" name="Guitar.Make" id="Guitar_Make" placeholder="Make">
            <div class="messageBottom">
            <span data-valmsg-replace="true" data-valmsg-for="Guitar1.Make" class="field-validation-valid"></span>
            </div>
    
            <input type="text" value="" name="Guitar1.Model" id="Guitar1_Model" placeholder="Model">
            <div class="messageBottom">
                <span data-valmsg-replace="true" data-valmsg-for="Guitar1.Model" class="field-validation-valid"></span>
            </div>
    
            <input type="text" value="" name="Guitar1.ProductionYear" id="Guitar1_ProductionYear" data-val-number="The field ProductionYear must be a number." data-val="true" placeholder="Production Year" class="valid">
            <div class="messageBottom">
            <span data-valmsg-replace="true" data-valmsg-for="Guitar1.ProductionYear" class="field-validation-valid">
            </span>
            </div>
    

    由于

    的Global.asax.cs

    FluentValidationModelValidatorProvider.Configure();
    

    视图模型

    [FluentValidation.Attributes.Validator(typeof(CustomerViewModelValidator))]
    public class CustomerViewModel
    {
        [Display(Name = "First Name")]
        public string FirstName { get; set; }
    
        [Display(Name = "Last Name")]
        public string LastName { get; set; }
    
        [Display(Name = "Phone")]
        public string Phone { get; set; }
    
        [Display(Name = "Email")]
        public string EmailAddress { get; set; }
    
        [Display(Name = "Guitar 1")]
        public Guitar Guitar1 { get; set; }
    
        [Display(Name = "Guitar 2")]
        public Guitar Guitar2 { get; set; }
    
        [Display(Name = "Guitar 3")]
        public Guitar Guitar3 { get; set; }
    }
    

    自定义吉他对象验证器

    public class GuitarValidator : AbstractValidator<Guitar>
    {
        public GuitarValidator()
        {
            RuleFor(x => x.Make).NotEmpty();
            RuleFor(x => x.Model).NotEmpty();
            RuleFor(x => x.ProductionYear).NotEmpty();
        }
    }
    

    查看模型验证程序

    public class CustomerViewModelValidator : AbstractValidator<CustomerViewModel>
    {
        public CustomerViewModelValidator()
        {
            RuleFor(x => x.FirstName).NotNull();
            RuleFor(x => x.LastName).NotNull();
            RuleFor(x => x.Phone).NotNull();
            RuleFor(x => x.EmailAddress).NotNull();
    
            //1st Guitar Object is Required
            RuleFor(x => x.Guitar).SetValidator(new GuitarValidator());
    
    
    
        }
    }
    

    视图

    <!-- Guitar Object #1 -->
         <div id="cosponsorsTemplate_1">
                <div class="formColumn1">@Html.LabelFor(x=>x.Guitar1)</div>
                <div class="formColumn2">@Html.TextBoxFor(x => x.Guitar1.Make, new { Placeholder = "Make" })
                    <div class="messageBottom">@Html.ValidationMessageFor(x => x.Guitar1.Make)</div>
                </div>
                <div class="formColumn3">@Html.TextBoxFor(x => x.Guitar1.Model, new { Placeholder = "Model" })
                    <div class="messageBottom">@Html.ValidationMessageFor(x => x.Guitar1.Model)</div>
                </div>
                <div class="formColumn4">@Html.TextBoxFor(x =>x.Guitar1.ProductionYear, new { Placeholder = "Production Year" })
                    <div class="messageBottom">@Html.ValidationMessageFor(x => x.Guitar1.ProductionYear)</div>
                    <a class="icon delete" data-delete-id="1">Delete</a>
                </div>
            </div>
    
       <!-- Guitar Object #2 -->
            <div id="cosponsorsTemplate_2">
                <div class="formColumn1">@Html.LabelFor(x=>x.Guitar2)</div>
                <div class="formColumn2">@Html.TextBoxFor(x => x.Guitar2.Make, new { Placeholder = "Make" })
                    <div class="messageBottom">@Html.ValidationMessageFor(x => x.Guitar2.Make)</div>
                </div>
                <div class="formColumn3">@Html.TextBoxFor(x => x.Guitar2.Model, new { Placeholder = "Model" })
                    <div class="messageBottom">@Html.ValidationMessageFor(x => x.Guitar2.Model)</div>
                </div>
                <div class="formColumn4">@Html.TextBoxFor(x => x.Guitar2.ProductionYear, new { Placeholder = "Production Year" })
                    <div class="messageBottom">@Html.ValidationMessageFor(x => x.Guitar2.ProductionYear)</div>
                    <a class="icon delete" data-delete-id="2">Delete</a>
                </div>
            </div>
    
        <!-- Guitar Object #3 -->
            <div id="cosponsorsTemplate_3">
                <div class="formColumn1">@Html.LabelFor(x=>x.Guitar3)</div>
                <div class="formColumn2">@Html.TextBoxFor(x => x.Guitar3.Make, new { Placeholder = "Make" })
                    <div class="messageBottom">@Html.ValidationMessageFor(x => x.Guitar3.Make)</div>
                </div>
                <div class="formColumn3">@Html.TextBoxFor(x => x.Guitar3.Model, new { Placeholder = "Model" })
                    <div class="messageBottom">@Html.ValidationMessageFor(x => x.Guitar3.Model)</div>
                </div>
                <div class="formColumn4">@Html.TextBoxFor(x => x.Guitar3.ProductionYear, new { Placeholder = "Production Year" })
                    <div class="messageBottom">@Html.ValidationMessageFor(x => x.Guitar3.ProductionYear)</div>
                    <a class="icon delete" data-delete-id="3">Delete</a>
                </div>
            </div>
    

    2 个答案:

    答案 0 :(得分:2)

    文档说明复杂的图形应该使用专门的验证器。您可以这样使用它:

    public class Customer {
      public string Name { get; set; }
      public Address Address { get; set; }
    }
    
    public class Address {
     public string Line1 { get; set; }
     public string Line2 { get; set; }
     public string Town { get; set; }
     public string County { get; set; }
     public string Postcode { get; set; }
    }
    
    public class AddressValidator : AbstractValidator<Address> {
      public AddressValidator() {
        RuleFor(address => address.Postcode).NotNull();
        //etc
      }
    }
    
    public class CustomerValidator : AbstractValidator<Customer> {
      public CustomerValidator() {
        RuleFor(customer => customer.Name).NotNull();
        RuleFor(customer => customer.Address).SetValidator(new AddressValidator())
      }
    

    }

    自: 重复使用复杂属性的验证器

    http://fluentvalidation.codeplex.com/wikipage?title=CreatingAValidator&referringTitle=Documentation

    对于您的用例,您将为聚合对象创建Guitar Validator和模型验证器。我记得有一个朋友遇到类似的问题,因为验证器不知道如何在没有中间验证器的情况下遍历对象图。

    答案 1 :(得分:0)

    我想出了这个问题。

    吉他课

    public class Guitar
    {
        public string Model { get; set; }
        public int? ProductionYear { get; set; } 
        public string Make { get; set; }
    }
    

    需要验证器类型装饰器

     [Validator(typeof(GuitarValidator))]
    



    <强>正确

        [Validator(typeof(GuitarValidator))]
        public class Guitar
        {
            public string Model { get; set; }
            public int? ProductionYear { get; set; } 
            public string Make { get; set; }
        }