What is difference between Model and ViewModel in asp.net core mvc? [duplicate] - asp.net

This question already has answers here:
What is ViewModel in MVC?
(16 answers)
Closed 5 years ago.
I have a Account class for account models.
public class Account
{
[Key]
public Int64 UID { get; set; }
[Required]
public string ID { get; set; }
[Required]
public string PassWord { get; set; }
[Required]
public string UserName { get; set; }
}
My project is not a code first project and this is a model class for database 'Account'.
But I use only two properties in login view, string ID and string PassWord.
So I can not use ModelState.Isvalid() in the login controller when I check the validation of model because I use
just two properties...
So I searched about that then, now I found about 'ViewModel' which is the model class for view.
Then I created a new class 'AccountViewModel' and then I mapped this with view instead of 'Account' model.
Did my way was right?
I understood the ViewModel is a model class just for View.
And The model class is for all. (like a global meaning...? for DB,view and so on)
What is different between Model and ViewModel class?
May I get some a nice way to solve this?

As the name says, view model is very specific to the view.It will be a simple POCO with only those properties needed for the view.
Your other model class is your entity models. So if you are using EF code first approach, you need entity class definitions from which EF will generate the database tables. So basically these entity classes look very similar to your db schema structure.
By creating a view model, you are removing the strong coupling of your entity classes to the UI layer. Now your UI layer is independent of your entity classes and if you ever decide to change the data access code from EF to something else, you do not need to touch the views at all.You simply need to update the mapping part(from the view model to the data access/service layer entities)
View models sometimes looks very similar to your entity models, especially if your entity model is a simple table/class.
In your case, since your view is passing a userid and password, you need a simple view model which has only those 2 properties. When user submits the form,you can read the values and use it to build an domain entity class object as needed.
public class LoginViewModel
{
public string UserId { set;get;}
public string Password { set;get; }
}
You can use data annotations with the view models. The MVC model validation framework these data annotations to do the validations. For example, since user should enter a UserId and Password, you may decorate them with appropriate annotations.
public class LoginViewModel
{
[Required]
public string UserId { set;get;}
[Required]
public string Password { set;get; }
}
The [Key] attribute is more useful when you define an entity class. So i would not think it is needed for a view model. Remember view model is more like a UI concern. It has no idea about your underlying data storage mechanism at all.
Some of the most used attributes with view model properties are
Required
MinLength
Range
Url
Phone
StringLength
DataType

Related

Conditional Validation of ViewModels

I have a ViewModel which is used for a Wizard containing two separate ViewModels which are used to load partial views into the wizard. Depending on the option selected on Step1, I need to validate either Step2 or Step3. The viewmodels for Step2 and 3 have their own AbstractValidator which works great because it includes client side validation. The problem is that if I use ModelState.IsValid, one of the VMs always fails to validate because it's empty (that step was not filled out). Is there a way to skip validation for one of the viewmodels?
Say you have the following model:
public class PersonViewModel
{
[Required]
public string Email { get; set; }
[Required]
public string Password { get; set; }
[Required]
public string FullName { get; set; }
}
But you want to exclude FullName from the model validation because you are using the model also in a place where FullName is not filled in, you can do so in the following way:
ModelState.Remove("FullName");
Hope to help, my friend :))
The solution I eventually arrived at was surprisingly simple but I didn't spot it in the docs. You can call $('#somecontainer').valid() which will show validation messages for supported controls and also return true if all controls in the container are valid. It doesn't work for everything as rules like GreaterThan aren't supported client side.

How to preserve input ids when editing lists in ASP.NET MVC?

I'm working with ASP.NET MVC 4, but I on't think that matters for the purpose of this question.
I have a relatively complex model for my edit view. Like this:
public class Recipe_model
{
public string Name { get; set; }
public List<Recipe_Ingredient_model> Ingredients { get; set; }
}
where Ingredients is
public class Recipe_Ingredient_model
{
public int RecipeID { get; set; }
public int? UnitID { get; set; }
public double? Quantity { get; set; }
public Ingredient_model Ingredient { get; set; }
}
which itself contains the Ingredient model.
When I make a form for this, the built-in Html.EditorFor() doesn't work for anything past the properties of the Recipe_model, so I'm using partial views to display the editor for each of the sub-models.
That works fine as far the interface goes, but when I submit the form to the controller and try to bind to the Recipe_model automatically using
[HttpPost]
public ActionResult Edit(Recipe_model model)
{
return View(model);
}
it fails because the ids of the input elements in the partial views do not conform to the correct pattern (I think ParentModel_Property).
Short from hard-coding the ids in the partial view or binding manually from the FormCollection in the controller, is there some way to get the correct ids generated in the partial view so that the model will bind automatically on submit?
This is common problem. Instead of simple partials, use EditorTemplates (special folder for models) and binding will work automatically.
For example look at this question: Updating multiple items within same view
in addition to the answer given by #WebDeveloper
you can also try and create a custom model binder though a little more complex but will add to the ease of posting and binding form value to the objects in long run
have a look here http://patrickdesjardins.com/blog/asp-net-mvc-model-binding
you will have to manually take all the form values and bind them to the model once and then you will be able to use the #HtmlFrom methods on the razor to do anything and you will get all the value inside the objects inside the action methods as you like.

