MVC .NET [必需]父模型上的DataAnnotations导致子模型中的ModelState无效

时间:2012-04-19 09:51:04

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

我想在保存子模型(VehicleModel)时“关闭”父模型(VehicleManufacturer)的某个属性上的必填字段验证,即:

public class VehicleManufacturer
{
    public virtual Guid Id { get; set; }

    [Required]
    [StringLength(50, MinimumLength = 1)]
    public virtual string Name { get; set; }
}

public class VehicleModel
{
    public virtual Guid Id { get; set; }

    [Required]
    [StringLength(50, MinimumLength = 1)]
    public virtual string Name { get; set; }

    public virtual VehicleManufacturer Manufacturer { get; set; }
}

所以,当我保存一个新模型时,我关心的是它的Name和ManufacturerID,它将从下拉列表中选择,但是,因为ManufacturerName在其实体中标记为[Required],保存新的VehicleModel时,我的ModelState无效,因为ManufacturerName为null:(

我想知道什么是最好的方法以及如何做到这一点。 我可以想到几个解决方案,但似乎没有一个正确的方法:

  • 在ModelState检查之前设置“默认”ManufacturerName值,即 “ - ”只是为了满足DataAnnotation
  • 填充两个ManufacturerName 和我的VehicleModelView中的ManufacturerId - 如果你的父母不好 model有一堆必需的字段,你真的不需要在a中使用 儿童模特
  • 关闭子模型的[必需]验证(不确定 怎么样?)
你觉得怎么样?

5 个答案:

答案 0 :(得分:2)

最简单的方法是为您不想显示的必需属性设置隐藏字段。

答案 1 :(得分:1)

一种可能的解决方案是将外键列添加到VehicleManufacturer(VehicleManufacturerId)到VehicleModel,并在视图中使用该列。

答案 2 :(得分:0)

IValidatableObject界面用于自定义模型验证。

例如:

public class VehicleModel : IValidatableObject
{
    public virtual Guid Id { get; set; }

    [StringLength(50, MinimumLength = 1)]
    public virtual string Name { get; set; }

    public virtual VehicleManufacturer Manufacturer { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if(string.IsNullOrWhiteSpace(Name))
        {
           yield return new ValidationResult("Name is required")
        } 
    }
}

然后在您的控制器中致电ModelState.IsValid

答案 3 :(得分:0)

我最终做的是使用ParentWithExtendedValidation子类化父模型:Parent

在ParentWithExtendedValidation中,标记了所有[必填]字段。

当我想专门编辑父级时,我使用了类型ParentWithExtendedValidation - 因为它是Parent的子类,一旦它通过了模型验证,你就可以将它强制转换回父级并将其传递给DAL而不会出现任何问题。

当您在关系中使用它时,例如编辑引用它的子项,您可以使用常规的Parent类。

希望这有帮助

EG我有一个Person类 - 拥有我所有正常的虚拟属性,只需要ID(进行验证,选择on-person; ID仍然正常工作)

和一个PersonEV类

public class PersonWithExtendedValidation : Person
{

    [Required]
    public override string FullName { get; set; }
    [Required]
    public override string FirstName { get; set; }
    [Required]
    public override string LastName { get; set; }        
    [Required]
    public override string DomainName { get; set; }
    [Required]
    public override string WorkPhone { get; set; }
    [Required]
    public override string CellPhone { get; set; }
    [Required]
    public override string Email { get; set; }        
}

然后在你的View / Controller中使用例如PersonEV作为模型和参数。

检查ModelState.IsValid后,转回(Person)并传递到正常的任何存储库或等等

答案 4 :(得分:0)

确定。我看着这个,发现我的方法很浪费。

这看起来如何?

我创建了一个名为ExtendedValidationRequired的注释。

它有一个静态值,可以打开条件检查扩展值。

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]

public class ExtendedValidationRequiredAttribute : RequiredAttribute
{



    // Summary:
    //     Initializes a new instance of the System.ComponentModel.DataAnnotations.RequiredAttribute
    //     class.
    public ExtendedValidationRequiredAttribute()
    {

    }



    // Summary:
    //     Checks that the value of the required data field is not empty.
    //
    // Parameters:
    //   value:
    //     The data field value to validate.
    //
    // Returns:
    //     true if validation is successful; otherwise, false.
    //
    // Exceptions:
    //   System.ComponentModel.DataAnnotations.ValidationException:
    //     The data field value was null.
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (ExtendedValidation.IsExtendedValidationEnabled(validationContext.ObjectType))
        {

            return base.IsValid(value,validationContext);
        }
        else
        {
            return ValidationResult.Success;                
        }


    }




}

然后我用[ExtendedValidationRequired(typeof(MyClassName))]

标记我的有时需要(例如当我直接编辑该类时)字段

这也适用于其他类型的验证器。

我实际上继续创建了一组'有时开启'验证器,并将我的设置移到了一个单独的类: public static class ExtendedValidation     {         private static Dictionary extendedValidationExemptions = new Dictionary();

    /// <summary>
    /// Disable extended validation for a specific type
    /// </summary>
    /// <param name="type"></param>
    public static void DisableExtendedValidation(Type type)
    {
        extendedValidationExemptions[type] = true;
    }
    /// <summary>
    /// Clear any EV exemptions
    /// </summary>
    public static void Reset()
    {
        extendedValidationExemptions.Clear();
    }

    /// <summary>
    /// Check if a class should perform extended validation
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public static bool IsExtendedValidationEnabled(Type type)
    {
        if (extendedValidationExemptions.ContainsKey(type))
        {
            return false;
        }
        else
        {
            return true;
        }
    }
}

}

现在我只是在编辑子项时关闭ExtendedValidation。

E.G:编辑Child时,可以禁用ExtendedValidation(typeof(Parent))而不会妨碍。

编辑:嗯,我意识到这不起作用。 - 我可以确定我在validationProperty中查看的类吗?我想我总是可以传递父属性,但这是一个PITA