Question

I have a solution split into two projects : A class library containing all of my model classes (lets call it Business), and an ASP.Net MVC project.

My Business classes are meant to be generic and work for multiple types of projects. For this reason, they don't contain any data annotations/associations to other classes, only member variables/properties/constructors.

Using the code-first approach, how should I design my ASP.Net models to work with my Business models.

My initial taught was setting my Business classes as partial classes and then overwrite my properties by adding the necessary data annotations/associations. I can't do that because we are dealing with two separate projects.

I was also thinking that I could use inheritance. My ASP.Net models could inherit from the Business classes and I could add my data annotations/associations on top of that. This seems a bit messy and illogical though, as I would need to define all of my constructors in this new subclass.

Is there a smart way of doing this in a cleanly?

EDIT :

My Business classes have validations by throwing exceptions in the property setters. My first design was to create my own custom data annotation that will catch the exceptions thrown by my setters :

public class SetterBasedValidation : ValidationAttribute
    {
        string m_errorMessage = null;
        public SetterBasedValidation(string errorMessage)
        {
            m_errorMessage = errorMessage;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            try
            {
                Type type = validationContext.ObjectType;
                PropertyInfo property = type.GetProperty(validationContext.MemberName);
                property.SetValue(validationContext.ObjectInstance, value);
            }
            catch (Exception)
            {
                return new ValidationResult(m_errorMessage);
            }

            return ValidationResult.Success;
        }
    }

I would then need a way to use my custom data annotation in my ASP.Net model class. This would give me the result I want :

  • Keep my Business classes generic
  • Use the validations from my setters
  • Use data annotations

EDIT 2 :

Here is a basic overview of what my solution setup looks like. My business classes (domain models) contains code looking like this :

 public class User
    {

        private string m_name = null;

        public string Name
        {
            get { return m_name; }
            set
            {
                string name = value.Trim();

                if (name.Length > 20 || name.Length < 1)
                {
                    throw new ArgumentException("Name length invalid.");
                }
                m_name = name;
            }
        }
    }

enter image description here

Was it helpful?

Solution

Your website should have a separate set of ViewModels which wrap the domain models and any other data/logic required by the page.

Because these view models belong to the website rather than the domain its ok to stick on any validation or extra logic which is only required by the website/View for the particular process you are implementing.

I think the best example is say you have some process 'Sign Up' the domain model for which includes a ton of data about the person signing up. Your design teams comes up with two designs.

  • Design 1: A large single page form with all the fields on

  • Design 2: A 'Wizard' approach with multiple separate forms

Although both designs use the same underling logic for signing up. each will have very different view models.

update ---

Entity Framework data annotations allow EF to correctly map your object to a database table. There are some conventions which will allow you to get away with not using some of them of your properties are named as expected.

However, you are correct in that if you want to separate your domain objects from the persistence logic you will need to implement an Entity Object which mirrors the properties on your domain object and to which you can add the data annotations.

You can wrap all this in a repository object which can get the Entity objects back from the DB, convert them to your Domain objects and return them to the calling code. However if you do all these things you will find that you have lost the time saving benefits of EF and might as well have just used SqlClient

In the ideal world you solution structure might look like this:

DomainModels - class lib
    User.cs

EntityModels - class lib
    UserEntity.cs - with data annotations

RepositoryEF - class lib ref domain and entity
    UserRepository.cs - eg. public User GetUser(string id)

Website - ref the other three
    UserController.cs - calls repository to get a domain object
    UserViewModel.cs - populated from domain object by controller
    UserView.cshtml - uses viewmodel as its model and displays data to user
Licensed under: CC-BY-SA with attribution
scroll top