mvvm confustion with the model and business layer connection - c#

So I have been searching for a while and all my searches on the model portion are just confusing me.
I have been seeing many examples where the view model has a direct reference to the model and then sets the model's member variables. However isn't the model supposed to be a business object so that the business layer can do calculations with that data?
So...
1) Should I share the model between both UI and the Business layer so both are referencing the exact same objects (shouldn't each layer "hide" their contents from each other in which case this wouldnt be the best).
http://blog.trivadis.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-01-50/1856.distributed_5F00_domain.png
2) Or should the model be in the business layer. Then the UI makes calls from the view model using provided business interfaces to access model info? This way the model itself is hidden from the UI. Similar to option 1's image except there would be some interface accessing the models and services.
3) Or UI does have the model. BUT I can see many occasions where the business layer would need this information resulting in multiple models which look relatively the exact same are made. Imagine that the entire picture below resides in the UI. Then there is a business layer below the model which the model accesses.
http://rarcher.azurewebsites.net/Images/mvvm00.png

The View never has direct access to the Model. The View is connected to the ViewModel via its DataContext.
The ViewModel has direct access to the Model and is able to recover values from the Model and set values into it as well as call methods so that actions occur. But the ViewModel does not have direct access to the View, there could 0, 1 or many View instances all looking at the same ViewModel and it would never know.
The Model does not know about the existence of the ViewModel or View. Therefore you could reuse the Model class in a different project without any dependency on WPF or even a user interface.
How you attach the Model to the ViewModel is up to you. You could pass a reference to the Model into the constructor of the ViewModel. Or provide a separate method or property that is called after the ViewModel is constructed.
For complete separation you would expose the same list of properties on the ViewModel as are present on the Model itself (or just the subset actually needed). The ViewModel can hook into the PropertyChanged event of the INotifyPropertyChanged interface that should be exposed from the Model. As it sees changes it can pass the change onto any watching View via its own properties and its own implementation of the INotifyPropertyChanged interface.

As #Phil Wright states in his answer, the Model should have no knowledge of the ViewModel or the View, so you are free to reuse your Models between different layers. In my experience, Models are generally simple POCOs with no dependencies on other layers.
Whether you reuse your Models between your layers is up to you. If you're using an ORM such as Entity Framework, your Models might be your entity classes. Your business layer might decide to use these entity classes, or you may want to abstract them or aggregate them or do something else with them. At the end of the day what goes in your Models is driven by what you want to store in them and how you want to use them, and SO can't really provide guidance on that because the question is so open-ended.
As far as WPF and MVVM are concerned, I like to think of the ViewModel as being an aggregator of sorts for one or more Models. You generally pass the Model(s) to the ViewModel somehow (through its constructor or whatever): the ViewModel then provides properties and commands that are used by the View (via binding) in order to read and/or change the state of the ViewModel. At some later point, the ViewModel may need to change the state of the Models that it was supplied with, to reflect the changes initiated by the View.
You may find that the Models needed by your business layer are slightly different to the Models used by your ViewModels, and unfortunately you can end-up writing a lot of very similar-looking Model code when this happens. In such cases, Model interfaces may help: there's nothing to say that the Models used by a ViewModel have to be concrete classes. So you could have a single "sort of complex" Model that has all the properties needed by both your ViewModels and your business layer, then expose that Model through two different interfaces (one for each layer) so that properties irrelevant to a particular layer are not visible to it (if that makes sense!).

Related

Benefits of strictly separating View and Model?

A colleague of mine doesn't want to bind from the View directly to the Model. For example, in the Model, he has a ObservableCollection and in the View he wants to use it. Instead of directly using it like I would do it (e.g. {Binding Model.Collection} he has another ObservableCollection in the ViewModel which has exactly the same data as the ObservableCollection in the Model. He is synchronizing both ObservableCollections with each other through events.
What are the benefits of his approach? I, personally, disapprove of his approach because it just adds duplicate code and since you have to synchronize the ObservableCollections yourself it's also more error prone. My colleague says he wants to do it this way because then he can change the Model without changing the View.
EDIT:
Some highly upvoted answers [1][2][3] support my in my thinking that it's really okay to bind directly to the Model.
It all comes down to code separation and reusability. Ideally, the View should be completely separated from the Model. If the View doesn’t rely on a specific implementation of the Model, then it can be reused with a different model to present some other data.
So, suppose you have a AlbumView and your current Model is Album, but in future you have decided to also add Movie or Book to you library. you could still use the same AlbumViewo display your movie and book objects. Furthermore, if you want to create a new project that has something to do with albums, you could simply reuse your Album class, because it’s not dependent on any view. That’s the strength of MVVM or MVC.
So for me, I would say, that your colleague is right, because Model naturally reflect the Data Access Layer Entity, where it will be stored and handled. In addition to that, Model may have more properties related to Access data layer such as created indexing. While you ViewModel is only related to the view and the presentation logic of your application. It only reflect what the user is going to see.
I would say using an ObservableCollection in the Model layer is wrong. By adding that you are basically saying "Model object stores data and notifies when it changes".
The role of the ViewModel is to manipulate the Model and provide an interface to the View for presenting the Model.
I believe your colleague is right because he is enforcing separation of concerns such that manipulating the Model should not impact the View.

