This question is locked. New answers and comments are not allowed.
I've been looking at DataAnnotations in an MVC project which uses OpenAccess.
What's the best way to extend the generated classes to include the additional UI agnostic validation that DataAnnotations provide?
Something like this is the first thing off the top of my head as I've used a similar approach elsewhere
using System; |
using System.Collections.Generic; |
using System.ComponentModel; |
using System.ComponentModel.DataAnnotations; |
using System.Linq; |
[MetadataType(typeof(CountryMetaData))] |
public partial class Country : IValidatedModel |
{ |
} |
public class CountryMetaData |
{ |
[Required(ErrorMessage = "CountryId is required")] |
[Range(1, Int32.MaxValue, ErrorMessage = "CountryId must be a positive integer")] |
public int CountryId |
{ |
get; |
set; |
} |
} |
/// <summary> |
/// A basic class for encapsulating a validation error message |
/// </summary> |
public class ValidationMessage |
{ |
public string PropertyName { get; set; } |
public string ErrorMessage { get; set; } |
} |
/// <summary> |
/// This is just provided as a means for extension methods |
/// </summary> |
public interface IValidatedModel |
{ |
} |
public static class ExtensionMethods |
{ |
/// <summary> |
/// Get all validation errors for the given instance |
/// </summary> |
public static IEnumerable<ValidationMessage> GetErrors(this IValidatedModel instance) |
{ |
var metadataAttrib = instance.GetType().GetCustomAttributes(typeof(MetadataTypeAttribute), true).OfType<MetadataTypeAttribute>().FirstOrDefault(); |
var typeObject = metadataAttrib != null ? metadataAttrib.MetadataClassType : instance.GetType(); |
var typeProperties = TypeDescriptor.GetProperties(typeObject).Cast<PropertyDescriptor>(); |
var classProperties = TypeDescriptor.GetProperties(instance.GetType()).Cast<PropertyDescriptor>(); |
return from property in typeProperties |
join modelProp in classProperties on property.Name equals modelProp.Name |
from attribute in property.Attributes.OfType<ValidationAttribute>() |
where !attribute.IsValid(modelProp.GetValue(instance)) |
select new ValidationMessage { PropertyName = property.Name, ErrorMessage = attribute.FormatErrorMessage(string.Empty) }; |
} |
/// <summary> |
/// Are there any validation errors? |
/// </summary> |
public static bool IsValid(this IValidatedModel model) |
{ |
return !model.GetErrors().Any(); |
} |
} |
This approach loses the benefit of reverse mapping the data source though. Is there a better way to bake in the validation by extending OpenAccess somehow and is there any plans to support dataannotations in the openaccess roadmap?
Thanks in advance
Mac.