Ivalidatable object

Custom validation attributes are convenient if you want to reuse validation code for multiple properties. They can even be used for type-level validation (which doesn’t make sense for the other validation attributes). But the DbContext also offers an alternative: the IValidatableObject interface, which can be implemented on your classes.

The IValidatableObject interface has a single method, Validate(), which takes a ValidationObject parameter and returns an IEnumerable<ValidationError> result:


Image

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)



Image

Public Function Validate(ByVal validationContext As ValidationContext)
      As IEnumerable(Of ValidationResult)
      Implements IValidatableObjectValidate


Within the Validate() method, you perform your tests and, if the object fails, add a ValidationResult to the response. In Visual Basic this is done by adding each result to a List(Of ValidationResult), as shown opposite, while in C# it’s customary to use the yield statement, as shown below:


Image

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
 MyClass obj = validationContext.ObjectInstance;
 if (property is not valid)
      yield return
      new ValidationResult("message", new string[] { "Property" });
 if (some other property is not valid)
   yield return
      new ValidationResult("message", new string[] {"Other Property"});
 ...
}



Image

Public Function Validate(ByVal validationContext As ValidationContext)
  As IEnumerable(Of ValidationResult)
  Implements IValidatableObject.Validate

 Dim results = New List(Of ValidationResult)
 Dim obj = validationContext.ObjectInstance

 If (property is not valid)
  result.Add(New ValidationResult("message", New String() {"Property"}))
 End If
 If (some other property is not valid)
  result.Add(New ValidationResult("message", New String() {"Other Property"}))
 End If
 ...

  Return result
End Function



Image Put On Your Thinking Hat

Ready to give it a try? Write a Validate() method for the RecipeIngredient class that checks that the Amount property is a positive number and only the IngredientName or the SourceId property can contain values, but not both.



Image Put On Your Thinking Hat

How’d you do?

Image

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
 RecipeIngredient ri = validationContext.ObjectInstance;

 if (ri.Amount < 0)
      yield return
      new ValidationResult("Amount must be positive", new string[] { "Amount" });
 if (ri.IngredientName != null && ri.SourceId != null)
  yield return
    new ValidationResult("You cannot enter both name and source",
      new string[] {"IngredientName", "SourceId"});
 ...
}


Image

Public Function Validate(validationContext As ValidationContest) _
   As IEnumerable(Of ValidationResult)

   Dim ri As RecipeIngredient = validationContext.ObjectInstance
   Dim results = New List(Of ValidationResult)


   If ri.Amount < 0 Then
       results.Add(New _
          ValidationResult("Amount must be positive", New String() { "Amount" }))
   End If
   If ri.IngredientName IsNot Nothing AndAlso ri.SourceId IsNot Nothing Then
     results.Add(New _
         ValidationResult("You cannot enter both name and source", _
         New String() {"IngredientName", "SourceId"}))
   End If
 ...
 return results
End Function



Image Take A Break

And that’s it for the DbContext validations and the chapter. Why don’t you take a break before you complete the Review and we move on to the final project?



..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset