22

What is the best way to use data annotations for validation if I'm using an Entity Framework (v5.0) database first approach?

This is my partial class created by Entity Framework:

//------------------------------------------------------------------------------
// <auto-generated>
//    This code was generated from a template.
//
//    Manual changes to this file may cause unexpected behavior in your application.
//    Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System.ComponentModel.DataAnnotations;

namespace ACore
{
    using System;
    using System.Collections.Generic;

    public partial class PayrollMarkup_State
    {
        [UIHint("StatesEditor")] // <-- I added this line but it will be overwritten
        public string State { get; set; }
        public Nullable<float> MaintenancePercentage { get; set; }
        public Nullable<float> OfficePercentage { get; set; }
    }
}

I tried this with no success....

Entity Framework generated file: 'PayrollMarkup_State.cs'

//------------------------------------------------------------------------------
// <auto-generated>
//    This code was generated from a template.
//
//    Manual changes to this file may cause unexpected behavior in your application.
//    Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System.ComponentModel.DataAnnotations;

namespace ACore
{
    using System;
    using System.Collections.Generic;

    public partial class PayrollMarkup_State
    {
        public string State { get; set; }
        public Nullable<float> MaintenancePercentage { get; set; }
        public Nullable<float> OfficePercentage { get; set; }
    }
}

I then created this file in a different directory: 'PayrollMarkup_state.cs'

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace ACore.Models
{
    [MetadataType(typeof(PayrollMarkupMetadata))]
    public partial class PayrollMarkup_State
    {
    }

    public class PayrollMarkupMetadata
    {
        [UIHint("StatesEditor")]
        public string State; // Has to have the same type and name as your model
    }
}
Mithrilhall
  • 1,485
  • 8
  • 33
  • 52

4 Answers4

23

Although it's somewhat painful, you need to create a class to use as the MetadataType for your model class.

[MetadataType(typeof(PayrollMarkupMetadata))
public partial class PayrollMarkup_State
{
  ...
}

public class PayrollMarkupMetadata
{
    [UIHint("StatesEditor")]
    public string State; // Has to have the same type and name as your model
    // etc.
}
GalacticCowboy
  • 11,663
  • 2
  • 41
  • 66
  • Does this really work if you declare a field instead of a property in your metadata class ? – JYL Mar 25 '13 at 18:18
  • 2
    @JYL yes, it doesn't look at whether it's a field or property, it's just an indirection mechanism. "Find this thing in that other class with this type and name, and apply these attributes to it." – GalacticCowboy Mar 25 '13 at 18:20
  • Thanks to Julie Lerman for linking me to this blog post. More detail on using GalacticCowboy's approach here. [Ardalis - Adding attributes to generated classes](http://ardalis.com/adding-attributes-to-generated-classes) – brian s Aug 15 '13 at 14:36
3

You have a namespace problem - you have defined two different PayrollMarkup_State classes, one under the ACore namespace and one under the ACore.Models namespace. Change the namespace to ACore (from ACore.Models) in the file containing the metadata type definition.

Moho
  • 15,457
  • 1
  • 30
  • 31
1

You can use a partial metadata class

http://www.asp.net/mvc/overview/getting-started/database-first-development/enhancing-data-validation

Shivam Srivastava
  • 4,496
  • 2
  • 23
  • 24
0

I used two additional classes: Map and Meta, here is my map:

namespace Whatever.Models
{
    [MetadataType(typeof(ThisMeta))]
    public partial class This
    {
    }


}

now here is meta class:

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace Whatever.Models
{
    public class ThisMeta
    {

        [DisplayName("")]
        public int UID { get; set; }

    }
}
IAbstract
  • 19,551
  • 15
  • 98
  • 146
cagedwhale
  • 51
  • 4