View use of Model and ViewModel in ASP.NET - asp.net

I'm learning about ASP.NET and working in an application and I don't seem to understand the difference between the Model and the ViewModel. When in a View the information you want is taken from the Model you call using #model. If you want to make a dropdown list you will display the information you get from there right? When using #Html.Action you call a method of the Controller where you create a ViewModel object with the same {get; set} methods and the same information as the Model. So why using this if it's the same as the Model? Or it isn't?
Probably my question doesn't make 100% sense, keep in mind I'm still new to ASP.NET. What I need to understand is the difference between the Model and the ViewModel.
I found this post: ASP.NET MVC Model vs ViewModel, but I need the answer to be more specific.

Let's say that you have 2 models Blog and Category:
public class Blog
{
public string BlogTitle{ get; set; }
public string Body{ get; set; }
}
public class Category
{
public string CategoryTitle{ get; set; }
}
A ViewModel is a solution for showing both of these on a single view. It is an alternative to using ViewBag, but in my opinion a much better one, because it allows you to strongly type the model properties.
In this case if you wanted to show a Blog post and list of categories you would create a view model
public class BlogCategoriesViewModel
{
public Blog Blog { get; set; }
public IEnumerable<Category> Categories { get; set; }
}
And in your view:
#model Project.ViewModels.BlogCategoriesViewModel
<h1>#Model.Blog.BlogTitle</h1>
<h2>Categories</h2>
#foreach (var item in Model.Categories)
{
<p>item.CategoryTitle</p>
}
In the View the ViewModel in this case is basically a collection of 2 submodes. A ViewModel also lets you add properties to your view which aren't directly mapped to domain entities.
Hope that helps

Related

Using (showing) data from another model from my current view

