Is it ok to have database context in my domain model - asp.net-mvc

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.

Related

Where do models belong in my solution?

This is the first time I'm doing a web project using MVC and I'm trying to make it based on three layers : MVC, DAL (Data Access Layer) and BLL (Business Logic Layer).
I'm also trying to use repositories and I'm doing it code-first.
Anyway I've searched a lot on the web but yet if you've got a good reference for me I'll be glad to see it .
My current project looks like this:
And here are my questions:
Where are the Product and User classes that represent tables supposed to be? It seems that I need to use them in the BLL and I don't really need them in the DAL but for the PASContext.
Where do I initiate the PASContext? In all of the examples I've seen on the internet no one made a constructor in the repository that takes 0 argument, which means that the context is not created within the repository (and I've read some reasons why like so all repositories will use one context).
If I'm trying to initiate the PASContext in the ProductBLL the compiler says it doesn't recognize it and I'm missing a reference (although I've added the needed reference and the name PASContext is marked in a blue like vs did recognize it)
PASContext is the class that is inherited from DbContext.
Here is some code to demonstrate:
public class ProductsBLL
{
private EFRepository<Product> productsRepository;
private List<Product> products;
public ProductsBLL()
{
PASContext context = new PASContext();
productsRepository = new EFRepository<Product>(context);
//LoadData();
}
About the View models, if I want, for example, to present a list of products for the client, do I need to create a ProductViewModel, get the data from ProductsBLL which has a list of Product and convert it to a list of ProductViewModel and then send it to the controller?
In addition, in the ProductController, do I only initiate ProductsBLL? I don't initiate any repository or context, right?
If someone could show me some project that uses repository, three-tier architecture and takes data from the database, transfers it to the BLL and from there to the MVC layer and using a ViewModel show it to the client it will be great.
Question 1
Where are the Product and User classes that represent tables supposed to be?
I would have these in a project that can be referenced by all other projects. That is, all other projects can depend on the solution with the models. In the case of onion architecture the models belong in the core which is at the center of the solution.
In your case I'd put them in the BLL.
Question 2
Where do I initiate the PASContext?
The reason why you don't normally see this done directly is because it's very common to use Dependency Injection or DI (What is dependency injection?)
This means that you don't need to instantiate a DbContext directly; you let the DI container do it for you. In my MVC applications the context has a PerWebRequest lifestyle.
PerWebRequest Lifestyle:
Instance of a component will be shared in scope of a single web request. The instance will be created the first time it's requested in scope of the web request.
A context is created when the request is made, used throughout the request (so all repositories gain the benefits of the first-level caching) and then the context is disposed of when the request is completed. All of it is managed by the DI container.
Question 3
do I need to create a ProductViewModel [...] ?
You generally only have one view-model to give to a view. The view should be its own object that has all of the things that the view needs in order to display everything. You suggest that you create multiple view-model objects and pass that to the view. My concern with that approach is what happens if you want to display more information for that view? Say, you want to display a single DateTime object to the user. Now you want to display one of something but you're passing many objects to the view.
Instead, separate things up. Create a single view-model and pass that to the view. If you have a part of the view that needs to display many of something, have the view call it as a child action or partial so that the view isn't doing too much.
Your approach:
A different approach:
Conclusion
If someone could show me some project that uses [...] three-tier architecture
I'm not sure about three-tier architecture. Here are some example projects that use a variety of solution architectures:
MVCForum
EFMVC
Official MVC samples
There is no single correct approach - just good and bad approaches.
I would start here. You'll get a lot more information on broad topics like this from prepared resources sources.
http://www.asp.net/mvc/tutorials/getting-started-with-aspnet-mvc3/cs/intro-to-aspnet-mvc-3.
Update
In-depth tutorials
http://www.codeproject.com/Articles/70061/Architecture-Guide-ASP-NET-MVC-Framework-N-tier-En
http://www.asp.net/mvc/tutorials/hands-on-labs/aspnet-mvc-4-models-and-data-access
http://www.asp.net/mvc/tutorials/getting-started-with-ef-5-using-mvc-4
http://www.codedigest.com/Articles/ASPNET/187_How_to_create_a_website_using_3_tier_architecture.aspx
http://www.mvcsharp.org/Basics_of_MVC_and_MVP/Default.aspx
Example Projects
http://prodinner.codeplex.com/
http://www.nopcommerce.com/
http://www.mvcsharp.org/Getting_started_with_MVCSharp/Default.aspx

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 Business Logic in Domain Model vs Service Layer

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

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.

Do roles/views belong inside or outside of the Repository Pattern?

Does role / view logic belong inside or outside of the Repository Pattern?
For example, I have a table of products, and each product has 5 price fields - one for each type of customer (wholesale, retail etc).
I only want to show the appropriate price to the appropriate user.
If I have a repository of these products, should the Product business object returned, contain all 5 prices, and somehow only display the relevant price?
If so, what is a good pattern to use?
Should I perhaps create a view object, which takes a business object and a role and determines the right price to show? Or shall I put that logic inside the business object?
(FYI: I will be building the solution in ASP MVC if you think it will help frame the response)
Yes, your repository should return all five prices, and your objects should contain the business logic that decides which customer receives which price. The objects should be capable of making this decision regardless of where their data came from.
This approach will also allow you to test your pricing logic independently of your data access concerns - for example, by using a 'dummy' repository, by manually creating a product with the five price fields already populated, or by using a mocking framework to mock your repository calls. Moving this sort of logic outside your business objects - e.g. putting it in your data access layer - can lead to an anti-pattern known as the Anemic Domain Model.
EDIT: In response to your comments:
The term "repository" specifically refers to a data access pattern that returns fully-populated collections (aggregates) of business objects. If you find that returning DTOs is a better solution for your problem, then go ahead and do so, but you may confuse people if you use the term "repository" to refer to other data access patterns. Personally, I'd stick with the repository approach and return fully-populated business objects, because I prefer working that way, but as with so much, it depends on the scale and complexity of the system you're building.
To expose your pricing logic, you probably just want to use a method like:
public class Product {
public decimal GetPriceFor(User user) {
// logic to determine per-user pricing goes here:
}
}
One approach is to create a service layer that contains your business logic. The service layer interacts with the repository applying any rules or filters that you require. This means anything returned from the service layer is just a plain c# object (POCO).
After designing some products with an extra data access layer, I would say: Design it with the functional dependencies in mind!
Suppose you have the following very common structure for the data dictionary: productName, productDetail, productPrice, customerName, customerDetail.
One can easily identify the relations: Customer and Product.
class Customer: customerName, customerDetail
class Product: productName, productDetail
But there is a third relation to draw, it is
class CustomerProduct: customerName, productName, productPrize
Because you can reason that only customerName X productName |-> productPrize. For the use case Customer C wants to know the price of product P:
Customer('C').prize('P')
The method prize must be delegated to know the exact prize and you have a clean separation of concerns. To be clear about the point: the BO will show no prize to the customer. Just the method has access to the delicate data. And this access you can restrict.

Resources