4

I'm working on an ASP.NET MVC 2 project with some business entities that have metadata dataannotations attributes applied to them (Validation attributes, Display attributes, etc.).

Something like:

//User entity
public class User
{

            [DisplayName("Vorname")]
            [Required(ErrorMessage = "Vorname fehlt")]
            [StringLength(MaxNameLength, ErrorMessage = "Vorname ist zu lang")]
            public string FirstName { get; set; }

            [DisplayName("Nachname")]
            [Required(ErrorMessage = "Nachnamefehlt")]
            [StringLength(MaxNameLength, ErrorMessage = "Nachname ist zu lang")]
            public string LastName { get; set; }

            [Required]
            public string Password{ get; set; }
}

Using the metadata from different views is no problem, as long as I am using my business entities as viewmodels or as part of a viewmodel like this:

//custom viewmodel with a user entity
public class CustomViewModel
{
   public User{get;set;}
   //some more properties...
}

However, sometimes I need to code a view for editing some, but not all fields of an entity. For those fields I want to reuse the metadata already specified in my user entity. The other fields should be ignored. I'm talking about custom view models like this:

[MetadataType(typeof(User))]
public class UserNameViewModel
    {

                public string FirstName { get; set; }

                public string LastName { get; set; }

                //no password on purpose, the user should only 
                //edit his first and last name in this view
    }

That's where I am running into problems. The custom view model above leads to an exception when the view is generated, because it has no password property.

The associated metadata type for type 'Zeiterfassung.Models.ViewModels.Users.UserNameViewModel+UserModel' contains the following unknown properties or fields: Password. Please make sure that the names of these members match the names of the properties on the main type.

Also, even if this exception did not occur, I expect to get into even more trouble with model validation on form submit because Password is marked as required in my business entity.

I can think of several workarounds, but none seem really ideal. In any case I can't change the database layout so that the password field would be in a separate entity in my example above.

How would you handle this scenario?

Adrian Grigore
  • 33,034
  • 36
  • 130
  • 210

1 Answers1

0

The only recommendation I could give you is to have view models specific to each view and have only the necessary properties and validation attributes on those view models. Don't worry if you repeat some validation attributes and properties on your view models. That's what they are meant for: reflect the logic of a given view.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 1
    That's what I have been doing so far, but it's a lot of duplicate code (in the form of metadata attributes). It also means having to unit test validation attributes for several models instead of just one model, even though in essence I only have the same validation rules on all models (for example, FirstName should always be required). – Adrian Grigore Oct 19 '10 at 12:11
  • Validation makes sense only in a given context for a given view, so writing unit tests for it shouldn't be a problem. The nightmare you will run into if you use the real models instead of view models will be orders of magnitude worse than putting validation attributes on your view models. Also have you ever considered using some other framework for validation instead of Data Annotations? [FluentValidation ](http://fluentvalidation.codeplex.com/) is really great and can be [unit tested](http://fluentvalidation.codeplex.com/wikipage?title=Testing&referringTitle=Documentation) very elegantly. – Darin Dimitrov Oct 19 '10 at 12:13
  • It's not a huge problem, but it's a lot of extra work, mostly in the form of extra unit tests. It also means a higher potential for bugs because when validation rules change on my business model, I will have to update several view model rules as well. It's easy to forget one of those in the process. – Adrian Grigore Oct 19 '10 at 12:17