The following subjects will be handled in oncoming blogs:
- Inversion of Control container: StructureMap
- View hierarchy
- View Model and Form Model
- Poor man's RenderAction
- Post-Redirect-Get pattern
To make the site as testable and maintainable as possible I adhere to the DRY principle (don't repeat yourself) and try to write SOLID code:
- Single Responsibility Principle
- Open/Closed Principle
- Liskov Substitution Principle
- Interface Segregation Principle
- Dependency Inversion
Another aspect to focus on is to keep the controllers mean and lean. This is called the skinny controller, fat model; it states to have your controller actions as thin/short as possible, because you really want to avoid having business logic in your controller. Keeping the business logic in the domain model and service layer encourages reuse and makes it easier to update your site flow, and of course avoids having duplicate code in your project. It's really a question of Separation Of Concerns.
The following diagram globally represents the architecture of our MVC application. The layers are explained in a bit more detail below from bottom to top.
Data is often accessed in databases or through web services; there usually is an impedance mismatch between their data structure and our domain model. To overcome this mismatch we have mappers to perform the conversion from data model to domain model and vice versa.
The repositories provide CRUD functionality for the domain models to the physical storage layer with the use of the mappers.
Inside this layer the services provide access to data in the form of domain models as well as the possibility to handle various other actions as creating and updating new objects.
The core business logic of the site is contained in this layer. This makes it reusable by all controllers and views.
The controllers of course play the central role in this layer. On get requests the controller requests domain models from the services in the layer beneath and passes these to the views in the form of view models; the conversion between domain models and view models is handled by the mappers.
In the case of views containing a form, the controller supplies the view with a form model. These contain various data from the domain model. Except for the data being edited it also contains data for dropdown lists and the likes. These models are also converted in the mappers.
When data is posted it usually enters the controller action as a form model. This model is handed off to a handler that updates the domain model with the data from the form model. This prevents the possibility of security leaks through overposting or underposting. Furthermore it keeps the controller skinny. Sequentially the handler calls the services for further handling of the actions neccessary to persist any changes.