What is the best place for business logic in ASP.NET MVC when using repositories? What is the best place for business logic in ASP.NET MVC when using repositories? asp.net asp.net

What is the best place for business logic in ASP.NET MVC when using repositories?


Ultimately there isn't a perfect place for your business logic besides its own layer (as part of the "Model" layer). Often you can get away with a different implementation, but there are trade offs in every case.

The trade off to creating another layer for the business logic is that you have to actually encapsulate your code. If you're too aggressive, you might also get some duplication between your entities and your domain model (if your DB's relational semantics already take care of your buiness logic).

View

The view is the most brittle part of your app, as it is the most likely part to change.

It is also very hard to get business logic correct in your view, due to having to support all the various view state transitions.

It is extremely well known these days that you just don't do this :)

Repository

The issue here is one of maintenance and purity of abstraction. Violating this can confuse people and make your app hard to maintain.

From the P of EAA article on the Repository pattern:

A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection

A repository is an abstraction that presents your data storage as a collection that holds domain objects.

No domain logic should reside in it. Instead, it should exist in your domain objects (by definition, as your business logic is your domain).

To do otherwise (to make your repository do double duty and also validate domain logic) would be a violation of SRP (Single Responsibility Principle), and would be a code smell.

You can have higher level domain objects that work with collections of domain objects to validate domain logic (such as dependencies within a collection of objects, size limits, etc). They will still use your repositories under the covers to do final storage/retrieval of domain objects, so they won't be doing double duty (so won't violate SRP).

Controller

The controller is also not a good place to put business logic. The controller's job is to mediate between the controller and the model.

The model is the domain, and the domain is your business logic.

Entities

You might consider putting domain data in entities.

But you must be careful when accessing navigation properties if the entities are attached, as you can trigger inadvertent DB queries or exceptions (depending on if your context is disposed or not). Detaching them is also a problem, as it destroys your object graph unless you explicitly reattach the objects to each other after detaching them from the context.

If you make separate domain model classes, you might consider treating entities as DTOs only.

Edit: IValidatableObject

I found out just now about a feature in Entity Framework 4.1 that you may want to check out: the IValidatableObject interface.

You can make your entities partial classes, and in the partial class, implement this interface. When you do, the Entity Framework will call Validate on save, and you can call Validate whenever it makes sense for you to do so.

This might help you avoid splitting your persistence model from your domain model in additional cases.

See this article: http://msdn.microsoft.com/en-us/data/gg193959

Side note: Views/View Models

In case you are thinking about it, I suggest you avoid the temptation to pass entities back to the view. It will break in a lot of cases (e.g. Javascript serialization to store view state), and cause unintentional DB queries in other cases. Pass back simple types instead (strings, ints, lists, hashsets, dictionaries, etc), or construct view model classes to pass to the view.


Add a Service Layer to pass models to Repository, where Service classes corresponding to the controller can be added. For example if you use a UserController and User Model, You can pass the User Model to UserService class.

Here the Service Layer can act as a bridge between the Repository and the controller so that the separation of Controller and Repository is well established.