Right now I have a few layers to my project: Core <> Repository <> API... and I'll be building a "client" MVC web project layer. My question is - where do viewModels belong in this architecture?
Should the controller methods of the Web Project call the API (multiple times - getTheseObjects, getThoseObjects) to get data, and then build the viewModel? Or should the API support calls to construct the viewModel so that only one API call (getAllObjectsForThisPage) needs to be made per page for the application?
Your view models will belong in your client MVC app. They will be specific to the views in that individual client application, and usually will get populated by domain objects.
This is how it can work: the controller mediates the https requests thus calls a API endpoint and receives some data or domain objects, which in turn you use to populate your view models.
Take a look at automapper if you are returning domain objects from your api, it really helps with mapping domain object to view models.
You can place ViewModels into your MVC application, but you could create something that is called DTO (Data Transformation Object) and return that from Web API to your client. In essence it will be a class with only the necessary information that you pass to the client. If you want to call that ViewModel you might as well go ahead and call it like that. My suggestion would be to issue one call and to return all the necessary information. One call one trip.
My practice usually is to separate ViewModel from MVC and store it in some other project. The service layer would prepare a ViewModel and return it to MVC. The reason for this is that once I had a requirement to build WPF application after MVC was completed. It was quite a pain moving things around and retesting everything to make sure that it still works fine.
Related
Gurus,
Am newbie in MVC. I am developing a web application for an Order Management System. I have devised architecture to have the following projects as part of my solution:
Client (Presentation layer, MVC)
CrossCuttingServices ( framework components like logging, caching, Data, Class lib)
Data (Entity framework layer for DB interation, C# class lib)
Services (Services layer to be consumed by Presentation, Web API)
Q1. My question is, where should I create my entity classes or Models, which will be used across Presentation to Services to Data? Either in models of Presentation or in Web API service layer or as a seperate project (C# library)?
Q2. Also, let me know is there any generic implementation to invoke WebAPI services from Presentation controller.
Q1: You will be using the same entities throughout the entire solution so I recommend storing them in your Data project since it keeps all database related stuff bundled together separately from the remaining logic.
Q2: You could always send a request to the APIs to get the resulting data, it's essentially what they're there for.
I have decided to go with Architecture like
1. JS Enabled Presentation (webform or only HTML + JS)
2. Web API (Controller calling data services (EF+Repo) as my service layer for data, it can support my browser based front end and devices
Let me know any drawbacks on same
We have a similar problem, with a pretty complex domain model. As a result we have opted for
data entity models defined in a separate DomainModel DLL
UI mapper classes that map from datamodel to UI models
WebAPI mapper classes that map from datamodel to WebAPI models
An example of why we want this?
UI has concept of distributor catalogue item, which is a specialisation of catalogue item
WebAPI uses the basic catalogueitem datamodel, but then returns different data based on the specific resource [eg a search URL returns item ID and basic info; an item lookup URL returns full details for the catalogue item.
As a result of the above, the catalogueitem in our DomainModel is the full complete object, which the different "clients" then map as they see fit.
[This is in line with what Filip Stankovski said above]
While I'm reading the book "ASP.NET MVC 4" I'm wondering about MVVM. I started googling and cannot find any books about developing web applications using MVVM, so I must be missing a bit of information here.
From what I understand, MVVM is used in web applications on the client side via knockout.js and other frameworks.
If however I was to develop a Windows Phone application, I could use MVVM directly without using MVC.
Does that mean, the concept of MVVM / data binding just does not apply to client-server web applications?
MVVM is really sort of a subpattern. There's not really any "MVVM" web app frameworks out there. They're all MVC and you pretty much just incorporate a view model if you want one.
With ASP.NET MVC, in particular, you just create a class, generally with a name in the form of [Model Name]ViewModel or [Model Name]VM. That class will have only the properties from your model that you'll need to work with and anything extra that doesn't make sense to put on your actual database-backed model, like SelectLists, etc.
In your action, you just pass an instance of this view model to your view instead of your model:
return View(viewModelInstance);
And, of course, make sure your view accepts that:
#model Namespace.To.MyViewModel
The only slightly complicated part is wiring the view model to the model (i.e., getting data to/from the view model/model. You can do this manually by explicitly mapping the properties, or you can use something like AutoMapper.
MVVM is the standard design pattern for WPF/Silverlight development, and should not be confused with MVC for ASP.Net development.
The two may sound similar and share some common parts, but they are two different design patterns.
From what I learned about knockout.js, it was designed to create "data bindings" similar to what you would use in WPF/Silverlight development, which is why the MVVM design pattern applies there.
To quote from another answer of mine regarding the differences between MVVM and MVC
In MVVM, your code classes (ViewModels) are your application, while your Views are just a pretty user-friendly interface that sits on top of the application code and allows users to interact with it. This means the ViewModels have a huge job, because they are your application, and are responsible for everything from application flow to business logic.
With MVC, your Views are your application, while your Controller handles application flow. Application logic is typically found in ViewModels, which are considered part of the M in MVC (sidenote: the M in MVC cannot be considered the same as the M in MVVM because MVC's M layer contains more functionality than MVVM's M layer). A user is given a screen (View), they interact with it then submit something to the Controller, and the Controller decides who does what with the data and returns a new View to the user.
MVC is a one-way data-binding system.
Fill your Model in Controller, then pass it to View.
MVVM is a two-way data-binding one.
Fill your Model, use it in View, when the View state's changes, your Model update automatically.(Vice-versa)
Does that mean, the concept of MVVM / data binding just does not apply to client-server web applications?
No, you can apply the MVVM pattern to client-server web applications.
In fact Asp.Net MVC actually kind of does use this pattern - when the controller creates the view, it can pass in a "view-model". This view-model is often a POCO data object with all the data that a particular view needs, drawn from the model (database). The view uses this data to render the html page.
MVVM on wikipedia says it was introduced by Microsoft with WPF. Specifically, the view binds to properties on the view-model. The view-model then maps this to the database. By this definition then, Asp.Net does not exactly match that. Client-side frameworks like knockout.js and vue.js do support this kind of 2-way binding with view-model properties.
All these patterns are based on the fantastic MV* pattern. It was originally called the MVC design pattern. So this is the exact same pattern as Asp.Net MVC then? Actually, not quite. Controller means something completely different to start with (see MVC on wikipedia). The original MVC controller handles all user input directly not via the view. Second, the original MVC pattern was designed for a desktop app GUI and Asp.Net MVC adapted the pattern for use in a client-server web app. An ASP.Net controller is a collection of http end-points which the client-side html page can hit (eg form-post, page-navigation, ajax).
So there are a lot of M-something-V patterns and the general pattern is often called the MVC design pattern.
There's one more important wrinkle: client-side vs server-side. We've introduced rich client-side javascript frameworks and the fantastic MV* pattern is great here too. So now we could have something like: client-side View-Model-ServerHTTPEndPoints and server-side ServerHTTPEndPoints-ServerModel. The server-endpoints refers to Asp.Net controllers or the equivalent in whatever web framework or programming language you are using. From the server-side point of view, the entire client-side html is the view. The client-side model talks to the server ajax api (http endpoints) to sync data or trigger advanced actions. The ServerModel is normally a database. In knockout/vue, instead of client-side "Model", it would be ViewModel. If you use react/vue with redux/flux then the client-side would be View-ViewModel-Model-ServerHTTPEndPoints where the Model would be the redux/flux Stores. Also, often on the server-side, a service is introduced: ServerHTTPEndPoints-Service-Model. This way unit tests can hit the service directly rather than firing up the entire web server and making HTTP connections.
I have used MVVM in desktop applications and I have a property in my viewmodels named Model where I store a business object as the model. My views have a property named DataContext where the viewmodels are stored before the views are loaded. A view bind its controls to the business object using the path DataContext.Model.BusObjPropertyName. I have a UserInteractionService that register from the start the relationships between views and viewmodels. When a viewmodel needs to show another viewmodel, it calls the method ShowView in the UserInteractionService and pass the viewmodel as parameter. Then the service instantiate the view corresponding to the viewmodel received, set its DataContext property with the viewmodel and show it.
If it is possible to do the bindings to a path like that above in Asp, all this model can be reused either in desktop as in Web applications.
I'm about a month into MVC and from what I understand, a pretty good approach to app architecture is:
MVC <> Service <> Repository <> Core
Within MVC we have Views, and Controllers to populate viewModels for the controllers. My question is: Where exactly to Data Transfer Objects come in? I'm building a single-page web app and I'm trying to do it right from the beginning.
From the reading I've done, I should use DTOs to "flatten" the Model objects before passing them into the ViewModel. Do they act as a "only data that I need" object that gets passed from the service to the controller, at which point the viewModels are constructed? If so, is it generally true that each model definition (ie Sets, Cards, Users) should have corresponding DTO classes in the Core layer? Any clarifications here would be awesome, thank you for your time!
First of all, about this phrase: "a pretty good approach to app architecture is...": I don't believe there is a single good approach to all apps, and I would prefer always to use the simplest approach (i.e. fewer layers) that could solve your problem at hand.
When you say "Service", it appears to be a whole layer of web services, rather than just some domain service classes; in most cases I've seen with Asp.Net MVC, the controller itself can fulfill the role of a service, thus eliminating the need to add yet another layer. Of course there are exceptions, just be sure your reason to increase complexity is legitimate.
About DTO's and View models: DTO's, like you described, flatten the object model and return "only data that I need". DTO is a more generic term, usually used with web services where you don't know who is the consumer. Think of (Asp.Net MVC) View Models as a more specialized kind of DTO, that returns "only data that THE VIEW needs". Thus, if you don't need an extra layer of services, you also don't need an extra layer of DTO's, just use View Models to flatten the domain classes directly and return them from your controllers.
In fact, for very simple applications, even the separation of Models x ViewModels is overkill - it is possible to use a single Model layer to fulfill both roles, with the help of the ViewBag. I don't know your requirements, so I can't say which is better for you.
Finally, one comment: if you must build a single page application, Asp.Net MVC is not the best tool for the job. I'd recommend using Asp.Net Web Api (only services, no views) at the server and a client mvc framework, such as BackboneJs or AngularJs.
The project I'm currently working on has a Core API which is used by everything: services, web, ...
This API has following layers:
Core
Core.Models
Core.DataProviders
Core.DataProviders.LinqToSql
Core.Utils
On top of this API is my ASP.NET MVC application. This looks like this:
Web
Web.Models (Some Web specific objects and logic. For example a class which builds a list of quarters to help me render a day in a scheduling table.)
Web.Extensions (Html Helpers, Controller base..)
Web.ViewModels (Composite objects to pass to the View.)
Web.Services (Layer which communicates with the Core and Web.Models. This layer builds ViewModels for my Controllers. Helps keeping my Controllers clean.)
Any serious flaws in this setup?
A more specific question: I need to parse some things coming from my View before I can pass them to the Core. Should I handle this in the Controller or in the Service layer?
Generally speaking data submitted from the view should be parsed by a ModelBinder, falling back to the Controller if using a ModelBinder doesn't seem to make sense.
Parsing in an application service makes sense if multiple sources can submit the data in the same format (like web service or file system persistance).
So I have a MVC app and in another project I have a normal collection of classes which handle the Business and Data logic for the application. I also have some logic in the Model of the MVC project itself. This logic handles ViewModels and the like, things which could not have been done in the n-tier project as they relate to the MVC project itself and need to be in the same project.
My questions are:
Should my model classes have knowledge of the n-tier business logic? Or should only the controller have this knowledge and send data back and forth between the n-tier application and the MVC model as needed?
If it's ok for my model to reference the n-tier application, then should my controller access n-tier via the model class?
Hope this makes sense, found it difficult to word correctly to get my point across.
Generally speaking here - Your model classes should not have business logic knowledge. They should have only the information required to display the view to the user (use DTOs as suggested by mxmissile).
Your business logic would either be in your controller, or (better) in a separate service layer called by your controller. Having methods on a model that, for instance, bypass the controller and make calls directly to the database is almost always a bad practice.
The idea here is to make the views as dumb as possible. You send them a model, they pull out the data they need, format it appropriately, and display it. This makes it much easier to create new views of the same data later if you decide you want to change the presentation.
Think of your models as only containers for data between your controllers and your views. Essentially DTOs.
Your ViewData/ViewModel classes in your MVC application may contain instances of your Model classes (mine do). My controllers call my business services and are responsible for any translation between ViewData and Models.
If it's ok for my model to reference
the n-tier application, then should my
controller access n-tier via the model
class?
I wouldn't go through the model to get to the application tiers, I would have the controller be that interfacing component. The controller calls to your application tiers which return instances of your Model from your data access components. You can then translate those instances into more consumable objects by using a ViewData/ViewModel object. You can do this in a controller, or use a separate assembler class.