Should I implement business logic on a Model or a ViewModel

When I'm processing business logic in an MVVM app. Should I do this on the Model or the ViewModel?
For example, if I want to re-calculate costs after an Asset has been re-valued, should I operate on the Model?
Is there an advantage in doing this on the ViewModel instead?
What happens if I have a list of ViewModels, but I want to translate that into a list of Models so I can do some processing? I could expose the Model as a property of the ViewModel (and use that to build the list of Models). But that means that the View will be able to access properties of the original Model
My suggestion is to put logic in a service layer instead.
This is a middle layer between view model and model (which, in a real object oriented paradigm, should only contains properties).
So the correct life circle may be:
View model -> service -> model handling.
This allows also to reuse business logic code through others view model if needed
The Model's purpose is to represent (or model) your business domain. Therefore, business logic by definition goes in the Model, not the ViewModel.
The job of the ViewModel is to expose properties and fields of the Model, and prepare them for consumption by the View.
For instance, picture a banking application. The Model may represent an account. Perhaps the Model has an account balance. The job of the Model may be to track the balance and make sure certain invariants are maintained (such as not allowing a withdrawal that is larger than the balance). The job of the ViewModel may be to turn the balance into a string that is used as a binding in the View.
You want to keep as much logic out of the ViewModel as possible to keep your code reusable and loosely coupled.
Use the model if you are building a web app; and one level bellow the model i.e. the domain level if you are building a LAN/desk app.
Your problem - re-calculate costs after an asset has been re-valued - might not just be a user interface issue. A back-end application might want to do the same (for example, for automatically importing data). And then you have a choice of either duplicating business logic or rewiring to existing one.
Nothing wrong with using the same model for the back-end too. But models -especially disconnected ones- tend to be large data structures because they need to bring with them all data from reference tables (unless you want to do round trips to server and sacrifice your GUI experience). And that might affect performance if model is used.
if you model contain required data for calculation you can use model.if model does not contain the data means create view-model and get data to do the calculation.(With respect to Business logic )
if you want to pass this data to view create View Model It improves code re-use opportunities

Can Models communicate with each other in MVVM

Can a Model communicate with other Models, for my case, can a Model have a list of an other Model, Example :
I have a Model called Graph, and a Model called Node.
Is it appropriate in the MVVM pattern to make the Graph class which is a Model, contain as a property, a list of the Model Node ?
Yes.
MVVM is simply a separation of concerns in terms of views and data. Views can have other views and models can encapsulate other models. The view model is the hybrid where data is stored and acquired using the models and consumed by the views.
Although the answer might be yes you do have to consider the 'proper' responsibilities in MVVM. As long as the Model maintains integrity of the model (references, domain/validation checks) it is perfectly fine to have the model classes 'communicate' with each other. However, in general, I prefer the ViewModel and the repositories to be responsible for retrieving data and translating it into ViewModel classes.
Many times I do not need any logic in the model, the model is the structure I receive from and send to the data store (file, db, web service, ...) The model is 'just' data to me and preferably generated (proxy generation, Entity Framework, ...)

Dal (with Entity Framework) and Model layers into MVC

