I have some common functions that apply throughout my application to update particular parts of the database when actions happen (Audit trail, modified dates etc). I'll use AuditTrail as an example.
Where should I be storing these functions?
Currently I am storing them in dbcontext classes
//... my db context class ...
public bool AddAuditEntry(int ID, string objectName)
{
// Here I create a new AuditTrail object, assign values then insert into db.
// This mode doesn't have a controller.
}
// We also have a table that keeps track of modified state for
// client side caching (nothing I have control over)
public bool ModifyObject(int ID)
{
// Here I mark the object id with modified date then save to db
// This particular model doesn't have a controller either.
}
I think they should belong in the model but I'm not quite sure how to implement it. Putting them in the controller isn't the best option as some of these relate only to a particular model class that may have no controller.
My problem with them being in the model is what then is the best way to update entities?
I'm not sure if this is the way other people do it but I actually have two models. I have my business models which contain these kinds of functions and validations. Stuff like an account balance cannot be less than zero or something like that. Once all that's done the models are translated into database models which are responsible for database level validations if necessary and database operations.
Related
I've researched about MVC for a while and similar questions like this and this.
They, however doesn't answer my question. In a lot MVC examples (Both ASP.NET MVC and JAVA MVC) They usually provide the Model with fields E.G (Name, Age etc) and then allow the view to "read" those fields.
But from what I've understood is that the View should not know about the Model, cause if the View does then it's not (correctly) encapsulated.
Pictures however shows that the View knows about the Model to display correct data.
If I understood correctly is that the Model can be business logic for a system and the View is not supposed to be connected to that.
Lets say that my Model fetch data from a database, then it's still my Model that is my business logic and not the database or am I thinking wrong?
So my questions is
Should the View know about the Model to use correct data?
Is the Controllers job to fetch data from E.G a database and create a Model from that, and the View should use the Model data for display?
What is Model Business Logic? (Please don't use fields to explain)
a lot of this is open to interpretation. There are a number of approaches and is down to which ever suits you best. My approach is below if its some help.
Should the View know about the Model to use correct data?
Yes. The view has a model import directive for it to bind to when it's rendered. If the view didn't know anything about the model it was accessing then how could it bind to the data.
Is the Controllers job to fetch data from E.G a database and create a Model from that, and the View should use the Model data for display?
No, the controller should no nothing about the implementation of the data layer. The controllers only job should be to invoke the services that it needs to build up the view model.
What is Model Business Logic? (Please don't use fields to explain)
Not to sure about the exact term "Model Business Logic". Model can be used to describe domain models or in this case View models. Business logic are operations you perform on business or domain model objects populated by some service.
The way how i handle ViewModels and business logic as you say is to separate out the domain model, e.g. Customer or Order in a separate dll and have those domain objects populated by a service. Then your View Model becomes a composite of domain model objects.
So in all.. the controller makes a call out to services that consume datalayers which in term return you populated domain objects. These can then be used to populate your view model which is then used by the view.
I've added below a very simplistic look at approach which will hopefully point you in the right direction.
public class MyController
{
[HttpGet]
public ViewResult GetCustomer(int customerID)
{
var myViewModel = new CustomerViewModel();
var myService = new MyServiceLayer();
var myCustomerDetails = myService.GetCustomerDetails(customerID);
myViewModel.Customer = myCustomerDetails;
return View("CustomerDetails", myViewModel);
}
}
public class CustomerViewModel
{
public CustomerDomainObject Customer { get; set; }
}
public class CustomerDomainObject
{
public string Name {get;set;}
}
public class MyServiceLayer
{
public CustomerDomainObject GetCustomerDetails(int customerID)
{
var myCustomer = new CustomerDomainObject();
var dataLayer = new MyDataLayer();
var myCustomerData = dataLayer.GetCustomerDetails(customerID);
var myDataRow = myCustomerData.Tables[0].Rows[0];
myCustomer.Name = myDataRow["Name"].ToString();
return myCustomer;
}
}
public class MyDataLayer
{
public DataSet GetCustomerDetails(int customerID)
{
//Execute proc etc...
return new DataSet();
}
}
In ASP.NET MVC you have strong typed views. This is a razor thing that let you access to your model properties easily when you are building your view. You will easily notice this since IntelliSense will work whenever you are trying to access a property like #Model.Name. If it should or not be strong typed, IMHO it just relay on what you need, there are not cons on using strong typed views. It will help you big time whenever you code your views, and you will have less runtime errors for sure.
For 'Model Business Logic' I would say that you can for sure have a lot of Logic in your model, but that is not as simple as it sounds. You will probably have to work with patterns and have small classes which responsible for one thing.
Look at this link: https://msdn.microsoft.com/en-us/library/hh404093.aspx
Generally speaking it's a good idea to completely separate the domain model from its view representation. Domain model contains the entire business logic, which can be quite complex. Also, the presentation layer usually requires extremely simplified objects (just data structures, without any business logic). Specific view technologies might apply heavy restrictions to the objects. Besides of that, we often change/aggregate domain objects to suit the final user specific needs (by creating specialized DTOs). Therefore, since presentation and domain layers are so distinct (and domain model should never depend on view), I often completely separate them. This allows to create a more supple design.
I'm doing 3 tier application using asp.net mvc and I want to do everything as recommended.
So I've done MvcSample.Bll for business logic, MvcSample.Data for data and MvcSample.Web for website.
In Data I've my edmx file (I'm using database first approach) and my repositories. And in Bll I'm doing services which will called in web.
So my question is that:
Should I write other models in Bll or use that ones which are generated in edmx file?
It heavily depends on the type of problem that your application is trying to solve.
From my experience, it is very rare that the business logic returns model objects directly from Entity Framework. Also, accepting these as arguments may not be the best idea.
Entity Framework model represents your relational database. Because of that, its definition contains many things that your business logic should not expose, for example navigation properties, computed properties etc. When accepting your model object as an argument, you may notice that many properties are not used by the particular business logic method. In many cases it confuses the developer and is the source of bugs.
All in all, if your application is a quick prototype, proof of concept or a simple CRUD software than it might be sufficient to use EF model classes. However, from practical point of view consider bespoke business logic model/dto classes.
From my point of view you need another model for your Bll.
That would encapsulate your Bllcompletely.
I think there is no right or wrong answer for your question.
In my experience, I used both.
Let's see at below example:
I have an User table
public class User
{
public int Id{get;set;}
public string First_Name{get;set;}
public string Last_Name{get;set;}
public int Age{get;set;}
public string Password{get;set;} //let's use this for demonstration
}
I have a Method call DisplayAll() in Bll. This method should list down all users in my database by Full Names (FirstName + LastName) and their Ages.
I should not return User class because it will expose the Password, but rather, I create a new Class UserDto
public class UserDto
{
public string FullName{get;set;}
public int Age{get;set;}
}
So here is my DisplayAll():
public List<UserDto> DisplayAll()
{
List<UserDto> result = ctx.User //my DbContext
.Select(x => new UserDto()
{
FullName = x.First_Name + " " +Last_Name,
Age = x.Age
}
return result;
}
So as you can see, my method DisplayAll() uses both User and UserDto
My approach will be
MvcSample.Data
-- Model Classes
-- EDMX attach to model
MvcSample.Bll
-- Model Inheriting MvcSample.Data.Model
-- Business Logic Class - Using MvcSample.Bll.Model
MvcSample.Web
-- Controller using MvcSample.Bll.Model
It depends on your view about software design and how you want to take advantage of it. by separating BLL model, you will have your freedom to put story specific validation and calculation. By using only DLL model, it is sometimes tough as it is going to take effect in DB.
You can use 3 tier architecture in asp.net in this way
MvcSample.BLL - business logic layer
MvcSample.DAL - Data access layer
MvcSample.Domain - Domain layer
MvcSample.web - website
All your repository classes are including in .BLL layer.That means your logics are stored here.
Usually .DAL is used for storing .edmx classes. .Domain is using for recreate database objects that are useful for server side.That means if you are passing a json object from client to server,Then that object should be create on the server side.So those classes can be implement in the .domain
I wonder how could I solve the following case : there are a form on website where manager input very big amount of data to Viewmodel and pass to server-side.
class CitizenRegistrationViewModel {
public string NationalPassportId { get;set; }
public string Name { get;set; }
public List<string> PreviousRegisteredOfficeCodes {get;set;}
// about 30 fields like strings, Booleans, HttpBasedFiles (pdf,jpg).
}
And the problem that in domain this data need to be logically separated and stored in different tables (classes in EF) like CitizensNationalPassportsTable, CitizensWorkingPlaceRecordsTable, etc. There are no complex class Citizen with properties like :
public class Citizen {
public ICollection<CitizensWorkingPlaceRecords> workingPlaces
// etc...
}
but this properties are separately stored in different tables with no one-to-one or one-to-many relations (no FK here) . The only NationalPassportId property could be used as navigation key (unique per user and all records related to user in different tables contains this key).
Should I write big amount of code to parse Viewmodel to domains models like :
public void CitizenRegistrationViewModelToDomainModel(CitizenRegistrationViewModel model){
CitizenNationalPassport passport = new CitizenNationalPassport(model.NationalPassportId);
CitizensWorkingPlaceRecord workplace = new CitizensWorkingPlaceRecord(model.PreviousRegisteredOfficeCodes, model.NationalPassportId);
// 12 extra objects need to create...
db.CitizenNationalPassports.Add(passport);
}
Or is there any more correct approach to handle this problem? I wanted to use AutoMapper, but is it the best solution?
I can't change business models' logic, as it is a legacy project.
You should have a set of classes that represents the data that the browser is exchanging with ASP.NET MVC. Let's name them for example, Input Models. In this classes you have metadata attributes, custom properties and many things that are relates with the exchange between browser and web server.
You should have another set of classes that represent your database structure, those are your Entity Framework POCO classes. Let's name them DB Models. It does not matter how POCO and fancy they are, they always map to tables and columns, so they are always tight to the DB structure.
You should have another set of classes that are your domain classes, the classes you use when operating objects in your business layer.These are binding/persistence/representation agnostic.
You should have a repository that knows how to persist a domain entity. In your case it will be a class that knows how to operate the DB models and the DbContext.
Then, when you get input from your browser, you bind that data to the input models and those are passed to the controller (this is done automatically by the DefaultModelBinder or you can use your own IModelBinder).
When you get an input model, you have to create a new domain entity using that data (in case that is an actual new entity). Once you have your domain object ready, you pass it to the repository to be saved.
The repository is responsible of knowing how to save the domain entity in the database, using the DB models.
In essence, the Controller or the business service instance you operate in the Controller's action context should be responsible of articulate the interaction between these elements without them knowing each others.
AutoMapper or an alternative could be used to automate the mapping from View model to Domain models, but this only makes sense if properties are named identical in View and Domain models. If this is not the case you'll end up writing mapping rules which doesn't help you. It just moves code from your current mapping classes to the AutoMapper configuration. So, if you're in a position to modify your viewmodels I'd go for AutoMapper or anything similar, if not I'd use what you currently have.
I have a question on what's the best design for my domain service. The use case is to create some entities based on user selected conditions.
The workflow of the app that will use this service:
User selects some conditions (like date, and other data)
He gets a list of "propositions" of the entities. He can select all of them, or only some.
The entities are created
What would be the best design for the domain service? I have two in mind:
Solution 1
interface IMyDomainService
{
IEnumerable<EntityProposition> GetEntitiesPropositions(Conditions conditions);
void CreateEntities(Conditions conditions);
}
In this case i would probably have some private method on the service that will be used by both of those. EntityProposition class is basicly 1:1 of what will be displayed in the view. There is some data in that class that is not part of the entity itself.
Solution 2
interface IMyDomainService
{
IEnumerable<EntitiyData> GetDataForEntities(Conditions conditions);
void CreateEntities(IEnumerable<EntityData> entities);
}
What would be the private method in Solution 1 is now exposed in interface. EnityData class holds all data for the entity that is relevant for creating the entity itself and displaying all the data for view.
To add some context:
This service is now used directly by ASP.NET MVC controller. It seems to me, that if i go with solution#2 i will have to create some additional application service, so it will wrap the logic of geting the data and creating entities.
EDIT 1
I will ask the question from different perspective: Should my controller look like this:
public ActionResult GetPropositions(Condtidions condtitions)
{
var entitiyData= service.GetEntityData(conditions);
return Json(entitiyData.ToViewModel());
}
public void CreateEntities(Conditions conditions)
{
var entitiyData= service.GetEntityData(conditions);
service.CreateEntities(entitiyData);
}
or:
public ActionResult GetPropositions(Condtidions condtitions)
{
var propositions = service.GetPropositons(conditions);
return Json(propositions.ToViewModel());
}
public void CreateEntities(Conditions conditions)
{
service.CreateEntities(conditions);
}
Of course this is simplified example, just to show my point.
Edit 2
Just as a followup: Firstly I gone with the Solution #2, but later my requirements changed, and i had to go back to the Solution #1. The reason behind was that after generating propositions, user could select few of them, but withing the same scope (conditions).
What is the most common case? Creating many entities or creating one?
Also I would not use Entites in the method names, it's pretty obvious that a service works with entities.
To me, the name sounds like you are just wrapping a repository with the services. That's a big no-no. Services in DDD is an extension of domain entities to encaspulate logic where you have to work with two or more entities in the same business case.
If you just need to fetch a entity, modify it and save it you should use the repository directly (no need to abstract away an abstraction).
interface IMyDomainRepository
{
IEnumerable<EntitiyData> GetData(Conditions conditions);
void Create(IEnumerable<EntityData> entities);
}
I've searched both SO and Google on this but have not found a relevant / acceptable answer.
Background:
* Using MVC 4.5
* I have some Generic Repo<T> that I am using over the top of EF5, which in turn are accessed by generic Service<T>
* I have domain models and view models and I am using Automapper to map between them, this mapping happens in the Service layer
* On top of that, I have my Controllers which again are generic as much as possible.
So, to the question; I have a couple of scenarios where I need to present a list of options to the user and they have to select one or more. The options are user specific, so my domain User has a List<Location> which is their saved locations, and when adding / modifying, an Item, they are required to select at least one Location.
I am resisting the temptation to fetch that List<Location> in my controllers because I want to keep them generic and slim, but at the same time, I'd rather not have two properties in my ItemView model, one for AvailableLocations and one for SelectedLocations, because this model is used not just for adding / modifying but for search results etc.
Options:
* Should I introduce a different model for adding / modifying an Item, e.g. ItemInput?
* Should I use some custom mapping and get Automapper to get the list of available locations?
* In which layer should I fetch these available locations?
What are people's suggestions on a neat and generic approach to this please?
Many thanks!
I would do something like this:
public IEnumerable<Location> GetLocations() {
return db.GetAll();
}
Then inside of your controller (I followed this from MVC scaffolding):
ViewBag.Locations = new SelectList(service.GetLocations, "name", "id");
(or your own checkbox list)
and put a listing control on the HTML/View page.
The reason I believe this is the best method is because the logic all resides inside the service. If you put it in your DTO/data model you may come against this problem:
What happens if you require additional logic to pull back locations? i.e. sub locations of locations.
You change your service (or override) to reflect the new changes, and this logic would go inside of the service:
public IEnumerable<Location> GetLocations(string parent) {
return db.GetAll().Where(loc => loc.parentname = parent);
}
p.s. I never use generic services, the reason I have a service is because some of the data access it provides contains logic that is not meant to sit with the generic DAL.
I could make an interface or abstract service to make my life a little easier for common operations between services but once you define say a concrete, a UserManagementSerive surely you are saying you want to manage an object that has Users, and Locations and Items each having its own specific functionality?
I don't think there is only one possible answer to this question.
I would recommend a simple, but not-so-generic approach. I would write what's called ViewModels, i.e. model classes that are related to your specific views. Then I would get your available locations from the controller, and populate an instance of the ViewModel in your controller using the fetched locations.
Basically I would expose some services like:
IEnumerable<Location> GetAvailableLocationsForUser(string userName);
Do note I've used IEnumerable<T>, not IQueryable<T>. Because the implementation will actually request the database, as it's too much bug-prone (at least IMO) if it's the role of the controller to do so (remember the deferred execution of IQueryable<T>).
And it returns a domain instance, i.e. an entity, not a mapped model. I wouldn't personally deal with anything but domain classes in the service layer. There could be domain classes that are not entities, but compositions of entities for example. This could help making efficient requests and avoiding using lazy-loading and deferred execution in the controllers. This is helpful when the controller needs a whole object graph and not only an entity.
Then I would write Models and ViewModels like the following, in the web application assembly:
public LocationModel
{
...
}
public CreateItemViewModel : ItemModel
{
public List<LocationModel> AssociatedLocations { get; set; }
public List<LocationModel> AvailableLocations { get; set; }
...
}
There are basically Models (ItemModel and LocationModel), which are objects related to the web application. This means there could be some web-related things in those models, for example computed read-only properties or attributes on properties (DisplayAttribute...etc.).
I would write those models multiple times, actually, because I don't think this is something that could be generalized: for example, one view could require the use of a navigation property while another view wouldn't. So this changes the depth of the mapping process depending on the views that uses the model. And I wouldn't use AutoMapper at all (only hand-written mappers).
There are also ViewModels (CreateItemViewModel), which are objects related to a single view (for example the view that allows to create an Item in this example). The difference between Model and ViewModel is that the ViewModel is related to a single view (and named according to this view). On the other hand, Models are related to multiple views (its namespace would help to know which views. For example, xxx.Item.Models for Models related to all views in the xxx.Item directory). ViewModels are built from scratch in the controller (or in a separate mapper) based on the domain classes.
In the above example, you could build a domain classes that would return AssociatedLocations and AvailableLocations, but it would require your service layer to be aware of the web part (I mean, your service interface and domain classes would know which properties are needed for a particular view). I'm not sure those properties are actually related to a single view in your application, but if it's not the case, you could also build a domain class as a composition of entities that would return AssociatedLocations and AvailableLocations:
public ItemExtended : Item
{
public List<Location> AssociatedLocations { get; set; }
public List<Location> AvailableLocations { get; set; }
}
ItemExtended GetItemExtendedById(long idItem);