Using Silvlight, custom EF POCO, custom Validation - leveraging Metadata and its not working in Silverlight 4
I am using metadata validation for both my MVC and SIlverlight together. However, the classes for silverlight arent working, and I think its due to the MetadataTypeAttribute that doesn't exist for silverlight 4. This seems to be the only thing holding by this part of my project... I am trying to avoid doing everthing custom as I dont like to reinvent the wheel, however the validation classes dont seem to render expected results..:
Here is my solution for CLR:
var metadataAttrib = this.GetType().GetCustomAttributes(typeof(MetadataTypeAttribute), true).OfType<MetadataTypeAttribute>().FirstOrDefault();
var buddyClassOrModelClass = metadataAttrib != null ? metadataAttrib.MetadataClassType : this.GetType();
var buddyClassProperties = TypeDescriptor.GetProperties(buddyClassOrModelClass).Cast<PropertyDescriptor>();
var modelClassProperties = TypeDescriptor.GetProperties(this.GetType()).Cast<PropertyDescriptor>();
var brokenRules = from buddyProp in buddyClassProperties
join modelProp in modelClassProperties on buddyProp.Name equals modelProp.Name
from attribute in buddyProp.Attributes.OfType<ValidationAttribute>()
where !attribute.IsValid(modelProp.GetValue(this))
select new BrokenRule() { FieldName = buddyProp.Name, ErrorMessage = attribute.FormatErrorMessage("") };
brokenRulesList = brokenRules.ToList();
... And here is the code for Silverlight
var metadataAttrib = this.GetType().GetCustomAttributes(typeof(MetadataTypeAttribute), true).OfType<MetadataTypeAttribute>().FirstOrDefault();
var buddyClassOrModelClass = metadataAttrib != null ? metadataAttrib.MetadataClassType : this.GetType();
var buddyClassProperties = buddyClassOrModelClass.GetType().GetProperties();
var modelClassProperties = this.GetType().GetProperties();
var validationContext = new ValidationContext(this, null, null);
var validationResults = from buddyProp in buddyClassProperties
join modelProp in modelClassProperties on buddyProp.Name equals modelProp.Name
from attribute in buddyProp.GetCustomAttributes(true).OfType<ValidationAttribute>().Cast<ValidationAttribute>()
where buddyProp.Name == modelProp.Name
select attribute.GetValidationResult(modelProp, validationContext);
brokenRulesList = new List<BrokenRule>();
foreach (ValidationResult vr in validationResults)
{
foreach (string memberName in vr.MemberNames)
brokenRulesList.Add(new BrokenRule() { FieldName = memberName, ErrorMessage = vr.ErrorMessage });
}
... However, the silverlight code is not working.. Here is the test case...
[MetadataType(typeof(UserMetadata))]
public partial class User
{
public partial class UserMetadata
{
[Required(ErrorMessageResourceName = "UserIDValidationMessage", ErrorMessageResourceType = typeof(AppResources))]
public System.Guid ID { get; set; }
public Nullable<int> UID { get; set; }
[Display(Name="UserUsernameLabel", Description="Username", ResourceType=typeof(AppResources))]
[Required(ErrorMessageResourceName = "UserUsernameValidationMessage", ErrorMessageResourceType = typeof(AppResources))]
[StringLength(70, ErrorMessageResourceName="UserUsernameValidationMessage", ErrorMessageResourceType = typeof(AppResources))]
public string Username { get; set; }
[Display(Name="UserFirstNameLabel", Description="First Name", ResourceType=typeof(AppResources))]
[StringLength(90, ErrorMessageResourceName="UserFirstNameValidationMessage", ErrorMessageResourceType = typeof(AppResources))]
public string FirstName { get; set; }
}
I made a class for silverlight which lets it compile, but its not working - as expected..
using System;
using System.Reflection;
namespace System.ComponentModel.DataAnnotations
开发者_JAVA百科{
public class MetadataTypeAttribute : Attribute
{
public MetadataTypeAttribute(Type t)
{
MetadataClassType = t;
}
public Type MetadataClassType
{
get;
set;
}
}
}
Does anyone know how to simply leverage to metadata classes for silverlight? Why the metadatatypeattribute isn't there I dont know. Any suggestions?
If you want to use Validation attributes in Silverlight, you must do one of three things:
Use a toolkit DataGrid to display the data - this automatically validates your properties (I have seen other controls do this, such as Telerik's RadGridView)
Validate manually in the property setter and throw a ValidationException if the value is not valid. You must also set ValidatesOnExceptions and NotifyOnValidationError to true in your Bindings.
Implement INotifyDataErrorInfo or IDataError in your model and set validation errors through the methods in those interfaces.
Option 3 is the recommended approach and looks to be most suitable for your purposes.
Check out this link for more info msdn.microsoft.com/en-us/library/dd901590(v=vs.95).aspx
Finally, the INotifyDataErrorInfo interface can be a little daunting - there is lots of plumbing to sort out before you can use it. However, this post from Jeremy Likness might help a little. Note that you do not have to validate in the setter as in the example.
精彩评论