First of all , I use EF into Dal layer (separeted project from MVC, same solution). The generated models from EF's EDMX file are the actual models from Model layer?? If so, how do I access these models to work in MVC's View layer? I think it's wrong accessing data layer directly from view to work with these models, and If I make a Model layer with "my models" and translate Dal's models into mine models... it'll be duplicated code.
Probably I'm getting something wrong, but most of egs. are with code first approach, and I can't figure out this.
You are right in your idea of not accessing access the Models in your DAL directly from your presentation layer.
To avoid duplicating code when translating your DAL objects into the Models used by your views, you could use something like AutoMapper, which is supposed to do the heavylifting for you in exactly that scenario.
I think it's wrong accessing data layer directly from view to work with these models...
That's right, the appropriate method is using View Model
When you have dozens of distinct values to pass to a view, the same flexibility that allows you to
quickly add a new entry, or rename an existing one, becomes your worst enemy .You are left on your
own to track item names and values; you get no help from Microsoft IntelliSense and compilers .
The only proven way to deal with complexity in software is through appropriate design. So defining an object model for each view helps you track what that view really needs. I suggest you define a
view-model class for each view you add to the application.
-- "Programming Microsoft ASP.NET MVC" by Dino Esposito
A ViewModel provides all information that your view requires to make itself. To transfer data from ViewModel and a business entity you can use AutoMapper.
Don't worry about duplication, those are two different concept and should be separated from each other; it makes your application easy to maintain.
I may be mistaking but to me, using generation from EDMX provides you with the DbContext which could be considered as the DAL and entities which could be considered as the Model.
So you might directly manipulate entity instances as your business object. Manipulation of the base through the DbContext should appear in the BLL layer. Additionally, you might implement DTOs where needed.
This, of course, assumes you want to use entity framework code generation. Other options like using POCOs might be more relevant considering your overall architecture.
I use a view model in my local project and the models in the other project. Then put references to the models im gonna use on the page in my view model. Then reference the view model on my page. Let me know if that sounds like something you want to do and I can edit in some code.

MVC: View and Model Interaction Regarding Data Access, etc

Should the model just be data structures? Where do the services (data access, business logic) sit in MVC?
Lets assume I have a view that shows a list of customer orders. I have a controller class that handles the clicks on the view controls (buttons, etc).
Should the controller kick off the data access code? Think button click, reload order query. Or should this go through the model layer at all?
Any example code would be great!
Generally I implement MVC as follows:
View - Receives data from the controller and generates output. Generally only display logic should appear here. For example, if you wanted to take an existing site and produce a mobile/iPhone version of it, you should be able to do that just by replacing the views (assuming you wanted the same functionality).
Model - Wrap access to data in models. In my apps, all SQL lives in the Model layer, no direct data access is allowed in the Views or Controllers. As Elie points out in another answer, the idea here is to (at least partially) insulate your Controllers/Views from changes in database structure. Models are also a good place to implement logic such as updating a "last modified" date whenever a field changes. If a major data source for your application is an external web service, consider whether wrapping that in a model class.
Controllers - Used to glue Models and Views together. Implement application logic here, validate forms, transfer data from models to views, etc.
For example, in my apps, when a page is requested, the controller will fetch whatever data is required from the models, and pass it to a view to generate the page the user sees. If that page was a form, the form may then be submitted, the controller handles validation, creates the necessary model and uses it to save the data.
If you follow this method, Models end up being quite generic and reusable. Your controllers are of a manageable size and complexity because data access and display has been removed to Models and Views respectively, and your views should be simple enough that a designer (with a little training) could comprehend them.
I wouldn't put Data Access Code in the Controller.
To build on what has already been said, it's important to think of layering WITHIN the layers. For example, you will likely have multiple layers within the Model itself - a Data Access Layer which performs any ORM and Database access and a more abstract layer which represents the Business Objects (without any knowledge of HOW to access their data).
This will allow you to test the components of your system more easily, as it supports mocking.
I like to keep the "contracts", or interfaces, for model persistence or service access in the domain (model) layer. I put implementations of data access or service calls in another layer.
The controllers are instantiated with constructors that take interfaces for the services, e.g. ISomeService, as parameters. The controllers themselves don't know how the service layers are implemented, but they can access them. Then I can easily substitute SqlSomeService or InMemorySomeService.
I've also been fairly happy with a concrete service implementation that takes a domain (model) layer repository as a parameter to its constructor.. For example: ICatalogRepository with SqlServerCatalogRepositry : ICatalogRepository is handed to CatalogService(ICatalogRepository, ISomeOtherDependency).
This kind of separation is easier with dependency injection frameworks.
The View would relay what should happen on a click in the UI to the Control layer, which would contain ALL business logic, and would in turn call the Model layer which would only make database calls. Only the model layer should be making database calls, or you will defeat the purpose of the MVC design pattern.
Think about it this way. Let's say you change your database. You would want to limit the amount of code change required, and keep all those changes together without affecting other pieces of your application. So by keeping all data access in the Model layer, even the simple calls, you limit any changes required to the Model layer. If you were to bypass the Model layer for any reason, you would now have to extend any changes needed to any code that knows about the database, making such maintenance more complex than it should be.

Categories