ASP.NET MVC Business Logic in Domain Model vs Service Layer - asp.net-mvc

I have been reading about where to put business logic in ASP.NET MVC Project for a while and I still can't get clear on some things.
1 - Domain models. What are these really? In my Model folder I have only a bunch of classes corresponding to my database. I am using EF code first. I assume these are my domain models.
2 - Service Layer. This answer suggests a service layer and I think this makes perfect sense. I had decided to go with this one. However, Martin Fowler's "Anemic Domain Models" article messed up my mind.
I am not really sure how can I add logic to my domain models.
I have gone through many business logic-related questions and each of them proposes either 1 or 2. What I don't understand is how I can implement the first one. Adding methods to entity classes (domain models for me) does not make sense at all. And why is the second approach considered bad?

First off, your Model folder in your Asp.Net MVC project should be used for ViewModels. These are the models that your Controllers send to your Views. They should be highly optimized for the View, meaning only the properties needed for the view, and nothing else.
What you are taking about, Domain Models, are the same as Business Models, and belong in your Business Layer. The Model folder in your Asp.Net MVC project are the models for your UI Layer.
The second approach, business logic in your service (really business) layer is not considered bad. It's a very nice buffer between your Data Layer and your UI Layer (3-tier architecture). Your data layer handles getting data, from either web services or a database, and your business/service layer handles translating that data into business/domain models. It also holds any business logic, like calculations, etc.
These business/domain models are usually POCOs, but they don't have to be. This is how I sometimes set up my business models:
public class BusinessObject
{
private DataObject _dataObject;
public BusinessObject(DataObject dataObject)
{
_dataObject = dataObject;
}
public int BusinessId
{
get {return _dataObject.Id;}
set {_dataObject.Id = value;}
}
public string Name
{
get {return _dataObject.Description;}
set {_dataObject.Description = value;}
}
}

I prefer to NOT have business logic in domain models. I keep my domain models usually as POCO's to represent my DB tables/schema.
Keeping the business logic away from the domain models will allow me to reuse my domain model with another project as well.
You may consider a middle layer between your controllers and your data access layer/ Repositary layer to handle this. I would call this as a service layer.

I know this has already been answered, but I categorize models into 3 groups
ViewModels - These are light weight (often poco) classes that model the data needed by a page on your site. These classes handle the mundane boilerplate of what gets shown to the user, and changes when the data that you want to display changes.
DomainModels - These are normally heavy weight business logic classes. They normally model the core business rules for what you're doing. These classes are often highly cohesive and are where the majority of the work that makes your site special happens. I said these models are normally heavyweight but in reality if all your project does is take that data from the user and stick it in the database, this class is going to be a little data mapping class. Many times you'll see these classes being composed of persistence models and returning view models.
PersistenceModels - These are models of your persistence mechanism. For most of us this means modeling a database table, but could also be a complex nosql document or json (or whatever) data that's returned from an api request. Their responsibility is to handle the mundane boiler plate of what shape your external data takes.
Keep in mind also that you don't always need to have all three of these types of models present in your project. Sometimes your view model will be line for line what you're persistence model is. In that case you'd be wasting your clients money to write the whole thing twice and add a domain model to map one to the other. You're the developer and it's your job to know when to build a air-craft carrier to go to the store for groceries.

Domain models should be able to perform their work on their own and expose properties and methods that represent their state and functions. They act as roots (aggregate roots) to a hierarchy of information that is required by models to function. They remain hidden only available to services.
Services expose business/domain functionality to the outside world (web services, UI etc) as a set of APIs following the message pattern (requests/responses), by retrieving models from the repositories that encapsulate the data access layer, then calling methods/business functions on the models and finally saving them back to the repositories.
Some times it feels that services repeat methods of business objects, but in time and real practice that is not what really happens.
In a real domain driven design you need at least 3 sets of objects. Business Objects, Repositories of Business Objects and Services.
Think as if your requirement is always that each type of component is written by different teams. One team requires an exposed service without knowing the details and without the other having to write the logic on the service it self. The service could then be consumed by anyone that requires it without having to dig into the core model itself.

Application flow control logic belongs in a controller.
Data access logic belongs in a repository.
Validation logic belongs in a service layer.
A service layer is an additional layer in an ASP.NET MVC application that mediates communication between a controller and repository layer.
The service layer contains business validation logic.
For example, a product service layer has a CreateProduct() method.
The CreateProduct() method calls the ValidateProduct() method to validate a new product before passing the product to the product repository.
Source:
http://www.asp.net/mvc/overview/older-versions-1/models-data/validating-with-a-service-layer-cs

