Corb3nik
Corb3nik

Reputation: 1177

Code First Approach with Model Inherited From Class In Different Assembly

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 :

Upvotes: 2

Views: 911

Answers (1)

Alexander Christov
Alexander Christov

Reputation: 10045

The idea to use the same classes for multiple purposes is not very good. Normally, business classes are oriented towards (responsible for) business logic. On the other hand view models, cause this is usually what you have in your ASP.NET MVC Models folder, are responsible for supporting the MVC app's views. Finally there are data classes (some call them DTOs) which are part of your DAL.

So, back-to-front you should have data classes, business classes, and finally view models, which form the absolute minimum for a middle-sized to large scale web app. Even small apps benefit from these separation.

Now you can recall the first letter of SOLID, that is the Single responsibility principle, which states:

A class should have only one reason to change.

(More about Single responsibility principle here.)

What you are trying to do is assigning two roles to your business classes, namely business and presentation, view models. So, say, you want to cover some new business functionality, then, for sure your view models will suffer. On the other hand, if you want to add some related to views functions (your case) your business logic implementation may become endangered. This is pretty much as if you're putting them in a procrustes bed.

What is even worse, you call these classes "generic" thus leaning towards using them in other parts of your application, perhaps DAL. Just don't.

And what is clearly visible in your example is that once you begin fighting against a fundamental design principle you get into design troubles building your application.

So, stick to what is well-known:

  1. Data classes (DTOs) - living in DAL,
  2. Business objects/classes - living in BL,
  3. View models - living in Presentation layer.

Separating your app this way will make your life much easier.

Upvotes: 2

Related Questions