I am not sure how to do what you are asking for but there is a way around it. Dynamic data validation by overriding the GetValidators of your custom DataAnnotationsModelValidatorProvider. In it you can read the rules for validating each field (from a database, config file, etc.) and add validators as need be. It has the added values that your validation is no longer tightly coupled to the model and can be changed without need to even restart the site. Of course it might be overkill for your case, but it was ideal for ours!
The generated class ItemRequest will always be a partial class. This allows you to write a second partial class which is marked with the necessary data annotations. In your case the partial class ItemRequest would look like this:
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
//make sure the namespace is equal to the other partial class ItemRequest
namespace MvcApplication1.Models
{
[MetadataType(typeof(ItemRequestMetaData))]
public partial class ItemRequest
{
}
public class ItemRequestMetaData
{
[Required]
public int RequestId {get;set;}
//...
}
}
As MUG4N answered you can use partial classes but will be better use interfaces instead. In this case you will have compilation errors if EF model doesn't correspond to validation model. So you can modify your EF models without fear that validation rules are outdated.
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace YourApplication.Models
{
public interface IEntityMetadata
{
[Required]
Int32 Id { get; set; }
}
[MetadataType(typeof(IEntityMetadata))]
public partial class Entity : IEntityMetadata
{
/* Id property has already existed in the mapped class */
}
}
P.S. If you are using project type which is differ from ASP.NET MVC (when you perform manual data validation) don't forget to register your validators
/* Global.asax or similar */
TypeDescriptor.AddProviderTransparent(
new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Entity), typeof(IEntityMetadata)), typeof(Entity));
This is sort of extension to @dimonser answer if you regenerate your db model you will have to manually re-add interfaces on those classes.
If you have stomach for it you can also modify your .tt templates:
Here's example of auto-generating interfaces on some classes, this is fragment from .tt just replace EntityClassOpening method in yours with following (and obviously var stringsToMatch with your entity names and interfaces).
Modify the T4 template adding required annotations, this file is usually named MODELNAME.tt
find where the T4 is creating the class and methods to know where to put these.
<#=codeStringGenerator.IgnoreJson(navigationProperty)#>
//create this method in file
public string IgnoreJson(NavigationProperty navigationProperty){
string result = navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? "" : @"[JsonIgnore]
[IgnoreDataMember]";
return result;
}
You will also need to add the namespaces;
<#=codeStringGenerator.UsingDirectives(inHeader: false)#>
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json;
using System.Runtime.Serialization;
Rebuild your classes by saving your model, all your methods should be annotated.
I found a solution like MUG4N's answer, but instead, nesting the MetaData class within the entity class, thereby reducing the number of classes in your public namespace list, and eliminating the need to have a unique name for each metadata class.
using System.ComponentModel.DataAnnotations;
namespace MvcApplication1.Models
{
[MetadataType(typeof(MetaData))]
public partial class ItemRequest
{
public class MetaData
{
[Required]
public int RequestId;
//...
}
}
}