Related

Is it ok to have database context in my domain model

I am developing a web based application using ASP.NET MVC. I am trying have rich domain models rather than the thin/anemic models.
I have modelled my solution along the lines of Onion architecture. The different projects are as below :
{}.Domain.Core - contains the domain objects and interfaces like IDbContext which is implemented in the Infrastructure layer
{}.Database - is the database prject
{].Infrastructure - contains implementation for logging, Data Access etc.
{}.Web - View and Controllers
**** The data access is done using dapper and IDbContext is a wrapper around 2 simple command, query interfaces. I have isolated each of the queries as separate class.
For sake of discussion I am taking a small part of the application.
I have a versioned document library which contains documents along with other metadata like tags, permissions etc
A simplified model of my document object is as shown below
I would want the operations to be defined within the domain object, since there is business logic involved in each of these operations.
Let me take "Delete" as an operation. The operation needs to be perform
Validate if user has permission to delete
Check if there are no associations which will get impacted by this delete
Check if no workflow is in progress
Delete the actual item from database in a transaction
As shown in above example, I would need the database context to complete this operation.
The way I have currently thinking if modeling is to have the domain object have IDbContext, which can execute the queries exposed.
In my controller class I call the domain objects and perform the operations.
I am not sure if passing the IDbContext in the domain object is ok? If not what are the better ways to model this?
I am not convinced in having a separate service layer because
1) Controller act as first layer of service layer for most of the cases
2) Service layer is just duplicating the same methods from domain to another class
Let me know how I can better this design.
Injecting the IDbContext like that brakes the main principle of the Domain model which should be responsible for business logic ONLY while retrieving and storing your domain entities is the responsibility of the infrastructure layer. Yes you inject it by interface, hiding the actual implementation but it makes you domain model aware of some storage.
Also the steps from above required to delete a Document doesn't entierly belong to the Document object. Let's consider the first step with user permissions and the following cases:
Users with Admin role should be allowed to delete any document
Document owner should be allowed to delete the document
For the first case there might not be a connection between a user and a document to remove. Admin users are just allowed to do anything. It's like a classical example with two bank accounts and an operation to tranfer money which involves both accounts but is not their responsibility. This is when Domain services come into place. Please don't confuse them with Service layer services. Domain services are part of the domain model and responsible for business logic only.
So if I were you, I would create a new Domain service with DeleteDocument method. This should do the first three steps from above accepting User and Document as parameters. The fourth step should be done by your repository. Not sure what you mean by saying
I didn’t see too much value in adding repositories
but from domain model perspective you already have one it's the IDbContext. I assume you meant some pattern to implement repository or separate repository for each entity. In the long run your pseudo code in the controller should be the following:
var user = bdContext<User>.SelectById(userId);
var document = bdContext<Document>.SelectById(docId);
var docService = new DocumentService();
docService.DeleteDocument(document, user); // Throw exception here if deletion is not allowed
bdContext<Document>.Delete(document);
If you expect you need this logic in many places of you application you can just wrap it up in a Service layer service.
I suggest reading Eric Evans book on DDD if you want to learn more about Domain modeling. This discusses the meaning of entities, value objects, domain services, etc. in detail.
ANSWER TO THE COMMENT:
Not really, the domain services are part of the domain, so both implementation and interface are part of the domain as well. The fact that two or more objects have to interact with each other is not enough for creating a domain service. Let's consider a flight booking system as an example. You have a Flight entity with different properties such as DepartureCity, ArrivalCity. Flight entity should also have a reference to a list of seats. Seat could be a separate entity as well with such
properties as Class (business, economy, etc.), Type (isle, row, middle), etc. So booking a seat requires interacting with different entites, such as Flight and Seat but we don't need a domain service here. As by nature Seat property makes no sense if not considered as a child object of a Flight. It's even very unlikely you would ever have a case to query a Seat entity from out of the Flight context. So reserving a Seat is responsibility of the Flight entity here and it's ok to place the reserving logic to the Flight class. Please note it's just an example to try and explain when we need to create domain services, a real system could be modeled completely another way. So just try following these three basic steps to decide whether or not you need a domain service:
The operation performed by the Service refers to a domain concept which does not naturally belong to an Entity or Value Object.
The operation performed refers to other objects in the domain.
The operation is stateless.
I'm accessing dbcontext from the controller which is application/service layer not domain/business layer. Domain model deals with business logic only, it should not be aware of any persistance logic and from the example above you can see that DocumentService has no references of the dbcontext.

