Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 基于父模型中其他字段的字段声明性条件验证_.net_Asp.net Mvc_Data Annotations_Asp.net Mvc Validation_System.componentmodel - Fatal编程技术网

.net 基于父模型中其他字段的字段声明性条件验证

.net 基于父模型中其他字段的字段声明性条件验证,.net,asp.net-mvc,data-annotations,asp.net-mvc-validation,system.componentmodel,.net,Asp.net Mvc,Data Annotations,Asp.net Mvc Validation,System.componentmodel,我有两种不同的类型: public class Person { public string Name { get; set; } public bool IsActive { get; set; } public Contact ContactDetails { get; set; } } public class Contact { [RequiredIfActive] public string Email { get; set; } } 我需

我有两种不同的类型:

public class Person
{
    public string Name { get; set; }
    public bool IsActive { get; set; }

    public Contact ContactDetails { get; set; }
}

public class Contact
{
    [RequiredIfActive]
    public string Email { get; set; }
}
我需要的是根据父模型字段的某些状态执行内部模型字段的条件声明性验证-在这个特定示例中,如果启用了
IsActive
选项,则必须填写
Email

我不想重新组织这些模型的分类,同时我需要使用基于属性的方法。似乎从属性中无法访问父模型的验证上下文。如何到达或注射

public class RequiredIfActiveAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, 
                                                ValidationContext validationContext)
    {
        /* validationContext.ObjectInstance gives access to the current 
           Contact type, but is there any way of accessing Person type? */
编辑:


我知道如何使用Fluent验证实现条件验证,但我不是在问这个问题(我不需要Fluent验证方面的支持)。但是,我想知道是否存在从内部访问父模型的任何方法
System.ComponentModel.DataAnnotations.ValidationAttribute

我的建议

转到工具=>Library Package Manager=>Package Manager控制台并安装Fluent验证

行动方法

[HttpGet]
public ActionResult Index()
{
    var model = new Person
    {
        Name = "PKKG",
        IsActive = true,
        ContactDetails = new Contact { Email = "PKKG@stackoverflow.com" }
    };
    return View(model);
}
[HttpPost]
public ActionResult Index(Person p)
{
    return View(p);
}
[Validator(typeof(MyPersonModelValidator))]
public class Person
{
    [Display(Name = "Name")]
    public string Name { get; set; }

    [Display(Name = "IsActive")]
    public bool IsActive { get; set; }

    public Contact ContactDetails { get; set; }
}

public class Contact
{
    [Display(Name = "Email")]
    public string Email { get; set; }
}
流畅的验证规则

public class MyPersonModelValidator : AbstractValidator<Person>
{
    public MyPersonModelValidator()
    {
        RuleFor(x => x.ContactDetails.Email)
            .EmailAddress()
            .WithMessage("Please enter valid email address")
            .NotNull().When(i => i.IsActive)
            .WithMessage("Please enter email");
    }
}
查看

@{
    var actionURL = Url.Action("Action", "Controller", new { area = "AreaName" },
                           Request.Url.Scheme);
}
@using (Html.BeginForm("Action", "Controller", FormMethod.Post, 
                                                    new { @action = actionURL }))
    @Html.EditorFor(i => i.Name);
    @Html.ValidationMessageFor(i => i.Name);

    @Html.EditorFor(i => i.IsActive);
    @Html.ValidationMessageFor(i => i.IsActive);

    @Html.EditorFor(i => i.ContactDetails.Email);
    @Html.ValidationMessageFor(i => i.ContactDetails.Email);
    <button type="submit">
        OK</button>
}
@{
var actionURL=Url.Action(“Action”,“Controller”,new{area=“AreaName”},
Request.Url.Scheme);
}
@使用(Html.BeginForm(“Action”、“Controller”、FormMethod.Post、,
新的{@action=actionURL})
@EditorFor(i=>i.Name);
@ValidationMessageFor(i=>i.Name);
@EditorFor(i=>i.IsActive);
@ValidationMessageFor(i=>i.IsActive);
@EditorFor(i=>i.ContactDetails.Email);
@Html.ValidationMessageFor(i=>i.ContactDetails.Email);
好啊
}

这不能通过Contact.Email上的属性来完成,因为正如您已经发现的,运行时不能从属性上下文中使用父
人员。要通过验证属性启用此方案,该属性必须修饰
Person
类。对于
System.ComponentModel.DataAnnotations
属性,您有两种选择:或一个自定义的
ValidationAttribute
子类,该子类的目标是
Person

下面是使用
CustomValidationAttribute
时这两个类的外观:

[CustomValidation(typeof(Person), "ValidateContactEmail")]
public class Person
{
    public string Name { get; set; }
    public bool IsActive { get; set; }
    public Contact ContactDetails { get; set; }

    public static ValidationResult ValidateContactEmail(Person person, ValidationContext context)
    {
        var result = ValidationResult.Success;
        if (person.IsActive)
        {
            if ((person.ContactDetails == null) || string.IsNullOrEmpty(person.ContactDetails.Email))
            {
                result = new ValidationResult("An e-mail address must be provided for an active person.", new string[] { "ContactDetails.Email" });
            }
        }

        return result;
    }
}

public class Contact
{
    public string Email { get; set; }
}

我非常感谢您的努力,但是,正如问题本身(以及现在已删除的注释)中所明确说明的那样,在我的具体案例中,Fluent Validation并不是我想要的解决方案。Fluent Validation比默认的MVC Validation好得多。在使用默认mvc验证4年后,我在3个月前切换到了fluent验证。@Softlion:这个问题主要是我的好奇心,我不想验证任何东西。在这种特殊的环境下,我也不想简化我的生活。这就是为什么Fluent验证建议不会针对我的任何级别的问题。如果可能的话,请您抽出一些时间给出一个代码示例以了解更多细节,好吗?我已经为CustomValidationAttribute添加了一个示例。自定义ValidationAttribute子类也需要一个吗?