1

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

Corb3nik
  • 131
  • 6
  • This question comes from my SO post : http://stackoverflow.com/questions/32771814/code-first-approach-with-model-inherited-from-class-in-different-assembly – Corb3nik Sep 28 '15 at 13:08
  • do you mean entity framework data annotations or asp.net form validation via view model annotations? – Ewan Sep 28 '15 at 14:06
  • @Ewan EF data annotations. Just like `[Key]`, `[Required]`, etc... – Corb3nik Sep 28 '15 at 15:00
  • how does asp.net fit into it? – Ewan Sep 28 '15 at 15:01
  • Well, to rephrase what I put in my question here, I have a class library project containing my domain models. These domain models have validations in the setters (each setter throws an exception when invalid). Now I would like to use these domain models in my ASP.net project using the code first approach. Therefore I must create classes in my `model` folder of my ASP.net project. To simplify my question a bit : What do I put in my `model` classes so that they work out with my validations from my setters. (Hope this makes sense for you) – Corb3nik Sep 28 '15 at 15:10
  • it makes a bit more sense. But you don't to have a website or put anything in the Models directory to use EF. – Ewan Sep 28 '15 at 15:15
  • @Ewan Indeed, now this is where the code-first approach problem comes in. How would I generate database migrations if I don't use the models directory? – Corb3nik Sep 28 '15 at 15:18
  • @Ewan Edited my question so that you can have a clearer view of my setup. – Corb3nik Sep 28 '15 at 15:25

1 Answers1

2

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
Ewan
  • 70,664
  • 5
  • 76
  • 161
  • Makes sense... It sucks that we have to do it that way though. I'll leave the question open a bit, but I think this is the only approach that we can take for this. – Corb3nik Sep 28 '15 at 15:46
  • personally I wouldn't bother with EF unless you want to skip rigorous separation of responsibility and just add the annotations to your domain objects – Ewan Sep 28 '15 at 15:53