Should business logic ever be in the model? (MVC4)

I have a class called "Stores" in my MVC app that has a class called "IsInCompliance" which depends on the values of several other fields. The logic would go through and say "if this, this, and this is true, then IsInCompliance is true".
Should this belong in the model definition, or would this logic be better placed in a service layer or controller? I figure I have four options:
Logic contained in a method within the model
Logic contained in a controller that writes back to the model
Logic contained in a Service that the model calls
Logic contained in a Service that the controller calls
Which is best? If 3 is the best, isn't there a circular dependency there (since my model project depends on the services project, which depends on the model project)?
Number 4 is the correct approach.
Controllers should act as a thin "traffic control" layer and delegate all logic to a service layer beneath them (or if it's not too obvious logic, to a business layer - but that's a different architectural question).
Your model should generally be a pure POCO structure, with optionally micro-logic of things that are internal to the data model. For example, ID generation and data integrity operations.
Most of your logic (for relatively simple / CRUD-based apps) should generally reside in the Service Layer.
This is a matter of preference/style, but I have always believed that methods that are germane to the Model object belong in that object.
Take this as an example (I'm coding on the fly without an open VS.NET instance, so please forgive any syntax errors, just trying to use this as a vehicle for communication):
public class Person
{
public Int32 Age { get; set; }
public bool IsEligibleToEnterLegallyBindingContract()
{
return Age >= 18;
}
}
I would assert that a model object that contains methods that introspects its own properties and is not dependent on messages and/or properties of other model objects is good object design and a good modeling approach in an MVC environment.
Update I had a discussion with a colleague regarding this, and he pointed me toward the Anemic Domain Model, an excellent article by Martin Fowler. I read this article several times after my colleague recommended it.
The closing paragraph from Mr. Fowler's article (this is a direct quote from martinfowler.com and credit is acknowledged and given to that site):
"In general, the more behavior you find in the services, the more likely you are to be robbing yourself of the benefits of a domain model. If all your logic is in services, you've robbed yourself blind."
MVC is all about separating concerns. Keep it that way. Separate your logic from your data by placing your business logic in a separate class (layer).
Usually I perform actions on the Model rather than IN the Model, however it is sort of a personal preference.
I would (in your case) write the logic in the Service layer, then do a coordination call from the Controller that would work on the Model.
That said however, I believe some people refer to this as an Anemic Domain Model.
I don't think any of the approaches are wrong, but I personally would go for Number 4.
I guess it depends on your coding style.
Either option 1, or option 4 is correct depending on who you ask.
For something like this, i think option 1 is correct.
If IsInCompliance only depends on the value other properties in the model then it should be in the model.
If the value of IsInCompliance depends on other classes then yes it should be in a service layer.
Moving stuff like this to a service layer results in an Anemic Domain model where your model classes end up just being dto's
In object oriented design, this is considered an anti pattern.
There is still plenty of stuff that needs to be in a service layer, i just don't think this is one of them.

ASP.NET MVC - M V C Responsibilities

I am probably over analyzing here, but with all the reading I have done on MVC, there seem to be so many opinions on how to do things.
Is there a "Best Practices" site or document out there that defines the responsibility of each piece of MVC?
The few questions I have, keep in mind I am using the EF/Repository&UnitOfWork/Service pattern are:
1) How to get the validation results (error messages, etc) of Domain Objects and Business Rules from the Service Layer to the View Models?
2) I am using Domain Objects and a Service Layer that does all the Business Logic, then I send the Domain Objects to the controllers and let them (via AutoMapper) convert them to View Models for the views. What other types of things are the responsibility of the controller? Is the following code OK? Is this too much logic in the controller?:
public ActionResult SomeAction()
{
var model = Mapper.Map<DomainObject, ViewModel>(service.QueryReposForData());
model.SomeCollectionForSelectList = Mapper.Map<IEnumerable<DomainObject>, IEnumerable<ViewModel>>(service.QueryReposForSelectListData());
return View(model);
}
I don't think that the only thing in a controller is one line that returns a view with an object graph mapped to view models?
3) I think it is OK to have properties on the ViewModels that can indicate to a view if something can be hidden for example and then perform that logic in the view? Example:
#if(Model.DisplaySomething)
{
<div>Something to show</div>
}
else
{
<div>Something else to show</div>
}
4) I was thinking of having my services return some sort of TransactionResult object back to the controllers on writes to make it the responsibility of the service to handle the transaction. So I would have an aggregate service that would start a transaction (UnitOfWork) do what ever it needed to do and then return this TransactionResult that could have error messages? I don't think I should make the controller responsible for managing the transaction, but rather have it just pass in a view model mapped to a domain object to the service and let it act on it?
5) Also, how much of ActionFilter's do you want to use? I know it is a huge extensibility point, but I often find myself trying to stuff all of the model creation into a filter.
Just opinions here based on how we work.
We keep our Controllers so skinny they are anorexic, in almost every case.
As for ViewModels, we follow the pattern of having a ViewModel for every view. The Controller loads it up with anything it needs, and kicks it off. From there, the ViewModel drives everything. In our world, the ViewModel is tied directly to the view and contains no code that would/could be used in other parts of the application. It interacts with any part of the larger 'Model' (service layer, etc) that it needs to and packages stuff up for the View to consume.
For your #3 example, I'd say absolutely yes - it's the way we use our ViewModels.
Again, none of this is gospel - just my take on how we handle it.
Excellent questions!
1) How to get the validation results (error messages, etc) of Domain
Objects and Business Rules from the Service Layer to the View Models?
I use EntityFramework in the back-end and implement IValidatableObject both on my models and my entities. On models, I perform cross-field validation, while on entities, I perform cross-entity validations.
2) I am using Domain Objects and a Service Layer that does all the
Business Logic, then I send the Domain Objects to the controllers and
let them (via AutoMapper) convert them to View Models for the views.
What other types of things are the responsibility of the controller?
Is the following code OK? Is this too much logic in the controller?:
This code is perfect. Controllers gather data, transform data into models and feeds them into a view.
3) I think it is OK to have properties on the ViewModels that can
indicate to a view if something can be hidden for example and then
perform that logic in the view? Example:
Yes, this is exactly what a ViewModel is meant for. To capture all data AND logic required for your view to render.
4) I was thinking of having my services return some sort of
TransactionResult object back to the controllers on writes to make it
the responsibility of the service to handle the transaction. So I
would have an aggregate service that would start a transaction
(UnitOfWork) do what ever it needed to do and then return this
TransactionResult that could have error messages? I don't think I
should make the controller responsible for managing the transaction,
but rather have it just pass in a view model mapped to a domain object
to the service and let it act on it?
I struggled with this a bit in my projects. In the end, I moved the SaveChanges method of EntityFramework to the front-end. This allows me to build a transaction in the front-end and then commit it once. Every method in my ApiController which performs an update, create or delete will also do a SaveChanges.
I use ApiControllers as a layer of abstraction between my back-end and actual Controller classes. To elaborate, my application both uses normal Controllers (HTML) and ApiControllers (REST aka Web API). Both types of controllers share a common interface for retrieving data.
Example: http://pastebin.com/uL1NGGqH
The UnitOfWork still resides in my back-end behind a facade. I just expose the SaveChanges to the front-end. Side-effects such as ValidationExceptions are either handled by ASP.NET MVC automagically or captured in custom ActionFilters.
5) Also, how much of ActionFilter's do you want to use? I know it is a
huge extensibility point, but I often find myself trying to stuff all
of the model creation into a filter.
I only used a handful of ActionFilters in the large MVC project I am currently working on. These ActionFilters are mostly used to enforce security and to translate Exceptions (such as ValidationExceptions) to JSON-format so my client-side validation framework can handle it.
Off-topic: You can never over analyze. Asking yourself these fundamental questions of MVC makes you better grasp the concepts of MVC and makes you a better developer in general. Just make sure you don't do it too much in the boss' time ;)
Same here:
base controllers with common actionfilters
Validation is done using DataAnnotation and model validation within the controller.
tiny controllers with injected wrapped context or specific service layer
Automapper mapping ViewModels/EF Pocos.
I don't really bother about implementing UnitOfWork or explicitly using transactions since EF4 automatically creates (if it does not exist) a new transaction for all the changes done within a SaveChanges (http://msdn.microsoft.com/en-us/library/bb896325.aspx. I just have a generic interface exposing the DbSets of the Context as IQuerable and the Add/Delete/Find methods.
But as said it's all personal.

