I've been doing mvc for some time, but it's my first contact with DI.
I started a new project with Ninject which seems pretty simple and easy to understand, however almost every tutorial I saw has UoW, Repositories and Services.
What I understand is that:
Repositories - Abstract Layer for interactions with EF / MongoDB / XML / Whatever may be a database (CRUD Operations)
UoW - Set of operations that correlate together, it may use N repositories to perform tasks that will be used in Controllers
Services I don't really get the point of this, it seems just one more step as it uses multiple UoW's to perform "more tasks"? I'm lost in this one.
Ok, it took me some time to "eat" the Repository thing since i prefer to pass the EF Context trough the UoW.
Is it ok if i forget the Repository and just use the context? Or is it used for any Unit Test task?
What's the Service's usage?
Since I may perform every actions/tasks inside UoW and then call it inside the controllers.
Is there any better set of patterns to use?
Since these are very common and you might be talking about either, I'm going to give a brief explanation about each.
Domain Services: When you have an entity and you start to push logic into it, you might get to a point where part of the logic doesn't really belong to that entity, so you create a Domain Service to abstract this logic away. An example would be:
public class Shipment
{
...
public void CalculateFee(IFeeCalculatorService feeCalculatorService)
{
... Any additional and entity relevant logic for fee calculation can be here as well.
this.Fee = feeCalculatorService.Calculate();
}
...
}
Application Services: These are the services that you will be calling from your controllers to encapsulate the operations needed for a specific task. Let's say you have a controller to receive a friendship request approval or rejection. Your Application Service should receive enough data to be able to:
Find the friendship request domain entity
Call its approve or reject method
Call the methods to persist that change back to the database
Return relevant information to the controller
Infrastructure Services: These services will abstract the logic that is not related to the business, but related to how the application works. An example would be a service to validate security tokens received on your requests, or to perform logging activities.
EFs DBContext already implements both the UoW and Repository patterns, so yiu have no benefit of implementing those again in yiur own code.
Services are a way to abstract business logic so it can be reused
Related
My application is using DDD with .NET Core and EF Core. I have some business rules that run within an entity that need to check dates against a cached list of company holiday dates. The company holidays are loaded from the db and cached by an application service that is configured with our DI container so it can be injected into our controllers, etc.
I cannot determine how, or if it's the right/best approach, to get the service injected into the entity so it can grab those dates when running business rules. I did find this answer that appears to demonstrate one way to do it, but I wanted to see if there were any additional options because that way has a bit of a code-smell to me upon first glance (adding a property to the DbContext to grab off the private constructor injected context).
Are there any other ways to accomplish something like this?
ORM classes are very rarely your domain objects. If you can start with your domain and seamlessly map to an ORM without the need for infrastructure specific alterations or attributes then that is fine; else you need to split your domain objects from your ORM objects.
You should not inject any services or repositories into aggregates. Aggregates should focus on the command/transactional side of the solution and work with pre-loaded state and should avoid requesting additional state through any handed mechanisms. The state should be obtained and handed to the aggregate.
In your specific scenario I would suggest loading your BusinessCalendar and then hand it to your aggregate when performing some function, e.g.:
public class TheAggregate
{
public bool AttemptRegistration(BusinessCalendar calendar)
{
if (!calendar.IsWorkingDay(DateTime.Now))
{
return false;
}
// ... registration code
return true;
}
// or perhaps...
public void Register(DateTime registrationDate, BusinessCalendar calendar)
{
if (!calendar.IsWorkingDay(registrationDate))
{
throw new InvalidOperationException();
}
// ... registration code
}
}
Another take on this is to have your domain ignore this bit and place the burden on the calling code. In this way if you ask you domain to do something it will do so since, perhaps, a registration on a non-working day (in my trivial example) may be performed in some circumstances. In these cases the application layer is responsible for checking the calendar for "normal" registration or overriding the default behaviour in some circumstances. This is the same approach one would take for authorisation. The application layer is responsible for authorisation and the domain should not care about that. If you can call the domain code then you have been authorised to do so.
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.
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
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.
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.