When implementing Repository for database in ASP.NET MVC project, is it correct to place business logic into it or may be better to place logic in controller class? Or use addit
In my opinion it depends on the business logic. Is the logic based on validation of input and input rules, if so it may be best to be on the model. However, if it is business rules based on workflow then that may need to be in a controller, such as, user chooses option A then gets redirected to a different page/form than if option B was selected. If the business rules have to deal with data persistence then it may need to go in the repository (It would seem strange to put it there to me). There's a ton of discussion about this, but it comes down to you or your team's perspective about how maintainable and flexible the end product will be based on the implementation.
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.
Business logic should be there in your Domain model.
Please look into this answer.
ASP.NET MVC - Should business logic exist in controllers?
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.
I agree with the above, controllers should not be responsible for business logic simply for returning the appropriate views. I use a service layer to provide business logic and view model creation so that a controller simply passes the model returned from a service to a view.
I also ensure my view models are simple DTOs, and the service simply knows how to populate the properties appropriately.