Where to put data manipulation and business logic code in ASP.NET MVC application?

Having watched samples from Rob Conery's Kona application, I see that he is using two things with IoC - ISession, where he has data layer code and Services, where he has some additional business logic that we need to perform when manipulating data in datastore. For instance, we might not just add a record to the DB but also change properties of another record, increase some counts, take something back, etc. We need to put that additional code somewehere and he puts it in those services.
For instance, he has a CustomerService that manipulates Customers. This requires us to send ISession instance to the CustomerService, so that the CustomerService can use it to access the datastore.
Now another way of doing it would be to put that additional code in the Customer class itself and send the ISession (or IRepository, whatever terminology we use) to that class. And not have any services. Typically, Customer, Order, Product, etc. classes are Model classes, so that would result in big/heavy model classes.
My question is, which solution is better? So far I did not have the need for that because I had most of the code in the controllers but now as my application grows, I need to make a decision on this and cleanup the controllers.
Currently I have:
- fat controllers with business logic in it,
- very atomic repositories,
- very clean models and viewmodels.
Should I move to:
- slim controllers,
- repositories with more code,
- models with business logic code (specifically should my model classes contain methods like Add(), Remove(), for instance Customer.Remove()??)
or to
- slim controllers,
- atomic repositories,
- still clean models,
- services (to encapsulate everything else that does not go into any of the previous).
I would recommend you having repositories containing atomic operations with the model classes and service layer which depends on those repositories to define business operations. The concept of AOP could be used to automatically start a SQL transaction at the beginning of each business operation and commit at the end or rollback in case of exception.
Finally controllers will use those service classes and convert between the domain models and view models.

