HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Validating individual properties and whole items

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
individualwholepropertiesvalidatingitemsand

Problem

I have a custom class I've written which allows me to validate individual properties of items, without firing validation errors on other properties. This allows me to individually validate what my users are editing without flinging up a lot of red mess on fields they haven't gotten to yet.

The validator uses reflection to get the properties to validate, this is so that I can trigger property validation in my view model in response to control updates on the view, and this lets me use databinding strings to identify the properties without needing any access to the model on the view-side. The validation rules are specified using data annotation attributes on the model.

The validation methods attempt to attach validation errors to the object being validated if possible (i.e. if it's a ComplexObject or Entity type) but also returns a collection of them to be processed manually.

For completeness, the validator also allows me to validate whole items as a helper, for use when submitting final copies of items.

```
using ComponentModelValidator = System.ComponentModel.DataAnnotations.Validator;

///
/// Uses data annotation attributes to validate whole items and individual properties
///
public class Validator
{
///
/// Validates properties on the provided item using validation attributes.
///
///
/// The validation errors are attached to the object if it is a ComplexObject or Entity.
///
/// The item to validate.
/// A collection of validation errors.
/// Thrown when item is null.
public ICollection ValidateItem(object item)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
if (item is Entity)
{
((Entity)item).ValidationErrors.Clear();
}
if (item is ComplexObject)
{
((ComplexObject)item).ValidationErrors.Clear();
}

var validationResults = new Collection();

ComponentModelValidator

Solution

ValidateItem

You are doing a lot of casts here. You should split this method into separate ones and call them like

public ICollection ValidateItem(object item)
{
    if (item == null)
    {
        throw new ArgumentNullException("item");
    }
    Entity entity = item as Entity;
    if (entity != null)
    {
        return ValidateEntity(entity);
    }
    return ValidateComplexObject(item as ComplexObject);
}


ValidateProperty

-
Instead of checking


if (propertyName.Equals(String.Empty))

you could check

if (propertyName.Length == 0)


but hey, there are edge cases

  • what should happen if propertyName is containing only whitespace characters ? So better use the good old String.IsNullOrWhiteSpace().



  • what would happen if the last character is a dot . (propertyName.Split('.').Last())



-
And again you are first checking if target is Entity before you cast it. Better to use the way I showed above.

GetRelativeProperty

-
prependPropertyName isn't really used, remove it.

-
this

var prop = i == dotIndices.Count - 1 ?  
               propertyName.Substring(dotIndices[i] + 1) :  
               propertyName.Substring(dotIndices[i] + 1, dotIndices[i + 1] - dotIndices[i] - 1);


The condition won't ever be true, because your loop has an ending condition of i

AddValidationErrorsToComplexObject

  • wouldn't targetAsComplexObject.ValidationErrors.Clear(); be enough for clearing the errors ?



AddValidationErrorsToEntity

  • same question like for AddValidationErrorsToComplexObject`

Code Snippets

public ICollection<ValidationResult> ValidateItem(object item)
{
    if (item == null)
    {
        throw new ArgumentNullException("item");
    }
    Entity entity = item as Entity;
    if (entity != null)
    {
        return ValidateEntity(entity);
    }
    return ValidateComplexObject(item as ComplexObject);
}
if (propertyName.Length == 0)
var prop = i == dotIndices.Count - 1 ?  
               propertyName.Substring(dotIndices[i] + 1) :  
               propertyName.Substring(dotIndices[i] + 1, dotIndices[i + 1] - dotIndices[i] - 1);

Context

StackExchange Code Review Q#78329, answer score: 2

Revisions (0)

No revisions yet.