I've been used to decorating data model classes with data annotation attributes, but the purist in me baulks slightly at including purely presentational attributes such as display format here. I am, however, quite happy to keep validation centric attributes here. One good reason I have to continue keeping all annotations etc. in the data model is that my view model aggregates data model classes, e.g. my ViewModelBase.DetailItem<TEntity> property in the view model is just a reference to an entity class in my data model. If I wanted to move presentational annotations to the view model, I would have to quite radically revise my design to one where I duplicate data model properties in my view model and use an object mapping tool to populate view model objects based on data model objects.
Where should I be doing my data annotations?
Just BTW, this is what my rough draft ViewModelBase looks like:
public class ViewModelBase<T>
{
public virtual string PageTitle { get; set; }
public virtual string ViewHeading { get; set; }
public virtual ViewMode ViewMode { get; set; }
public virtual IEnumerable<T> ItemList { get; set; }
public virtual T DetailItem { get; set; }
}
Validation should at least be performed at the view model because this is what you receive from the view. Also the validation is always performed in the context of a given view. So you could have two different view models corresponding to two different views but mapped to a single model class and because the validation could be different depending on the view, this validation should be performed on the view model. If you performed the validation on the model then you would have hard time to distinguish between the two cases, because you could have a situation where a property is required in the first view, but not required on the second view. So if you are using data annotations to perform validation then you should decorate your view model with them.
I share the same concern around the DRY principal and validation, which is why I prefer to keep most validation requirements in the model. But why does it have to be one or the other? Model Validation belongs in the model, but there are certain view-specific validations which belong in the viewmodel.
That being said, data annotations are just that: annotations around data. Not proper validation logic. Validation logic is a completely different concept to data annotations (A Required attribute is merely one aspect of validation). I personally find it difficult to place where real validation fits within a MVVM implementation as some validation requires context rather than just required or not.
Short answer: If it's in your Model then it gets aggregated to your viewmodels. If there is a view specific requirement, the viewmodel can cater for additional requirements if needed.
Related
I'm working on an MVC application using LINQ-SQL to connect to my SQL Server database.
Currently when fetching data, I'm passing the properties of my LINQ objects over to a Domain Model, which I'm then creating properties of in my View Models.
For example my View Model might have the following properties:
public Models.UserModel user { get; set; }
public List<Models.CountryModel> countries { get; set; }
My Domain Models have exactly the same properties as my LINQ objects, and I copy these properties over like:
Models.UserModel user = new Models.UserModel();
user.Username = User.Username;
user.FirstName = User.FirstName;
user.LastName = User.LastName;
Where user is my Models.UserModel object, and User is my LINQ object mapped from the User database table.
As my Domain Model is exactly the same as my LINQ object, is there any advantage for me transferring this data over to a Domain Model, or would it be okay for me to just use LINQ objects in my View Model such as:
public User user { get; set; }
public List<Country> countries { get; set; }
What are the advantages of using a Domain Model? Is this purely to loosely couple with the database LINQ objects?
If there are advantages to using Domain Models, how would be best to structure these within my MVC application?
Should they be split off entirely at the "Models" folder level (for example a sub-folder "DomainModels" and "ViewModels") or coincide (such as "UserEditViewModel.cs" and "UserDomainModel.cs").
As my Domain Model is exactly the same as my LINQ object, is there any
advantage for me transferring this data over to a Domain Model, or
would it be okay for me to just use LINQ objects in my View Model such
as:
You could reference domain models in your view models in case they are exactly the same. I don't see any benefit of duplicating this logic except that in the real world they are never the same. You always have some view specific things such as validation or even display labels. The advantage of having pure view models is that your application is no longer tied to your database structure. You could easily flip/flop data access technologies without modifying the UI part. I find it more maintainable to have this clear separation and always tend to make it in my applications.
In an mvc project, could someone explain to me the difference between a model and a view model?
My understanding is that a view model reperesents the data for view eg. cshml, but a model represents the data for a partial view. Would this be correct. I have seen the names used in different situations which confuses me so looking for direction on this.
Models are your domain. For example we might have a customer model. We can use this customer in our domain. We can place orders for this customer. We can update the customers contact details, and so forth.
// Domain object, encapsulates state.
class Customer
{
public void PlaceOrder() {...}
public void UpdateContactDetails() { ... }
}
View Models are a way of presenting the data in an easy way. For example, we might have a customer view model. This would be a simple DTO (Data Transfer Object) which allows us to expose the customer to a view. Often view models are created from models - some form of conversion often takes place.
// DTO - exposes state - no domain logic
class CustomerViewModel
{
public string Name { get; set; }
public int Id { get; set; }
}
The benefit of using a view model rather than using your domain objects in your views is that you don't have to expose the innards of your domain to ease presentation logic. I should add that view models are a way of controlling model binding, e.g. if you expose a database record you probably don't want the whole record to be bindable. Using a view model means only those parameters on the model will be bound. Therefore using view models is important from a security point of view. The alternative here is to use whitelists to control what is used during the model binding process - naturally this is tedious and prone to error.
In terms of ASP.NET MVC - the word model is used somewhat interchangeably. In a "real world" project, your domain is likely complex and will not reside inside a Web App, chances are you'll include some other dependency. Therefore the "models" you'll use will be View Models.
In general, in the ASP.NET world, when people refer to models to refer to 'domain models' which are often a 1-1 mapping between say a database table and a C# class.
When referring to view models, these are convenience classes which aid the passing of data between the view (.cshtml) and controller.
The view models should contain data relevant to the view, which may contain aggregation data of the domain model (e.g. a property called 'FullName' which is the combination of 'FirstName' and 'LastName') or things like paging info etc.
Personally I prefer to use view models to present data in simple forms to the view, and I make the controller actions take instances of a view model, construct domain models and act on them, either directly or through a service layer.
I'd say that is general a view model holds the data for a specific view/screen/partial view and a model is rather the object representing the business object or entity.
Please look into the following posting, your question was successfully answered:
ASP.NET MVC Model vs ViewModel
Hope this helps
I am new to MVC so this question may be naive
I know you can add validation attributes to model properties and the framework will provide appropriate server side and client side validation.However I am forced to use a legacy database structure where one of the properties in the model is either "int" or "string"
and the other property(Value) data type is determined by the first property.This means that I cannot use Annotations for validation. But is there any simple way of programatically "annotating" the properties after values are fetched from the database and the model class is constructed.If this can be done then it will do effective (client Side) validation without much hassle.
thanks
This answer shows one way to inject attributes at runtime. Another answer shows how to use validations that are only checked sometimes.
In your case it would be pretty easy to do model-based validation.
For server-side validation:
public class MyModel: IValidatableObject
{
public string Prop1 { get; set; }
public string Prop2 { get; set; }
public IEnumerable<ValidationResult>
Validate(ValidationContext validationContext)
{
var relevantFields = new [] {"Prop2"};
if (Prop1 == "Int" && NotValidInt(Prop2))
yield return new ValidationResult("Prop2 must be convertable to int", relevantFields);
else if (prop1 == "String" && NotValidString(Prop2))
yield return new ValidationResult("Prop2 must be convertible to string", relevantFields);
}
}
For client-side validation, it's a bit more involved but details are available here:
MSDN article on adding support for clientside validation
A Good StackOverflow answer on the topic
See the custom validation section of the free Pluralsight training on validation for more information on server-side validation.
You are falling into the normal newbie error of thinking of your database as the M in MVC. Any non-trivial app is going to require that you seperate your database model from your view model. So apply your attributes to a view model, then use business logic to copy the values to your database model when your view is properly validated.
MVC is a User Interface pattern, and databases do not belong in it... I know, every sample application under the sun passes your data objects to the view, but that's just not the way it should be done.
I've found this text in Prism documentation. I'm starting on MVVM and I'm at lost. Can (should) I bind model properties in the view or I must create a viewmodel with a proxy property for every property in the model?
The model classes typically provide
property and collection change
notification events through the
INotifyPropertyChanged and
INotifyCollectionChanged interfaces.
This allows them to be easily data
bound in the view. Model classes that
represent collections of objects
typically derive from the
ObservableCollection class.
EDIT: Here is some extra info to help. I'm building a personal project from the ground up (so I'm designing the models too), this is the first time that I use MVVM and I want to learn properly.
My model is very hieraquical, having classes with list of more class with more list inside, building a complex tree of information. I was trying the "standard" MVVM approach, build the model with POCO and no notifications, and using List. Then building the ViewModel with proper notifications and using ObservableCollections.
The problem is, the way it is going, I'm almost reconstructing my whole model as a ViewModel AND having to keep the data synched between the to (the ObservableCollection to the List). Then I read that on the Prism docs and wondered if I should have all that trouble or just create a root ViewModel for logic and bind all the rest to the model itself.
It depends really, if your model already implements INotifyPropertyChanged and/or IError info you might want to bind right to the model property. However if you want to do special validation and other stuff that the model knows nothing about you add the property wrappers in your view model.
This article gives a good example of a hybrid: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
Often my MV properties look like this and thats quite normal:
public string Symbol
{
get { return Model.Symbol; }
set { Model.Symbol = value; this.NotifyOfPropertyChange(() => this.Symbol); }
}
I often do NOT implement INotifyPropertyChanged in the model and thus often I have to write the wrappers.
EDIT: In response to your additional information: It can be a bit tricky to to keep the collections and lists in sync. In your case what I would do is to create a view model for each model class, but NOT wrap all the properties just access them like this: {Bindng Customer.Name}. But of course you have to create a wrapper for the collections which contain view models. The Prism documentation is, as they say themselves, just guidance, if your scenario needs a different approach then this is fine.
Take a look at this code. I only wrap the collections and the properties I will access through the model. This gives you the best of both worlds. Then IF you need a special property that does not belong into you model you can add it to the view model (see the CustomerViewModel), or if you need special notification for a certain properties.
class CompanyViewModel{
public CopanyViewModel(Company c){
foreach(var customer in c.Customers)
Customers.Add(new CustomerViewModel(customer);
}
public Company Company {get;set;}
public ObservableCollection<CustomerViewModel> Customers {get;set;}
}
class CustomerViewModel{
public CustomerViewModel(Customer c){
Customer = c;
}
public Customer Customer {get;set;}
public Brush CustomerBackground{
get{
if(Customer.Active)
return Brush.Greeen;
else
return Brush.Red;
}
}
}
(This code might not work, I just typed it in here.)
Now, if you need changed notification for all models and all properties you have to either implement it in you model or in wrap all properties in a view model.
My terminology is probably way off here but basically I'm trying to pass multiple data models to a view. To help put the question in context, take this example:
Say I was making a blog. When I log in I want the home screen to display a list of all new unapproved comments, as well as a list of recently registered users, and a list of the most recently submitted blog posts.
Most discussions I've seen suggest strongly-typing the view page so it can be called with something like "return View(RecentComments)" and iterate through the comments in the view, or to cast the data model like "var NewUsers = (MembershipUserCollection) ViewData.Model". What I'm ideally after is the 'right', or at least a 'right-enough', way of passing multiple models while still maintaining appropriate logic separation.
One way is to create a new type that encapsulates both pieces of model data:
public class MyBigViewData {
public SubData1 SubData1 { get; set; }
public SubData2 SubData2 { get; set; }
}
public class SubData1 {
... more properties here ...
}
public class SubData2 {
... more properties here ...
}
Another way is to store the "main" model data as the strongly-typed data and store other data in the view data as dictionary items:
ViewData["username"] = "joe"; // "other" data
ViewData["something"] = "whatever"; // "other" data
ViewData["subdata1"] = new SubData1(...);
return View(myRealModelData);
The advantage of the second approach is that you don't need to do anything special at all: It works right out of the box.
What I've done in the past is written a class that contained instances of both the classes I will need on the view.
ie
public class City{
public Mall TheMall;
public School TheSchool;
}
Then your view will be strongly typed as City, and you will use Model.TheMall.Property and Model.TheSchool.Property to access what you need
EDIT
This is an example of what other posters mean by creating an object with both objects as fields/properties
Sadly, the only way to accomplish passing multiple objects is either by creating an object with both objects as fields/properties, or by using a weakly typed array.
The way to pass multiple models to a view is to create what we call a Form View Model which has your other models within it.
Then in your view you can pass the individual models contained in your Form View Model to the Partial Views responsible for rendering the data in said models.
Makes sense?
edit
btw: a form view model is simply a class. it's not a special type as may have been suggested by my answer.
In addition to my other answer, another way to do this would be not to strongly-type the view and master pages in the page directive, but instead make use of the generic type-based ViewData extensions from MVC Contrib. These extensions basically use the fully-qualified type name as the ViewData dictionary key. Effectively, the typing benefits are the same as the strongly-typed page approach, with less class overhead in terms of the number of view model classes required. Then in your actions you do
ViewData.Add<Car>(car);
ViewData.Add<LayoutAData>(layoutAData);
and in the views you do
<%= ViewData.Get<Car>().Color %>
and in the master page you do
<%= ViewData.Get<LayoutAData>().Username %>
You could cache these Get<> calls inline in the views to mitigate the cost of casting multiple times.
After working on a large ASP.NET MVC app, I found the approach that was most productive while minimizing runtime casting was based on using generics to mimic the nested structure of views. Essentially views get their own data type. Typically these are either domain objects, or collections of domain objects that include metadata. Generic versions of these types are available across all possible master pages, taking a type parameter that defines data relevant to the master page.
public class Car {
// can be used as a model
}
public class CarCollection: Collection<Car> {
public BodyTypes BodyType {get;set;}
public Colors Color {get;set;}
// can also be used as a model
}
public interface ILayoutModel<TLayout> {
TLayout LayoutModel {get;set;}
}
public class CarView<TLayout>: Car, ILayoutModel<TLayout> {
// model that can be used with strongly-typed master page
}
public class CarCollection<TLayout> : CarCollection, ILayoutModel<TLayout> {
// model that can be used with strongly-typed master page
}
public class LayoutAData {
// model for LayoutA.master
}
public class LayoutBData {
// model for LayoutB.master
}
It's also possible to invert the generic-ness, but since the view dictates the layout, the view data should dominate over the layout data in my opinion. LayoutA.master would derive from ViewMasterPage<ILayoutModel<LayoutAData>> and LayoutB.master would derive from ViewMasterPage<ILayoutModel<LayoutBData>>. This keeps the view data and the layout data separate, in a consistent, strongly-typed and flexible way.
Creating an object that can encapsulate your other objects is the best way to go. Otherwise you're stuck with a bunch of ugly ViewData tags in the controller and the view.
One thing no one seems to have mentioned is that in the original questioners example, it might make sense to create the view out of a series of child actions that handle their own area of functionality rather than making a mega view model. That way the components such as unnapproved messages etc can be reused.
This also gives better encapsulation.