66

I have a couple model classes like so:

public class MyModelBase
{
    public string Name { get; set; }
}

public class MyModel : MyModelBase
{
    public string SomeOtherProperty { get; set; }
}

How can MyModel add a [Required] attribute to the Name property?

Mr Bell
  • 9,228
  • 18
  • 84
  • 134

4 Answers4

53

Declare the property in the parent class as virtual:

public class MyModelBase
{
    public virtual string Name { get; set; }
}

public class MyModel : MyModelBase
{
    [Required]
    public override string Name { get; set; }

    public string SomeOtherProperty { get; set; }
}

Or you could use a MetadataType to handle the validation (as long as you're talking about DataAnnotations...otherwise you're stuck with the example above):

class MyModelMetadata
{
    [Required]
    public string Name { get; set; }

    public string SomeOtherProperty { get; set; }
}

[MetadataType(typeof(MyModelMetadata))]
public class MyModel : MyModelBase
{
    public string SomeOtherProperty { get; set; }
}
Kevin Aenmey
  • 13,259
  • 5
  • 46
  • 45
Justin Niessner
  • 242,243
  • 40
  • 408
  • 536
  • 1
    This is the way to go if you have additional behavior you don't want to lose. +1 – Yuck Jul 01 '11 at 16:17
  • You now have to be careful with potential virtual calls in the base constructor. – nicodemus13 Oct 16 '13 at 21:08
  • 6
    According to [MSDN](https://msdn.microsoft.com/en-us/library/ff664465%28v=pandp.50%29.aspx) **MyModel** should be partial. – d.popov May 09 '16 at 13:51
  • 6
    Note that **overriding auto-properties with new auto-properties** results in **twice the number of backing fields** (i.e. ~double instance size). More scary is the fact that you may inadvertently **lose data from the base class' field initializers**! (The data is in the base backing fields, but the override implementations only look at their _own_ backing fields.) See Justin Minnaar's answer for a better way to override. – Timo Jun 04 '18 at 13:30
45

Try using a metadata class. It's a separate class that is referenced using attributes that lets you add data annotations to model classes indirectly.

e.g.

[MetadataType(typeof(MyModelMetadata))]
public class MyModel : MyModelBase {
  ... /* the current model code */
}


internal class MyModelMetadata {
    [Required]
    public string Name { get; set; }
}

ASP.NET MVC (including Core) offers similar support for its attributes like FromQuery, via the ModelMetadataTypeAttribute.

Ian Kemp
  • 28,293
  • 19
  • 112
  • 138
Kevin McKelvin
  • 3,467
  • 1
  • 27
  • 27
  • Anybody care to comment about the downvote? Technically this looks correct to me (even added something similar to my original answer). – Justin Niessner Jul 01 '11 at 16:19
  • 2
    My guess would be that this only works for attributes in the DataAnnotations namespace and is thus not a generic solution. – Marchy May 17 '12 at 19:42
  • 3
    [MSDN](https://msdn.microsoft.com/en-us/library/ff664465%28v=pandp.50%29.aspx) says that **MyModel** should be partial. – d.popov May 09 '16 at 13:52
  • @d.popov, MSDN doesn't says that MyModel should always be partial. MSDN uses a partial class because they assume that MyModel is partially generated by a tools that generate the MyModel class. – Yanal-Yves Fargialla Dec 06 '19 at 23:54
  • And note that we can not have two partial classes in different assemblies. – Hassan Monjezi Aug 03 '21 at 06:03
  • This simply doesn't work as shown. I run Attribute.IsDefined I get nothing. – AndrewBenjamin Jan 18 '23 at 17:49
28

I note that none of these answers actually call the base Name property correctly. The override should write something like the following, in order that you don't have a separate value for the new property.

public class MyModelBase
{
    public virtual string Name { get; set; }
}

public class MyModel : MyModelBase
{
    [Required]
    public override string Name { get { return base.Name; } set { base.Name = value; }

    public string SomeOtherProperty { get; set; }
}
Justin Minnaar
  • 381
  • 3
  • 3
  • 2
    I fail to see, why would it be necessary. If what you say was true, this code should not work, yet it works: http://csharppad.com/gist/c5db27fb3b90f961a2da . I guess, that compiler handles overridden auto properties automatically. – Spook Dec 10 '15 at 09:25
  • 1
    @Spook I think it would be necessary only if you have some custom implementation in base class (like RaisePropertyChanged in setter). If you just use auto properties in subclass, the getter/setter in base class will not be called. – Ryan Mar 30 '16 at 10:52
  • 1
    Good answer. A shorter syntax would be : `public override string Name { get => base.Name; set => base.Name = value; }` – Alex from Jitbit Mar 08 '23 at 16:05
-1

You can overload the base property by "new" keyword.

public class MyModelBase
{
     public string Name { get; set; }
}

public class MyModel : MyModelBase
{
     [Required]
     public new string Name {get; set;}
     public string SomeOtherProperty { get; set; }
}
ahmet
  • 702
  • 1
  • 10
  • 29
  • 2
    This "works" but breaks polymorphism. If you write the following code "something" would be null. MyModel m = new MyModel(); m.Name = "Blah"; MyModelBase mb = m; var something = mb.Name; – raterus Oct 27 '17 at 16:57
  • So you say new keyword overloading is dangerous? Then what is it for? – ahmet Oct 27 '17 at 17:04
  • I never said it was dangerous, but in light of the other better solutions here, using new is not recommended. I typically use new very sparingly, and only when I need to override the return type. – raterus Oct 30 '17 at 15:04
  • Are you sure you mean to use the word "overload"? I think you're trying to talk about "override" instead. Overriding with new can have "dangerous" implications if you don't fully understand what you're doing. The way you asked "then what is it for" suggests that something potentially dangerous has no actual purpose. An ax is dangerous, but it's also good for chopping wood. The "new" keyword is "dangerous" in some contexts, but also is useful for wholesale replacing specific functionality in a derived class. – Jazimov Aug 24 '18 at 14:28
  • new is useful when you want to change the type of a property in an inherited class, that can have very useful specific purposes, but it also creates an extra set of backing fields and if you use auto-properties and don't manage the values of the base fields, data may be lost if you try to use the properties from the base class methods. If you use new, you either need to know that the base class is not going to need to use the values set in the derived class or you need to do like Justin Minnaar's answer below where he sets the base properties. – ScottFoster1000 Sep 30 '18 at 06:36
  • new is bad practice in general. It breaks the base functionality and it doesnt flow towards child classes. – Kat Lim Ruiz Aug 03 '19 at 14:20