Hopefully I am being clear here. I have a ViewModel called A. I have a Model called M. I have a Repository for Model M and the DB stuff it maps to called RM.
Would my ViewModel, A, have a Property of my Model M AND my one for my Repository RM.
I would then use it by calling the various methods on RM and bind to M which I would pass to certain methods in RM like Save().
Make sense? Is that "normal" or even close?
You could be describing a typical situation, depending on your preferences. If your view model wishes to work with entities, then it could do so via a repository which you could inject as a dependency using constructor injection, and your view model could work against an abstraction rather than a specific implementation of your repository.
If you wished to access the repository at a later point after construction, then you could assign the repository to a private field or property for example.
In terms of your model, you could have a property which exposes this to the view so that you didn't need to duplicate the properties of the model on your view model. However, this would depend on whether you are happy with the view having direct access to your model which could be a violation of the LoD (Law of Demeter) in order not to violate the DRY (Don't Repeat Yourself) principle.
One approach would be to expose a property of type M, like you have at the moment, from the view model. The view will then bind to the properties of this exposed model. On your view model expose a method called Save and your view will call this method on the click of a button (binding can be used if you're using WPF). The Save method will then create an instance of the repository, add the property of type M to it and then save the repository.
Example:
public class ViewModel
{
public void Save()
{
// Create your repository
// Add this.Model to the repository
// Save the repository changes
}
public M Model { get; set; } // Bind your view to this.
}
This allows you to perform other operations before and after the save, you can use other properties to decide if, and what you save, and how your view model "saves" remains part of the view model and not the repository.
I would also recommend looking into using dependency injection, as mentioned by #devdigital, for your repository. This would mean you wouldn't have to create your repository in your Save method and instead you would use the instance of the repository passed into the constructor of the view model.
Related
I am currently developing a UWP application, but I think this question applies to any project type with a UI. I have built a View Model for my UI using the new Microsoft Toolkit MVVM library. It has properties such as:
private bool _isLoginAvailable = true;
public bool IsLoginAvailable
{
get => _isLoginAvailable;
set => SetProperty(ref _isLoginAvailable, value);
}
Furthermore, I have a few business methods that as parameters require up to 5-6 of these properties.
Reading on forums, I saw that it is unadvised to business logic within the view model, therefore, I came up with the following options:
Create a new class for the methods, and use the view model as a parameter: SampleMethod(SampleViewModel vm). Then, if I create an object of this class in the view model, I could use SampleMethod(this). At this point, I don't really see a difference between this option, and including the method within the view model class.
Second option I see is to add each required parameter to the method, and return each parameter as well in a tuple: SampleMethod(var1, var2, var3...) { return (var1, var2, var3...)} This to me seems very cumbersome.
The third option I figured is to use the MVVM Toolkit's messaging feature. In this case, I can set up the constructor of the view model to listen to messages with Messenger.Register<SampleViewModel, Var1Message>(this, (r, m) => r.var1 = m.Value);. Then, the method in a differenct class can send the value in message using Messenger.Send(new Var1Message(message). While this seems to be the best option, as it can be easily implemented together with dependency injection, it quickly becomes very convoluted, as for each property a new sealed class is required, that describes the message.
Is any of these options the best practice, or is there an option that I am not aware of?
If business methods require multiple properties in your VM, then maybe the properties should be in the business object? Are the properties intrinsic to the business rules, or do they only exist in the context of the view?
VM properties can just pass through to the business properties, or quite often you can just directly expose the business object itself in your VM.
Why do you think that its inadvisable to use methods within a ViewModel?
A ViewModel must act as an intermediary between the View, Model and business logic classes or libraries.
Consider using a RelayCommand (implement the property as ICommand type) in your ViewModel, this can be bound to a button click and is used to call a method within your ViewModel that takes the property values and passes them to your business logic.
A typical scenario for a ViewModel may be user input on a form, with your ViewModel properties being bound by the View. The user then clicks a button to submit this data.
So far I have yet to see the value of having models in WPF. All my ViewModels, by convention, have an associated Model. Each of these Models is a virtual clone of the their respective ViewModel. Both the ViewModel and Model classes implement INotifyPropertyChanged and the ViewModel just delegates everything to the Model anyway.
Why bother having Models then? Why can't I just move my Model logic up into the ViewModel and call it a day?
It seems rather redundant (that is, not DRY) to have MVVM, and just use VVM by default unless some special edge case demands a Model.
If using explicit model classes better supports unit testing, for example, or some other best practice, I can see the value.
The model is just the low level application data.
The view model is more specific.
It's like a window tapping into the data tailored for the view.
It also augments the model with details needed for the view. A good example is pagination.
A model can have more than one view model. These view models would offer different aspects of the data.
You can create a mashup of different data sources. A view model cleanly façades the models involved.
That means there is no 1:1 relationship between models and view models.
So, if you just display the low level data without a lot of additional logic, features, summaries, aggregations, filters, etc. you can do away with view models and just use the model directly. This seems to be the case with your project.
The model can be auto-generated (Entity Framework), or it might not be a specific class at all (think of a DataTable).
I assume that if you say "I don't use a model", you do in fact use a model, you just don't call it that way.
First of all, even in MVVM you can expose your Model directly in the VM and bind through it to the Model. {Binding MyModel.MyModelsProperty} where DataContext = ViewModel that way you don't have to necessarily wrap everything unless that is just your style to do so.
The ViewModel and Model have different responsibilities. For example, consider designing a file explorer with a tree view of folders. Each node in the tree view is a Directory/Folder. The directories are the models and they have properties related to the file system. The ViewModel may wrap or expose these properties for the TreeView nodes to display (For example the Name of the directory), but it also adds additional information such as "IsEditing" and "IsExpanded" to determine the state that the node is in.
You're just talking about one pattern in MVVM, actually there are more.
In Stateful viewmodel you don't actually delegate things to Models, Viewmodel itself maintains its state, so as you said in this pattern you can almost ignore the model as you can have state in VM itself.
To create isolation between business logic and presentation, data
should be removed from the view. The stateful view model pattern moves
data into the view model using XAML data binding. This allows the view
model to be tested without constructing a view, and it allows the view
to change with minimal impact on the business logic.
In Stateless viewmodel you delegate the calls to Model, which is what you're probably referring to.
Note that you don't necessarily implement INotifyPropertyChanged in Model. Just implementing it in VM is fine as long as you don't change the properties directly in Model.
So why do we need VM and Model? VM is for supporting view like providing Commands, etc and Model is just to hold the piece of data abstract the same.
If you think of it as an abstraction, let's say you need to build a screen to display a list of Employees and make a Selection, Search or Filter. Then we break it up in components. You will require:
An Employee class (Model)
An EmployeeManagementViewModel to prepare and present your list of Employees and manage state changes for your View (e.g. can contain a SelectedEmployee, Filter Search text, etc) to be used by your EmployeeManagementView
A list of Employees (Which will live in your EmployeeManagementViewModel)
Most likely you will already have an Employee class. If that's the case then you just need to expose that model in your EmployeeManagementViewModel as an ObservableCollection of Employees.
In case you don't already have an Employee class you may decide to create an EmployeeViewModel and add your Employee properties there like FirstName, LastName, etc.
Technically this will work but conceptually it bothers me because an EmployeeViewModel is not an Employee (it contains an employee). If you're abstracting reality then, the blueprint of an Employee should not include properties or methods to be used by a View. To me Employee should be a POCO which could implement INotifyPropertyChanged and nothing more than that. You're separating View state from the Model itself. Having an Employee POCO makes it easier to UnitTest, create mock employees, map it to a database table through an ORM, etc.
As the name implies the ViewModel is the model for your View and the Model is the model for your business domain
Anyway that's how I see it. When I started doing MVVM work I had that same question but over the years seems like it makes sense.
In general, my Models end up being a Data Access Layer, be it through Entity Framework, a WCF proxy, or some other class.
Depending on concurrency issues, the class could be static or instanced. If you can separate the behavior enough, you could "split" the DAL classes into a separate model for each view model, but duplicate code could become a problem.
Wikipedia: MVVM
Model: as in the classic MVC pattern, the model refers to either (a) a domain model which represents the real state content (an object-oriented approach), or (b) the data access layer that represents that content (a data-centric approach).
Your ViewModel isn't a substitute for your domain Model. It acts as an intermidiate between your view and the model, including commands, binding collections to your view, validation, etc.
Your domain model should also be reusable across ViewModels. If you implement it all in the VM you will end up abusing the DRY principle by sharing specific VM logic across multiple VMs.
In my experience when you just use Domain models as the ViewModel (as a property of the VM) you end up with a lot of Keys that require you to either go get the text value and store somewhere else or you end up adding the property to the VM anyway. Your view typically has more info than just one single domain model (e.g. related objects, display values, text status values etc..), something that the Domain model has no need for and would ultimately weigh it down. The view model is dedicated to the needs of the view, it keeps coding the View simple and non-complex.
I've come across an interesting question during my development. Right now, I use a database-agnostic unit of work layer to abstract the access of data from the actual database dependencies in my ASP MVC 4 web application.
Each individual database project which implements the unit of work interfaces are aware of my business models (models that go directly to/from the database). I'm not too sure how I feel about this approach, but that's not the question I am going to ask.
Should I be using a solution like AutoMapper to convert my business models to/from domain models - models that are passed to the view and used for any work that shouldn't have access to database fields (i.e., IDs)?
For example, consider inside my BusinessModels project, I have the following classes
BusinessModels
/UserAccounts/
User.cs
- ID
- Username
- HashedPassword
- Salt
UserSettings.cs
- IsSubscribedToNewsletter
- AllowDirectEmails
Would it make any sense to bind these User, and UserSettings models into a single model using AutoMapper like so
MyProject
/DomainModels/
User.cs
- Username
- HashedPassword
- Salt
- IsSubscribedToNewsletter
- AllowDirectEmails
for the purpose of views?
This question also extends to non-MVC projects but I feel seeing as I am working on an MVC project it would make more sense to ask it in that tag.
TLDR is there any point in mapping business models/entities to view models or does that provide an unnecessary layer of abstraction? And if so, would the Repositories contain business models, or view models (which map automatically to business models under-the-hood)?
You can use view models for two different things:
rendering a new view (GET action), passing the view model object as the model for the view
receiving data back from the view, in a Post Action (POST action), using the view model as parameter
(I know, the second is arguable. But it's not strange to use the view models for this)
The model for the GET action needs all the properties neccessary to render the View:
the values of the entity you're showing/editing
extra values needed to render the view (for example SelectLists for drop down lists)
Suppose that you have a User which can belong to one UserGroup.
In this case, if you want to edit the user, the model needs:
the User data
a list of UserGroups
I'd use a model like this:
public class EditUserModel
{
public User User {get;set;}
public SelectList UserGroups {get;set;}
}
As you can see, I directly add the User as a property. But I don't add the list of categories as a property, because I don't need the whole list of categories, with all their properties in the view. Besides, if you unit test the controller you can verify that the SelectList is as expected (that couldn't be done if you created the User Groups list in the view)
But, what if you don't need all the properties of the user in the View? Is it worth removing the User property, and add individual properties for Name, Email, JoinedData, Active... ? I think the anser is NO. Imagine you add/remove or rename some of the User entity properties. If you had individual properties in the view model, you'd have to change them as well, before updating the View. And, if you rely on automatic mapping (auto mapper, value injecter) you would't even realized if you make some mistake.
I also said that the view model can be used for posting back data to the controller. So you could do this:
[HttpPost]
public ActionResult Edit(EditUserModel userModel)
If you do so, the model binder will populate the userModel with the values in the form controls. So you'lll get back a half empty model. In this case, the UserGroups list would be null, and, depending on how many of the User's properties you edit, the User could also have many null/non-initialized properties.
To avoid making errors, in some occasions is advisable to create a different model (and probably auxiliary classes) to make it clear what is expected to be posted to the model.
For example, if you have an action to show the whole user data, but which only allows to change its password, you could create a class with two properties: Password, and PasswordConfirmation.
In this case, the view model for the POST could only have the Password and PasswordConfirmation. And derive a model for the GET which has this inherited properties, and also the list of User Groups and the User.
Why inheriting and not using independent classes? Simply beacuse when you use something like Html.TextBoxFor(m => m.User.Name), the Model Binder will be able to set the Name property of the User property, only if the parameter for the post action has the same structure. I.e. if the view model for the get has this structure:
public ChangePasswordModel
{
public string Password {get;set;}
public string PasswordConfirmation {get;set;}
// extra properties, like the list of user groups, the user data...
}
And the model for the post has this structure:
public PostedChanegPasswordModel
{
public User User {get;set;}
}
The content of the input rendered by Html.TextBoxFor(m => m.EditedUser.Name) won't be bound to the User.Name of the PostedEditViewModel.
But if you make this:
public EditUserModel : PostedEditUserModel
{
// extra properties, like the list of user groups
}
the data will be bound without any problem.
In general you have to be careful with the models you use for posting and getting. And I recommend using as many different view models as neccesary.
When to use automatic property mapping to completely new view and different models?
You must have a very strong reason to have different view models. This could be a result of starting the application from outside in (i.e. design first) or because a team is developing the UI before or while the business logie is being implemented.
In this case you can find that the classes for the view models, and the views themselves are already defined, and are quite similart to your entities, but not exactly equal. This is one case when I think it can be good to use mappers.
The other reason to use different classes would be to decouple the interface from the logic. But this usually only happens in the previous case.
Regards viewmodels I treat them like a summary of the data you wish to work with.
So taking from your example, your viewmodel would contain data from both the User and UserSettings classes. Let's say you had a view named UserData.cshtml then I would code it up like so:
public class UserDataViewModel
{
public string Username { get; set; }
public bool AllowDirectEmails { get; set; }
// etc ...
}
public ActionResult UserData()
{
var viewModel = new UserDataViewModel();
viewModel.UserName = "Whatever";
viewModel.AllowDirectEmails = false;
// Or however you get the data for the user.....
return View(viewModel)
}
Hopefully you get the idea. So you are on the right track with merging information from externals classes into one viewmodel class. Bascially tie everything together in the viewmodel class.
I name the viewmodel class the same as the view that it's going to be used for. This can help documentation, as well as make it easier for devs new to the code to follow.
I am Learning ASP.NET MVC and downloaded a couple of sample apps. MusicStore etc...
I am coming from a wpf background where we had the MVVM Pattern.
I have noticed that they used the concept of model and ViewModel.
In MVVM is pretty clear that you bind the view to the ViewModel injecting the model into the viewModel.
In MVC you have a controller but I am not sure and confused how the all ties together,as I cannot see the model injected into the ViewModel
I have the following structure
MyCompany.Entities.dll (All the models go here) EG Product
MyCompany.Dal.dll (All the repositories go here)
MyCompany.Services.dll (called by MyCompany.WebUI.Controller calls MyCompany.Dal)
MyCompany.WebUI.MyApp
MyCompany.Tests
From some of the examples I have seen your Model acts as a ViewModel.Am I correct?
Let's take a controller i have something like
public class ProductController
{
public ProductController(IProductRepository productRepository)
{
//omitted as not relevant
}
}
public class ProductVM
{
public ProductVM()
{
// Shouldn't we inject the model here RG Product
}
}
Is there some N-tier examples out there I can refer to?
Is the concept of ViewModel a valid one in MVC?
What is the standard?
Thanks for any suggestions.
Use ViewModels to simplify the View.
For instance, you might have a deep object graph with Products, Order, Customers, etc - and some information from each of these objects are required on a particular View.
A ViewModel provides a way to aggregate the information required for a View into a single object.
ViewModels also allow for things like data annotations and validation - which does not belong on your model, as your model should stay "domain-specific".
But in reality, ViewModels are nothing more than a simple wrapper for your domain objects.
Use a tool like AutoMapper to map back and forth between your ViewModels and domain models with ease.
Personally I always bind to ViewModels in my Views, never to the domain models, even if it's a single object. Why? Well I like to decorate my ViewModels with UIHints, validation, data annotations. Just the same way your domain models are enriched with domain-specific rules and business logic, so should your ViewModels be enriched with UI-specific logic.
If you simply have a object with a 1-1 representation of your domain model, you are missing the point of ViewModels.
Add to the ViewModels only, and nothing more, what is required for a particular View.
Example controller action
public ActionResult CustomerInfo(int customerId)
{
// Fetch the customer from the Repository.
var customer = _repository.FindById(customerId);
// Map domain to ViewModel.
var model = Mapper.Map<Customer,CustomerViewModel>(customer);
// Return strongly-typed view.
return View(model);
}
The difference between MVC and MVVM is that MVC has one set of classes for the data entities. In MVVM you have 2 - one set for binding to your views, and one set for managing the data persistence (which could be in a separate WCF service for example).
The benefits of MVVM are that the model bound to the views is relevant to the UI and completely independant from the persistence Model.
Which to use? Well it depends on how closely the data structure required by your Views maps to the structure of the database. When it is similar - it is possible to bind the DataEntities from your DAL directly to your view - this is the classic MVC pattern. However, you gain much with a separate ViewModel as you can extend these classes with View specific behaviour (e.g. Validation) that your DAL should not be concerned with.
For all but the most simple applications, I would recommend use of a separate ViewModel.
Extremely simple,
ViewModel can be the combination of multiple Model classes, to display or transforming the data to and from within the Network, may be via API calls.
However, Model class is nothing but just be specific to any particular entity, Object or strict to a particular Table.
Ex- For "EmployeeViewModel" can be the combinations of Multiple Model Classes i.e. EmpBasicDetails + EmpAddressDetails +EmpExperienceSummary.
Whereas, "EmpBasicDetails" - is specific Model class which contains the Employee Details specifically.
~Cheers,
I'm debating with myself about the best practice approach to controlling an Aggreate View Model class that I've created for my app... Let's say I have an aggregate model that has a PurchaseOrder object and a list of line items that belong to that Purchase Order, and a few other auxuliary/related objects. This view model is just a wrapper around all these objects that you would typcially need when working on any give PurchaseOrder.
After after creating an instance of this view model, I then want it to load up a PurchaseOrder (and it will load the PurchaseOrderLineItems automatically and saturate all the other related objects)...
So, to instruct the view model to load up a PurchaseOrder, is it more acceptable to:
Instruct the view model by setting a property on it (and let the property setter of the view model class respond by loading up the data)
ViewModel.PoNo = 1234;
or
Call a method on the view model to do the work:
ViewModel.LoadPurchaseOrder(1234);
Just to give a few mode detials about the Aggregate View Model, it basically looks like this:
public class ViewModel
{
//-- private fields
PurchaseOrder _Po = new PurcaseOrder();
List<PurchaseOrderItem> _PoLineItems;
Vendor _Vend = new Vendor();
int _PoNo;
//-- public properties here
ViewModel(){} // Constructor
}
Does this ViewModel serve any purpose other than relating all the PurchaseOrder informaton together? If not i would say you should pass your purchase order in the constructor of ViewModel because it seems like ViewModel would only be in a valid state if it had a PurchaseOrder.
EDIT: Given the 2 options you have listed, I think a method call makes more sense than setting a property as it is easier to tell that you are loading a PurchaseOrder into this ViewModel. As a developer, I wouldn't think that setting an integer property would end up loading all kinds of objects on the ViewModel, but one might expect that from calling a method.