ASP.NET MVC4
I have Business layer DLL which communicates to my DAL and retrieves classes like:
public class ProductionParameter
{
public string CompanyCode { get; set; }
public string UnitCode { get; set; }
public string ItemDescriptionLocal { get; set; }
public string ItemDescriptionEnglish { get; set; }
public string ConsumedItemDescriptionLocal { get; set; }
public string ConsumedItemDescriptionEnglish { get; set; }
public string LotCategory1Description { get; set; }
public string LotCategory2Description { get; set; }
public string LotCategory3Description { get; set; }
public string LotCategory1Code { get; set; }
public string LotCategory2Code { get; set; }
public string LotCategory3Code { get; set; }
public string LineCode { get; set; }
public string LineCodeDisplay { get; set; }
public List<Pallet> PalletsProduced { get; set; }
}
My controller gets the above info but my View doesnt need all the above.
For example lets say i get 3 production parameters classes that each one has 20 Pallets. It means that each productionparameter has 20 pallets produced.
I want to show to my MVC View consolidated data for each production parameter.
How i do it correctly?
Standard Case:
Do i create in Models a class with exactly the info i need for the view and then define this class in the #model directive?
AJAX:
What changes if i want to make this via AJAX? My AJAX call will return the consolidated data or the full data and let AngularJS or Jquery make the consolidation on the client?
Standard Case:
Do i create in Models a class with exactly the info i need for the
view and then define this class in the #model directive?
Yes, that's exactly what you should do. You define a view model with only the properties requires by your view. Then your controller action will aggregate one or more domain models into the view model and pass it to the view.
AJAX:
What changes if i want to make this via AJAX? My AJAX call will return
the consolidated data or the full data and let AngularJS or Jquery
make the consolidation on the client?
You should always return a view model from your controller action containing only the required information to the client. This way, not only that you optimize bandwidth and network usage, but you make the life of the clients much easier. They no longer need to make complex data querying and projections but directly use the information that is provided to them under the form of a view model.
Conclusion: your controller actions should always take and pass specifically designed view models from/to views.
You can use ViewModels keeping your business logic separate from Views.A ViewModel represents data that you want to have displayed on your view/page.
Lets say that you have an ProductionParameterclass which contains the following properties:
public class ProductionParameter
{
public string CompanyCode { get; set; }
public string UnitCode { get; set; }
public string ItemDescriptionLocal { get; set; }
public string ItemDescriptionEnglish { get; set; }
public string ConsumedItemDescriptionLocal { get; set; }
public string ConsumedItemDescriptionEnglish { get; set; }
public string LotCategory1Description { get; set; }
public string LotCategory2Description { get; set; }
public string LotCategory3Description { get; set; }
public string LotCategory1Code { get; set; }
public string LotCategory2Code { get; set; }
public string LotCategory3Code { get; set; }
public string LineCode { get; set; }
public string LineCodeDisplay { get; set; }
public List<Pallet> PalletsProduced { get; set; }
}
View models differ from domain models in that view models only contain the data (represented by properties) that you want to use on your view.
Suppose, you want to display only following properties on the view, then your ViewModel can be
public class ProductionParameterViewModel
{
public string CompanyCode { get; set; }
public string UnitCode { get; set; }
public string ItemDescriptionLocal { get; set; }
public string ItemDescriptionEnglish { get; set; }
public string ConsumedItemDescriptionLocal { get; set; }
public string ConsumedItemDescriptionEnglish { get; set; }
public string LineCodeDisplay { get; set; }
public List<Pallet> PalletsProduced { get; set; }
}
Then , on your View, you can use it as below:
#model MyProject.ViewModels.ProductionParameterViewModel
Edit:
If you have two models, then you can put them in a single model as below:
public class ViewModel1
{
}
public class ViewModel2
{
}
public class MyAggregateModel
{
public ViewModel1 Model1 { get; set;}
public ViewModel2 Model2 { get; set;}
}
Related
I have two models without relationship in ASP.NET MVC.
Model 1:
public int ExperienceId { get; set; }
public string ExperienceTitle { get; set; }
public string ExperienceText { get; set; }
Model 2:
public int EducationId { get; set; }
public string EducationTitle { get; set; }
public string EdicationText { get; set; }
I want to display the information of these two tables (models) that have no relationship between them using a view model together in one view.
that's easy to do if that i understood from your question, check below code.
public class ViewModel{
public Model1 model_1{ get; set; }
public Model2 model_2{ get; set; }
}
Say I have the following model:
class Product
{
public string Id { get; set; }
public string Name { get; set; }
public string Brand { get; set; }
public string Description { get; set; }
public string Image { get; set; }
}
For a list view in the client I would only need the following:
class ProductListView
{
public string Name { get; set; }
public string Image { get; set; }
}
For a detail view I would need the following:
class ProductDetailView
{
public string Name { get; set; }
public string Brand { get; set; }
public string Description { get; set; }
public string Image { get; set; }
}
For an update of the name, I would need:
class ProductUpdateName
{
public string Id { get; set; }
public string Name { get; set; }
}
For an update of the description and brand, I would need:
class ProductUpdateDescriptionAndBrand
{
public string Id { get; set; }
public string Brand { get; set; }
public string Description { get; set; }
}
For all these different combinations, do I create the same number of classes? This sounds horrible though.
I can do anonymous classes instead but then I would need reflection to figure out the actual fields. This also sounds wrong.
So what is the best way?
A DTO by nature should represent a particular use case. The class is a representation of the data that will be transferred - hence the name. As such, whenever there's different data, yes, you should have a different DTO.
Now, that doesn't stop you from building upon your DTOs via inheritance. For example, ProductDetailView could inherit from ProductListView, since it is a superset of the properties of ProductListView. However, you should not inherit from ProductUpdateDescriptionAndBrand, because that includes an Id property, which ProductDetailView does not.
In those cases, you can opt to employ composition instead. For example, you could have something like:
public class BrandDescription
{
public string Brand { get; set; }
public string Description { get; set; }
}
And then:
public class ProductUpdateDescriptionAndBrand
{
public string Id { get; set; }
public BrandDescription BrandDescription { get; set; }
}
public class ProductDetailView : ProductListView
{
public BrandDescription BrandDescription { get; set; }
}
Otherwise, then just keep the classes as they are and use all of them as appropriate. Remember also that each of these serves a particular purpose (representing a particular group of data being transferred). As such, a property like Description, doesn't necessarily mean the same thing in all places. Just because the properties are similar or named the same doesn't mean they are handling the same concept(s).
I need to pass a complex object to a .NET MVC controller from a View and i'm using Razor to do so. Here is my link:
<a href="#Url.Action("PlayVideo","Media",m)">
where "m" is an object of type MediaVM like this:
public class MediaVM
{
public int Id { get; set; }
public DateTime Date { get; set; }
public VCMediaType MediaType { get; set; }
public string RoomName { get; set; }
public string ThumbPath { get; set; }
public List<string> Sources { get; set; }
public string Description { get; set; }
public string CaseNumber { get; set; }
public string PatientFullName { get; set; }
}
The problem is with the "Sources" property; because it is a List of Strings, when i call the action at the "MediaController" it receives the MediaVM object correctly constructed except for the Sources property, which just contains a Collection with one String with the literal "System.Collections.Generic.List`1[System.String]".
The Constructor:
public ActionResult PlayVideo(MediaVM videoMedia)
{
return PartialView("Player", videoMedia);
}
How could i pass the complete list of strings? Is it possible?
Well I have a very complex User Profile system in a social network application I am building. The profile page has tabs that distinguishes each category of user profile information: Basic, Education, Job. There is a UserProfileViewModel sitting on top of everything, which composes of inner view models such as BasicViewModel, EducationViewModel and JobViewModel. Consider the structure as below:
public class ProfileViewModel
{
public string id { get; set; }
public BasicViewModel basic { get; set; }
public EducationViewModel education { get; set; }
public JobViewModel job { get; set; }
}
public class BasicViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime? DateOfRegistration { get; set; }
public DateTime? DateOfBirth { get; set; }
public string Gender { get; set; }
public string PhoneNumber { get; set; }
[Display(Name = "Biography")]
public string Biography { get; set; }
public string NickName { get; set; }
public string FavoriteQuotes { get; set; }
}
public class EducationViewModel{
public string EducationStatus { get; set; }
public List<University> Universities { get; set; }
public string CourseStatus { get; set; }
public string CourseSpecialization { get; set; }
public List<string> EducationEvents { get; set; }
}
public class JobViewModel
{
public string WorkStatus { get; set; }
public List<Company> Companies { get; set; }
}
public abstract class Organization
{
public string Name { get; set; }
public DateTime? Year { get; set; }
public int TimePeiod { get; set; }
}
public class University: Organization
{
public string Degree { get; set; }
public string Profession { get; set; }
}
public class Company: Organization
{
public string Website { get; set; }
public string Position { get; set; }
}
So the question is, does data annotation for model validation(both server and client side) work for a model that has composite structure like this? If so, do I just place annotation like I usually do with simple view models? If not, how can I achieve this in alternative ways? Please help.
Any single view model may contain other viewmodels like this:
This model is server side:
[Serializable]
public class MyBigViewModel : IValidatableObject
{
public MyBigViewModel(){
MyOtherViewModel = new MyOtherViewModel();
MyThirdViewModel = new MyThirdViewModel();
}
public MyOtherViewModel {get;set;}
public MyThiddViewModel {get;set;}
public void Post(){
//you can do something here based on post back
//like maybe this where the post method here processes new data
MyOtherViewModel.Post();
}
}
The controller could look like this:
public ActionResult UserList (MyBigViewModel uvm){
if(ModelState.IsValid){
uvm.Post();
return View(uvm);
}
return View(uvm);
}
You can implement the IValidateableObject to do "server side" validation. In the example above however, we want each viewmodel to "contain" it's own model for validation.
Each viewmodel property can use data annotations "contained" in only that viewmodel. It's a very nice way to "Contain" what you want where you want.
I very often use multiple Viewmodels in main VM and pass them in with partial views as needed.
I have two models:
public class Resort
{
public int ID { get; set; }
public String Name { get; set; }
public int BlackDiamond { get; set; }
public int BlueSquare { get; set; }
public int GreenCircle { get; set; }
public int TerrainPark { get; set; }
}
And
public class Input
{
public int ID { get; set; }
public string Name { get; set; }
public bool GreenCircle { get; set; }
public bool BlueSquare { get; set; }
public bool BlackDiamond { get; set; }
public bool TerrainPark { get; set; }
}
The idea here is to create a Controller that will allow me to have access to data from both Models as my logic will basically allow me to search through all Resorts looking for the Resort with the highest number of whichever experience level is preferred. As an example, let's say that I prefer BlackDiamonds, so I would want to search for the Resort with the highest number of BlackDiamonds. So I will need to know which experience level is preferred and which Resort has the highest number of that preferred experience level.
You could define a view model aggregating those 2 models:
public class MyViewModel
{
public Input Input { get; set; }
public Resort Resort { get; set; }
}
Now the controller actions could take/pass this view model from/to the views which will be strongly typed to the view model. Now you will have all the necessary data.