Missing a part / layer in my app

I have an asp.net mvc application with three layers:
- data layer with entities and repository (nhibernate) pattern
- service layer with services (functions), which communicates with data layer.
- ui layer with asp.net mvc application, which communicates with service layer.
The problem is that the data in my entities is different that the data in my views.
So I am using custom shaped ViewModels. But I don't like the way I am mapping between the service layer and the view models.
Everything is happening in the controllers action. I am using AutoMapper but I think that there is too much spaghetti code.
Let me give an example:
1.) I am having an user registration process. I have a FirstName, LastName, Email, OpenId inputs which maps to the same
properties in the ViewModel. But than I am having to different entities to store this data (one for the user, and one for the openid identity - user can have multiple openid identities).
So in my controller action I have a mapping (AutoMapper) between a view model and a user entity and a mapping (AutoMapper) between the view model and an openid entity. After that
I save each entity with the service function.
I miss something - like a custom DTO (I don't think that viewmodel should be shared between the service layer and the web layer) which will be passed between the web and service layer.
2.) I have a search functionality in the application. From the controller action I call the service layer which returns me the list of document entities which matches search criteria.
But again the problem is that I also want to display category (different entity) for each result. So in the controller action I am looping between the results and add the category info
into IDictionary structure in the view model.
I also miss something here - again some DTO which will return list of pairs (new object): document, category.
Is the DTO right pattern? Should I take a look at the DDD? Any related material will be appreciated.
Many thanks!
I don't think you are missing a layer in your application architecture, but it sounds like you are missing some types (classes).
Should you create more DTOs? No, I don't think this is a good idea. IIRC, the original definition of DTO was to transfer data across process boundaries. WCF Data Contracts are a good example of DTOs. However, since DTOs are simply messages, they don't contain any behavior. If you base you internal API on DTO it will lead to an Anemic Domain model.
You should still seriously consider adding new types to your application to capture your needs. Where should such types go?
That depends. If you can say that the type in question encapsulates a general-purpose concept, it belongs in a Domain Model. If it only exists to support a given (user) interface, it belongs in that layer.
In your second example you need to combine Document and Category, although they are separate entities. Does this combination encapsulate a recurring concept? If so, it belongs in your Domain Model. If not, it belongs in your UI layer.
If in doubt, place the new type in the outer layer (your UI layer). You can move it to your Domain Model with relative ease if it turns out that it is a more general concept than you first imagined. Moving the other way is harder becuase the type may already have polluted the Domain Model, so starting in the outer layer is the safest option.

Resources