Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to use DataAnnotations with Interfaces?

I want to use DataAnnotations to validate classes that implements some interfaces, and so I'm adding validation attributes to the interface, like this:

public interface IUser {     [Required]     string Name { get; set; }      [Display(Name = "Email Address")]     [Required]     string Email { get; set; } } 

It doesn't work when I try to use Validator.TryValidateObject.

Is there any way to make this instead of having to write a custom TryValidateObject method?

like image 753
Bruno Avatar asked May 07 '11 06:05

Bruno


People also ask

What is the use of using system ComponentModel DataAnnotations?

Data annotations (available as part of the System. ComponentModel. DataAnnotations namespace) are attributes that can be applied to classes or class members to specify the relationship between classes, describe how the data is to be displayed in the UI, and specify validation rules.

What are DataAnnotations in net core?

"Data Annotation provides attribute classes that are used to define metadata for ASP.NET MVC and ASP.NET data controls." Why would I use Data Annotation? There are 3 main areas where you may use it; two of them are related to your data presentation to your end user and one is to design your database.


2 Answers

I'm surprised no one mentioned MetadataTypeAttribute. But yes, this works.

[MetadataType(typeof(ICustomerMetaData))] public partial class Customer { }   public interface ICustomerMetaData {   // Apply RequiredAttribute   [Required(ErrorMessage = "Title is required.")]   string Title { get; } } 

As for using an Interface directly (using Customer: ICustomerMetaData):

The product team does not want to implement this feature, for two main reasons:

• Consistency with DataAnnotations.Validator

• Consistency with validation behavior in ASP.Net MVC

• Tricky scenario: a class implements two interfaces that have the same property, but with conflicting attributes on them. Which attribute would take precedence?

While MVC automatically registers the MetaData with the TypeDescriptor, you may have to manually add it yourself:

  using System;   using System.Collections.Generic;   using System.ComponentModel;   using System.ComponentModel.DataAnnotations;    public class Program   {      public static void Main()      {         var customer = new Customer();          TypeDescriptor.AddProviderTransparent(           new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Customer),              typeof(ICustomerMetaData)),              typeof(Customer));          var context = new ValidationContext(customer);         var validationResults = new List<ValidationResult>();          var isValid = Validator.TryValidateObject(           customer, context, validationResults, true);         Console.WriteLine($"is Valid = {isValid}");          customer.Title = "I has Title";          isValid = Validator.TryValidateObject(           customer, context, validationResults, true);         Console.WriteLine($"is Valid = {isValid}");           Console.ReadKey();      }       [MetadataType(typeof(ICustomerMetaData))]      public partial class Customer      {         public string Title { get; set;  }      }       public interface ICustomerMetaData      {         // Apply RequiredAttribute         [Required(ErrorMessage = "Title is required.")]         string Title { get; }      }   } 

Output:

is Valid = False

is Valid = True

like image 150
Erik Philips Avatar answered Sep 23 '22 04:09

Erik Philips


If you use a base class instead of an interface, the attributes will work fine.

like image 25
Lee Gunn Avatar answered Sep 24 '22 04:09

Lee Gunn