No code to show. I just want to understand something. I already do some MVC code (I have a model, I ask Visual Studio to create Controller and View).
Each view has only "ONE MODEL" associated. So, with Razor, I can show data from this model. I play with my code and I understand it up to now.
BUT ...
On the same view, HOW we can work with another MODEL ?
For me, a model is simply a class with properties, etc. My database has an equivalent "data table" for each model. I can manipulate it with Entity Framework ... no problem. But, I need to use DATA from different model (different table) in the SAME VIEW and Visual Studio does not give me permission to use another MODEL in the view.
What is the strategy ? (or maybe I don't understand something ...)
Thank you.
The strategy is to build a view model, a model built to be displayed, and represents the data that you need to use.
Example :
You have these classes, classes who are a representation of your database :
public class FootballTeam{
public string Name{get;set;}
public string Logo{get;set;}
}
public class FootballGame{
public Datetime Date {get;set;}
public string Competition {get;set;}
}
public class Referee{
public string Name{get;set;}
public int Experience {get;set;}
}
To display information about a match game, you can create a view model for this, class who can references some classes of your business model if necessary :
public class GameViewModel{
[DisplayName("Home team")]
public FootballTeam HomeTeam{get;set;}
[DisplayName("Referee")]
public Referee Referee{get;set;}
[DisplayName("Visitor team")]
public FootballTeam VisitorTeam {get;set;}
[DisplayName("Comments")]
public List<string> RedactionComments{get;set;}
}
And create a view who will consume this GameViewModel.
In general, when you create a new MVC project, your have a folder named "ViewModels" in your presentation layer who contains some classes like this one.
This method allows to separate your business model to your presentation model, which are 2 completely different things.
There are very good answers here : What is ViewModel in MVC?
You can update your model type of your razor view to any type you want. It will work as long as you are passing that type from your action method.
Simply open up the razor view and change the line where it says what type the model is.
#model Customer
Now you need to make sure that you are passing a Customer object from your action
public ActionResult Create()
{
return View( new Customer());
}
Also when you create a view, You do not need to necessarily select the Model type in the Dialog box. You can keep that empty and add it to the razor view as needed ( as shown above)
If you want to bring data from 2 different table, Create a new view model which has properties needed for the view and use that as your view's model type.
You should use ViewModal to Create a ViewModal that will be combination of two modals properties as per our need
ViewModel contains the fields which are represented in the strongly-typed view. It is used to pass data from controller to strongly-typed view with Own Defined Modals
Understand how to use View Modal in MVC From Link Below -
Understand View Modal In MVC
CODE THAT DEMONSTRATE HOW TO USE VIEWMODALS IN MVC
Product.cs
public class Product
{
public Product() { Id = Guid.NewGuid(); }
public Guid Id { get; set; }
public string ProductName { get; set; }
public virtual ProductCategory ProductCategory { get; set; }
}
ProductCategory.cs
public class ProductCategory
{
public int Id { get; set; }
public string CategoryName { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
ProductViewModel.cs
public class ProductViewModel
{
public Guid Id { get; set; }
[Required(ErrorMessage = "required")]
public string ProductName { get; set; }
public int SelectedValue { get; set; }
public virtual ProductCategory ProductCategory { get; set; }
[DisplayName("Product Category")]
public virtual ICollection<ProductCategory> ProductCategories { get; set; }
}

Displaying multiple lists of data in a view (i.e. CustomerContacts, CustomerLocations)

I have a CustomersController and in the Detail.cshtml view I need to display a list of that Customer's contacts and a list of that Customer's locations. I have a Detail(int? id) ActionResult and I have access to my CustomerService from within the controller. As of now in my Detail ActionResult I am able to do:
var cust = _custService.GetCustomerById(id);
return View(cust);
How would one recommend getting the rest of my lists in the view. I think I will create a GetContacts(customerID), GetLocations(CustomerID) within my CustomerService and then call them just like I call GetCustomerByID above. If I were to do it this way how would I have access to these lists in my view.
The next thing I was thinking about was possibly creating a ViewModel that has all of the basic customer properties like customer.Name, customer.Phone but then trying to figure out how I also make sure the ViewModel has the customer's contacts and locations. Would I just add 2 more properties to the ViewModel like customer.contacts and customer.locations since EF6 will make them available to me?
Any suggestions on the best way to go about getting multiple lists of information related to an entity in a view? Customer contacts and Customer locations are both one-to-many
The best practice is using a view model to transfer the data, as you have thought about.
public class CustomerDetailViewModel {
public string Name { get; set; }
public string Phone { get; set; }
public List<Contact> Contacts { get; set; }
public List<Location> Locations { get; set; }
}

Save two Entities from one View

How to save two Entities from one View. Suppose I have two Entities Party and Person with One to Many relation. Now I need to save both Entities from Party View. I am using ASP.NET MVC4.
public partial class Cm_Opt_Pty_Party_S
{
public Cm_Opt_Pty_Party_S()
{
this.Cm_Opt_Psn_Person_S = new HashSet<Cm_Opt_Psn_Person_S>();
}
public int Pty_ID { get; set; }
public Nullable<int> Pty_PARTYTYPECODE { get; set; }
public string Pty_FULLNAME { get; set; }
public string Pty_GOVTID { get; set; }
public Nullable<int> Pty_GOVTIDTC { get; set; }
public Nullable<int> Pty_GOVTIDSTAT { get; set; }
public virtual ICollection<Cm_Opt_Psn_Person_S> Cm_Opt_Psn_Person_S { get; set; }
}
What you can do is create a ViewModel This class would contain the relevant properties needed to create both entities.
Then you base your View on the ViewModel instead, and pass that to the controller.
When you want to save the entities, you can build up the separate entities and save them.
I have a better understanding of your issue, so editing this answer to show the solution I would use.
Your Controller will deliver the Party object to your view for displaying the Party information. Using a loop you can display the items contained in the collection.
#foreach(var m in Model.Persons)
{
#Html.DisplayFor(model=>m.FirstName)
#Html.DisplayFor(model=>m.Surname)
}
When you want to add more items into the collection, you will need to render a partial view or new view containing a form for adding a Person. It will be strongly typed as Person model and the Controller action recieving the post will be expecting a Person
If for example a Person just had a FirstName,Surname and PartyId the form would use these helpers in your view
#Html.TextboxFor(m=>m.FirstName)
#Html.TextboxFor(m=>m.Surname)
#Html.TextBoxFor(m=>m.PartyId)
You then submit that back to your controller, and have logic for adding the person to the collection. Then return the view with Party model containing the newly added Person in the Persons collection.
Using #Ajax.BeginForm or some custom Jquery/Javascript you could handle this async to prevent page refreshing during the process.
If you don't want to do it this way, another option is EditorTemplates. See here for example: ASP.NET MVC LIST and Create in same view

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.

ASP.NET MVC 3 Razor- Get data from custom editor

I have an experience in work with ASP.NET forms, but new to MVC.
How can I get data from shared views on postback?
In ASP.NET Forms I can write something like this:
ASP.NET Forms:
Model code:
public class MyModelItem
{
// Just TextBox is enough for editing this
public string SimpleProperty { get; set; }
// For this property separate NestedItemEditor.ascx is required
public MyModelNestedItem ComplexProperty { get; set; }
}
public class MyModelNestedItem
{
public string FirstProperty { get; set; }
public string SecondProperty { get; set; }
}
Behavior:
Control for editing MyModelNestedItem is separate ASCX control NestedItemEditor.ascx
This is just for example, MyModelNestedItem can be much more complex, I just want to give idea what I mean.
Now when I showing this item for editing, I'm showing one asp:TextBox and one NestedItemEditor.ascx. On page postback I'm gathering data from both and that's it.
Problem with MVC:
When I'm trying to implement this scenario with MVC, I'm using customized EditorFor (through using UIHint and creating shared view). So this shared view Views\Shared\EditorTemplates\MyModelNestedItem.cshtml can now display data that is already in MyModelNestedItem property but I have no idea how to make it return new entered data.
When parent controller recieves a post request, data seems to be in Request.Form, but which is civilized way to reach it? Sure, the best solution will be if data will fetch automatically into the MyModelItem.ComplexProperty.
The action which is called on post needs to be something like:
[HttpPost]
public ActionResult Index(MyViewModel mdl)
Then all the properties of the model which have input controls (or hidden inputs) on the form will have the data which was entered on the form (or passed to it or modified by javascript, in the case of hidden inputs).
This assumes that MyViewModel is the model referenced in your view.
Writing an ActionResult method in the controller with the complex type simply worked for me:
public class Topic
{
public Topic()
{
}
public DetailsClass Details
{
get;
set;
}
}
public class DetailsClass
{
public string TopicDetails
{
get;
set;
}
}
The view:
#modelTopic
#using (Html.BeginForm("Submit","Default"))
{
#Html.EditorFor(m=>m.Details)
#:<input type="submit" />
}
The controller:
public ActionResult Index()
{
Topic topic = new Topic();
return View( topic);
}
public ActionResult Submit(Topic t)
{
return View(t);
}
When submited, the Topic t contains the value i ented within the editor (Assuming You have a custom editor for the complex type, DetailsClass in my sample)

Resources