質問

I'm having trouble getting my head around how to extend the ValidationAttribute class when I want to compare across entities.

Example, I have the following 2 entities:

public class Incident
{
    public DateTime IncidentDate {get;set;}
    //other properties

    public virtual ICollection<Grievance> Grievances {get;set;}
}

public class Grievance
{
    public DateTime FileDate {get;set;}
    public DateTime? HearingDate {get;set;}
    //other properties

    public virtual Incident Incident {get;set;}  
}

I want to validate (server side, because this DLL is going to be used by multiple different projects) that the two DateTime of a Grievance properties are after the IncidentDate property for the corresponding Incident.

Ideally I'd want to write a HearingDateAttribute : ValidationAttribute type of class, but I'm not sure how to get the IncidentDate property to do a compare to for the IsValid override.

Edit

Ok this seems to work, but I'm not sure that it's best practice:

public sealed class HearingDateAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext context)
    {
        var hearingDate = (DateTime)value;
        var grievance = (Grievance)context.ObjectInstance;
        var incidentDate = grievance.Incident.IncidentDate;

        if (hearingDate > incidentDate.Value)
        {
            return ValidationResult.Success;
        }

        return null;
    }
}
役に立ちましたか?

解決

Data Annotations are good for triggering simple validation on individual properties but aren't good for model level validation. You should implement IValidatableObject on you entity. Something like this:

public class Grievance: IValidatebleObject
{

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) 
     { 
         if (FileDate < Incident.IncidentDate 
            ||(HearingDate.HasValue && HearingDate.Value < Incident.IncidentDate)) 
         { 
             yield return new ValidationResult 
              ("Dates invalid", 
               new[] { "FileDate", “HearingDate”, "Incident.IncidentDate" }); 
         } 
     }  
}

Reference:

http://msdn.microsoft.com/en-us/data/gg193959.aspx

他のヒント

You could write something like that for your Grievance class

public bool AreDatesBiggerThanIncident()
{
    return FileDate>Incident.IncidentDate && (HearingDate.HasValue? HearingDate.Value>Incident.IncidentDate : true);
}

I assumed you don't want your nullable datetime to break the check, but you could expand it, f.e:

public bool AreDatesBiggerThanIncident(bool returnFalseIfNullableEmpty=false)
{
    return FileDate>Incident.IncidentDate && (HearingDate.HasValue? HearingDate.Value>Incident.IncidentDate : !returnFalseIfNullableEmpty);
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top