I know this question has been asked before. I am only asking so that I can get a better explanation. In my webforms applications, this is how I implemented my projects. The solution had two projects. The first project contains Data Access and Business Logic. The first project is referenced in the second project. The aspx.cs files call the business logic class and the business logic class calls the data access class.
I am trying to follow the same approach in my MVC applicaiton. How would I implement that? Controller calls Model which in turn calls Business logic? This approach would add overhead right?
In reference to the direction the comments are taking this thread (this doesn't fit neatly into a comment):
The models folder that is created with a new MVC project is for View Models - they are classes to support views. These are not your business models or data models.
For instance, in a ViewModel that supports a view, you might have a enum property that renders to a dropdown:
public enum CustomerTypes
{
INDIVIDUAL = 0,
COMPANY
}
public class CustomerViewModel
{
public CustomerTypes Type { get; set; }
public string[] CustomerTypesSelectList { get; set; }
}
public class CustomerController : Controller
{
public ActionResult Edit()
{
var model = new CustomerViewModel();
model.CustomerTypesSelectList =
Enum.GetNames(typeof(CustomerTypesSelectList));
return View(model);
}
}
And with this you have some javascript in your view to populate a fancy drop down list with the items in CustomerTypesSelectList.
The UI-specific string[] property is a common construct of a ViewModel that gets stripped away when it gets converted to the business model or data model. The Controller would control the conversion (a.k.a. mapping), but probably rely on another class to implement the mapping that ties together the ViewModel and the business model.
To sum up, in an n-layer architecture:
The MVC Controller is not your business logic. Your business logic resides inside of various services and components that are called by the controller.
The Models folder contains ViewModels - classes that are meant to support the operation of the UI only.
The Controller calls a mapper to translate between ViewModels and business models when calling into the business layer.
Have your architecture with following things
Data access project - add ORM/ADO.net with repository and unit of work pattern. Repositories can be generated using T4 template from ORM
ViewModel project - have a separate project for Viewmodels (containing properties to be used by view).
Business layer - have classes which contains functions that access repositories from data access layer, join them if needed using LINQ and populate in Viewmodel and return view model object or view model collection to controller.
WEB Project -
Controller - access business layer functions using dependency injection and return view model to view
View - Access view mode returned by controller
Related
I have Api project, business project and database context.
I am thinking of design like this:
viewmodels in api project, and mappings with automapper. Automapper
will here map viewmodel to business dto model
dto models in business project, and mappings with automapper. Automapper will here map dto model to entity model (database).
Question 1: Should I use OperationViewModel or OperationRequestModel(ResponseModel) in api project?
Question 2: Is additional mapping between viewmodel and dto model overkill, or is it good practice to separate those concerns and decouple even more, or should I map dto models with entity models and use those dto models in api project?
Firstly, I would like to congratulate you on 'getting it'. So many projects I see have the database access in the UI layer!!
Initially, you may feel that having different (but almost identical) classes for ViewModel, Business and data layers a pain, but this is where AutoMapper is brilliant. Most of the time, you don't need to do anything and it just works.
Once your code gets a bit more meat on the bone, you will find it easier to add database fields without having to worry about the effects on your view model, and to create view models that are exactly what the view requires, without having to worry about database fields. Win-win. I would also create a separate view model for each function, even if they are identical (use inheritance if required, but make sure you have a different class each time).
IMO, the models should be exposed by the layer that creates and consumes them, so the ViewModel should have XXXViewModel, the businesss layer have XXXDto etc.
public IndexViewModel Index()
{
var vm = new IndexViewModel()
{
Items = _mapper.map<List<Item>>(_service.GetSomeData())
};
return vm;
}
public GetViewModel Get(int id)
{
var vm = _mapper.Map<GetViewModel>(_service.get(id));
return vm;
}
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.
In MVC it's pretty straignforward:
Client makes a request, controller asks buiseness logic to do some fancy stuff, buiseness logic asks repository to return some data, then repository returns data and buiseness logic is responsible for converting data from entities to viewmodels, which are returned to the client.
In MVVM I'm pretty much lost, since the viewmodel itself is responsible for making requests to the buiseness logic, there is no "middle layer" like the Controller. I could implement mappers in the buiseness logic project but since viewmodels are responsible to ask buiseness logic for data, it would create circular reference.
So where do I have to make this "magic" happen?
I'm gonna try to give some context with a simple example.
Be aware that all the code below is conceptual only and written here and not in VS.
Think of your ViewModel as a wrapper for your model.
Your model is exposed by a property so you can bind to it or to it's properties from your view.
Your ViewModel :
public class SomeEntityViewModel : NotificationObject
{
private SomeEntity _someEntity;
public SomeEntity SomeEntity
{
get{ return _someEntity;}
set
{
_someEntity = value;
RaisePropertyChanged("SomeEntity");
}
}
}
Now lets assume you send a request to your server and await a response.
Let's also assume you have an higher object (like a parent ViewModel) which initiates your VM :
public class SomeEntityContainerViewModel : NotificationObject
{
public ObservableCollection<SomeEntityViewModel> Items;
public void async OnRequestNewEntity()
{
SomeEntity newEntity = await _someEntityService.CreateSomeEntityAsync();
var vm = new SomeEntityViewModel{ SomeEntity = newEntity};
Items.add(vm);
}
}
Your SomeEntityContainerView of which SomeEntityContainerViewModel is the DataContext :
<UserControl>
<Button Command="{Binding RequestNewEntityCommand}" />
<ItemsControl ItemsSource="{Binding Items}" />
</UserControl>
Your SomeEntityView of which SomeEntityViewModel is the DataContext :
<UserControl>
<TextBlock Text="{Binding SomeEntity.Name}" />
</UserControl>
In it's most simplistic design :
Your model needs to be "dumb", only data.
Your ViewModel is the closest equivalent to a Controller and it will handle the logic and it is the component that will wrap (not convert) your model in a view model.
In the example above we have some higher object a parent ViewModel which initiates our ViewModel.
That's equivalent to a Controller's scope which has other nested controllers under it in the DOM.
Based on the mvvm-light reference I am assuming a WPF app here.
I the 1st paragraph you mention your business logic (I will call it a service from here) is responsible for converting to the view model. I would say the service should have no knowledge of the view. So in that case the controller (or a mapper called by controller or model binder) would handle the mapping.
In MVVM (my opinion here while trying to draw a comparison for you) the ViewModel acts a lot like the controller as it goes and gets the model, maps and binds to an observable. It is then also the model that binds to the view (the view model that is often used in mvc).
So I think the trick here for you is to move where the mapping should occur. The services should not have any knowledge of the views. They are not coupled to the views then which is a good thing.
In MVVM the "business layer" that you refer to is the "model" - in fact anything after the viewmodel is considered part of the "model". However in any work I've ever done, I've always split this model into n-tier, usually with a controller style class that uses services to retrieve data entities from a data repository.
Where to convert entities/models to viewmodels?
You don't, strictly speaking. The viewmodels can contain the entities (i.e. the VM has an ObservableCollection of them), or a viewmodel can wrap an entity (useful in list controls where you may need to show options or execute actions on a per row basis).
The MVC approach to an entity is a bit dirtier than MVVM, you end up with a richer business model rather than a nice lean entity. In MVVM that "richness" is mostly split out and handled by the viewmodel, and you try and keep the data entity as simple as possible (yes you can include things like validation in the entity, but you should only do it when necessary, other times the validation should be taken care of in the VM or somewhere in the model).
Your question is the wrong way round. The view model represents the logic behind the users interaction with your application, so the question really should be "how does the view model acquire entities and models when user interaction requests them?". The answer is: "With a dependency injection framework, e.g. Ninject". This allows you to scope entities to pages in a WPF app, to web requests in an MVC or WCF app, to singletons in any external console utilities or to mocked objects in your testing framework...and all without your view models knowing or caring about how those entities or the services providing them are being created or work internally.
I'm trying to determine where to place my "Validation Models".
My structure is at the moment:
Web (have reference to Business and Objects)
Controllers
Views
CSS
Scripts
Business (have reference to Data and Objects)
Services
Data (have reference to Objects)
Repositories and EF Context(Code First)
Objects
POCOs (for EF)
Now is my question where to place validation things like a LogIn Model? Should the model be placed in my Web layer or Objects layer? - or should I even store validation models like that?
Thanks in advance!
Models should be placed in your business layer. View models should be placed in your web layer because they are tied to a view. You should have a mapping between your models and view models (to facilitate this task you may use a tool like AutoMapper). Views receive view models from controllers. Validation is performed on those view models.
So:
Web
Controllers
Views
Models (here you may place your view models)
CSS
Scripts
Anything that needs to be validated should go in your Business layer. Validation is a business concern that shouldn't be scattered across layers and shouldn't be tied to a specific application type (web, windows, service, etc).
If you expose your domain model to the application then you can also decorate your entities with validation attributes, but note that if your domain model changes then your application breaks.
Let's say you have an AccountService class in the Business layer, which has a Login method. Login accepts a LoginInput class and returns a LoginResult class:
public class LoginInput {
[Required]
public string Username { get; set; }
[Required]
public string Password { get; set; }
}
public class LoginResult {
public bool Success { get; internal set; }
public string Error { get; internal set; }
}
Both of these classes can be used as ViewModels, so you don't need to create any ViewModel in the Web layer, and you certainly shouldn't put validation logic in them.
In my ASP.NET MVC app, I have a fairly complex edit page which combines a number of models into one view.
I'm using the ViewModel pattern to combine all of this information and present one cohesive object to the View.
As an example, my ViewModel structure is something like this:
CompanyId
CompanyName
List<Employee> Employees
List<ContactMethod> ContactMethods
The Employee object has a number of basic properties, and a preferred contact method.
On the edit page, the user is given all of the employees of the company and they have the ability to add and remove (using javascript), as well as edit employee details. The ContactMethods list is used to populate the dropdown for each employee.
I've successfully translated my Models (read from the database) into this ViewModel and back again, so after an edit, I'm left with a ViewModel representing the current state of that company's employees.
I'm using a Repository pattern to communicate with the database, so my question is, should I call directly into the CompanyRepository, passing the ViewModel, or should I convert the ViewModel back into Model objects first before using the Repository to write them to the database?
In short, should the Repository know about my ViewModel objects?
I would convert the ViewModel back into Model objects first. I like keeping the dependency between my Web layer and Repository layers as loose as possible.
I don't think your Repository should know about your ViewModel, since that's a web level concept.
ViewModel is the model to the view (UI), so repository shouldn't know about the view model. Separating them will keep repository loosely coupled from the UI.
Use another layer like service layer, to encapsulate repository from the UI.
This layer also does the ViewModel - Model conversation and do respository call.
public class ServiceLayer
{
public void SaveModel(ViewModel viewmodel)
{
var model = viewModel.ToModel();
repository.Save(model)
}
}
I would agree with the previous answer of converting ViewModels back into "plain" Models, but would add that this task should probably be carried out by a separate service layer. This layer would be responsible for disassembling your ViewModels and acting appropriately.
This is essentially the definition of a service: something whose job is to carry out a logical unit of work that requires multiple models and/or complex logic.