How to perform complex validation on a model object?

My project is in ASP.NET MVC 3. In my domain I have a model object defined by Entity Framework. In order to validate properties I simply extend the generated EF object and add a metadata class which contains all my validation attributes.
[MetadataType(typeof(ContactInformationMetaData))]
public partial class ContactInformation
{
}
public class ContactInformationMetaData
{
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
public string Phone { get; set; }
[EmailValidator]
public string Email { get; set; }
}
This works great most of the time but now I have a more complex scenario. I don't want the Phone and Email properties to be required but I want ONE of them to be required. In other words, I want to require that either email or phone or both be set, but not none.
How would I perform complex validation like this? If I create a custom validation attribute where would I put it and how would that work?
Here is another question exactly like that (even the Phone and Email example is the same):
Model Validation / ASP.NET MVC 3 - Conditional Required Attribute
Check out FluentValidation:
http://fluentvalidation.codeplex.com/wikipage?title=mvc
you can easily create this type of custom validation, it's a pretty cool validation framework in general

how to edit json data runtime?

i want to add the data to existing generated json data in my asp.net mvc application , what i have to do ?
means , suppose i have class Company that having list of Departments as property. but json serialization is not able to support such kind of circular reference. so i thought how if, i get serialize the Company object first without list of Departments, then get departments for each company and then serialize this list and append data to company serialized data. i know this may be wrong way . but i have to do because of time ultimatum. please guide.
You could define a view model where you won't have any circular references:
public class DepartmentViewModel
{
public string DepartmentName { get; set; }
}
public class CompanyViewModel
{
public IEnumerable<DepartmentViewModel> Departments { get; set; }
}
and then you would map between your model and view model (you could use AutoMapper for this) and finally return the view model to the view.
For example:
public ActionResult Index()
{
var companies = _repository.GetCompanies();
var companiesVM = Mapper.Map<IEnumerable<Company>, IEnumerable<CompanyViewModel>>(companies);
return Json(companiesVM, JsonRequestBehavior.AllowGet);
}
Now you no longer would have circular references and you will be able to successfully serialize the view model to JSON and you would only pass the information that is required to the view.

ASP.NET MVC, Linq to SQL Data Annotation Validation

I'm trying implement Data Annotation to my Linq to SQL objects. The .dbml file is generated and I'm not sure how to add data annotation to the objects without touching the generated source code.
I tried to add data annotations to the a separate partial class of the object, but its not recognizing it, no Intelli sense either.
As I said in my original answer to this question, you should use an interface. The answer posted after mine (which was marked as Accepted) said to use a class. This is not as good. An interface is a better option for the following reasons:
If there is a mismatch between the name in your LINQ class and the name in your interface, the compiler will flag it for you
An interface can not be instantiated, so this protects class users from accidentally instatntiating the metadata type
If you use Resharper (or similar), the interface can be automatically extracted from the LINQ class
An interface is less verbose than an empty class
If you program against interfaces rather than classes (which is a good practice), then you've already got an interface you can use as your metadata type
For a class called, say "User", create an interface for it (say 'IUser'), and then update the definition of your partial User class as follows:
[MetadataType(typeof(IUser))]
public class User : IUser
Then, in your IUser interface, add appropriate Data Annotation attributes to the properties:
[Required]
[StringLength(50, ErrorMessage = "Username cannot exceed 50 characters")]
string Username { get; set; }
For a class called, say "User", create an interface for it (say 'IUser'), and then update the definition of your partial User class as follows:
[MetadataType(typeof(IUser))]
public class User : IUser
Then, in your IUser interface, add appropriate Data Annotation attributes to the properties:
[Required]
[StringLength(50, ErrorMessage = "Username cannot exceed 50 characters")]
string Username { get; set; }
Linq to SQL generates object classes as partial. An easy way to implement data annotations is to create your own partial class of the object, place the [MetadataType(typeof(YourDataAnnotationClass))] on the partial class you created.
Example:
// Linq to SQL Class
public partial class Article
{
public string Title { get; set; }
...... etc
}
Create your own MetaData class with Metadata for each field you want to validate
public class MyMetaDataClass
{
[Required]
[Range(5,20)]
public string Title { get; set; }
}
Create a Partial Class for the Object class you want to add metadata to, in this case Articles class:
[MetadataType(typeof(MyMetaDataClass))]
public partial class Article { }
Note: you don't need to specify anything in the class, just the metadata type.
Thanks,but the problem is MS define the prototype of MetadataTypeAttrubute as
[AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed class MetadataTypeAttribute : Attribute
So, you had to use class but not interface
From China
Forest Lee: 李晓强
xiaoqianglinsen#163.com (MSN)
lixiaoqiang#webservice.com.cn

Resources