In the MVC 3 i want to display data from two models viz. Student and Enrollment into a single view.
Student model
public class Student
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int student_id { get; set; }
public string student_name { get; set; }
public string father { get; set; }
}
Enrollment model
public class Enrollment
{
[Key]
public int enrollment_id { get; set; }
public string rollno { get; set; }
public int student_id { get; set; }
public string registration_no { get; set; }
public date registration_date { get; set; }
}
My ViewModel looks like this
public class StudentEnrollmentViewModel
{
public Student_Info Student_Info { get; set; }
public Enrollment_Info Enrollment_Info { get; set; }
[Key]
public int ID { get; set; }
}
How do I retrieve the data from the two model and assign it to a viewmodel so that I can display it in a view? I am using Repository Design Pattern.
Generally speaking, a controller would be responsible for contacting the model, storing the result set returned in a variable/array/struc that the view would consume. The model and view components/classes would be registered in the controller.
An example:
<event-handler event="display.institutions" access="public">
<notify listener="userInstitutionRights" method="getInstitutionsWithDataRightsNOXML" resultKey="request.institutions" />
<view-page name="userNav" contentKey="request.userNav"/>
<view-page name="userInstitutions" contentKey="request.pageContent"/>
<announce event="assemblePage" />
</event-handler>
Event display.institutions is calling a model component userInstitutionRights and storing the result in a resultKey request.institutions and is including two view pages userNav, userInstitutions where the resultKey is available to each.
You can use DynamicPage, Look into following example
We need to use a Dynamic view page. (More Information)
Follow following steps:
Create DynamicViewPage type
public class DynamicViewPage : ViewPage
{
public new dynamic Model { get; private set; }
protected override void SetViewData(ViewDataDictionary viewData)
{
base.SetViewData(viewData);
Model = ViewData.Model;
}`
}
Your Controller will look like
public ActionResult Account(string returnUrl)
{
LoginModel loginmodel = null;//Initialize Model;
RegistrationModel registrationModel = null ;//Initialize Model;
// Any Extra logic
return View("Account", new
{
Login = loginmodel,
Register = registrationModel
});
}
your View should Inherit from
Inherits="DynamicViewPage"
Now #Model.Login will give you Loginmodel
#Model.Register will give you RegisterModel
It should work as you expected.........
Related
I'm having trouble understanding how to implement a ViewModel in Asp.net MVC, I have the following tables:
Form
ID, Data
Report
ID, FormID, Owner, Category, Status, SubmissionDate
ReportValues
ID, ReportID, Title, Value
I'm looking for a way to display and edit Report and ReportValues in the one ViewModel where ReportValues.ReportID = Report.ID
ReportValues will have multiple entries that relate to a Report.
I have had a look at similiar questions on here and tried following a tutorial ( http://techfunda.com/howto/262/list-data-using-viewmodel ) and coming up empty handed.
If you need any more information let me know and thanks in advance for any replies!
Your View Model is nothing more than a class. You can solve this many ways, but here's an example.
Create your 3 classes like you normally would.
public class Form
{
public int Id { get; set; }
public string Data { get; set; }
}
public class ReportValues
{
public int Id { get; set; }
public int ReportId { get; set; }
public string Title { get; set; }
public string Value { get; set; }
}
public class Report
{
public int Id { get; set; }
public int FormId { get; set; }
public string Owner { get; set; }
public string Category { get; set; }
public string Status { get; set; }
public DateTime SubmissionDate { get; set; }
}
Then, create your ViewModel class to include the three above classes like this.
public class ReportViewModel
{
public Form Form { get; set; }
public ReportValues ReportValues { get; set; }
public Report Report { get; set; }
}
In your view you can access your three classes and their properties as you would in your controller. Model.Form.Id
Depending on your data types, ReportValues will likely be a property of Report, but that's entirely up to your data structure. You will need to populate the classes using whatever method you want (Entity Framework, ADO, etc.) before you can pass them to your view and use them.
I am trying to create a view (with Razor engine) by mapping the model class to Person class through the Add View option in Visual Studio 2013.
When it creates a view it only creates Age, Gender, Name fields. However, I need a view which would list down all the properties in each class; i.e. I need a view which contains the following fields: Age, Name, Gender, EmployerName, Salary, City, State, and Country.
I have a a class similar to this:
public class Person
{
public int Age { get; set }
public string Gender { get; set; }
public string Name { get; set; }
public JobDetails JobDetailsInfo { get; set; }
public Address AddressInfo { get; set; }
}
public class JobDetails
{
public string EmployerName { get; set; }
public string Designation { get; set; }
public int Salary { get; set; }
}
public class Address
{
public string City { get; set; }
public string State { get; set; }
public int Country { get; set; }
}
As your relationships are 1:1, this is pretty straight-forward.
You'll have to manually edit the view. Assuming the Model is of type Person, here's an example row:
<tr>
<td>#Model.Age</td>
<td>#Model.Name</td>
<td>#Model.Gender</td>
<td>#Model.JobDetailsInfo.EmployerName</td>
<td>#Model.JobDetailsInfo.Salary</td>
<td>#Model.AddressInfo.City</td>
<td>#Model.AddressInfo.State</td>
<td>#Model.AddressInfo.Country</td>
</tr>
This will work as long as you have that simple relationship, but if what you've shown does not correctly represent any normalisation you've applied to the data structure, this will fall flat on its face.
create the view manually or use inheritence...something like
public class jobdetails : person
{
}
I slightly changed my class structure and i created partial views for commondata,jobdetails and address and used them in my main view using #Html.Partial. I was able to pass default data by creating an object instance and loading some default values and passed the entire object to the view .The catch here is the model class which is bind to the Parent view must conatin all properties which are used for creating partial views. Pls see below
Controller method:
//Assign all properties for person object here
return View("ViewName", "PersonObject");
.cshtml:
#Html.Partial("ViewPath",Model.Data)
#Html.Partial("ViewPath",Model.JobDetailsInfo )
#Html.Partial("ViewPath",Model.AddressInfo )
public class Person
{
public CommonData Data
public JobDetails JobDetailsInfo { get; set; }
public Address AddressInfo { get; set; }
}
public class CommonData
{
public int Age { get; set }
public string Gender { get; set; }
public string Name { get; set; }
}
public class JobDetails
{
public string EmployerName { get; set; }
public string Designation { get; set; }
public int Salary { get; set; }
}
public class Address
{
public string City { get; set; }
public string State { get; set; }
public int Country { get; set; }
}
Can someone explain to me how to use multiple models with a single view in which each of the models represent a DB table?
What I've currently done is created a model file for each model.
Example Model:
[Table("Order")]
public class OrderModel
{
[Key, Column(Order = 0)]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int OrderID { get; set; }
[Key, Column(Order = 1)]
public int UserID { get; set; }
public UserProfile Account { get; set; }
public DateTime Date { get; set; }
public int ShipLocation { get; set; }
public string PONumber { get; set; }
public int StatusID { get; set; }
public StatusModel Status { get; set; }
}
Here is the other model that encompases all the models to use in a single controller / view.
public class OrderPlacementModel
{
public OrderModel OrderChild { get; set; }
public OrderItemsModel OrderItemsChild { get; set; }
public StatusModel StatusChild { get; set; }
public MaterialsModel MaterialsChild { get; set; }
public CategoryModel CategoryChild { get; set; }
public PackModel PackChild { get; set; }
}
public ActionResult PlaceOrder()
{
var viewModel = new OrderPlacementModel
{
OrderChild = new OrderModel(),//or fetch this object from your data source
OrderItemsChild = new OrderItemsChild(),
//...etcetera
};
return View(viewModel);
}
Edit
Or, if you've strongly typed your view to a List<OrderPlacementModel> instead of a single instance, you could do something similar to this:
public ActionResult PlaceOrder()
{
var viewModel = new List<OrderPlacementModel>();
var model = new OrderPlacementModel
{
OrderChild = new OrderModel(),//or fetch this object from your data source
OrderItemsChild = new OrderItemsChild(),
//...etcetera
};
viewModel.Add(model);
//lather, rinse, repeat for however many instances you need to send to your view.
return View(viewModel);
}
Ideally, you should create a view model for the view that encompasses the fields from each model that you need to expose via the view. You can then map these in your controller. I would keep your mapping classes completely ignorant of your view models. Keep your views independent of your data model.
public class OrderViewModel
{
public int OrderId { get; set; }
public int UserId { get; set; }
public DateTime Date { get; set; }
public int ShippingLocation { get; set; }
public List<ItemViewModel> Items { get; set; }
}
public class ItemViewModel
{
public int ItemId { get; set; }
public int Title { get; set; }
}
Note how I have created a view model for the order and - to allow the order have multiple items - have separated these out into a separate model class. Now, you can type your view to OrderViewModel and use as many instances of ItemViewModel as your require.
You can then map your viewmodels to database entities from your controller:
[HttpPost]
public ActionResult ConfirmOrder (OrderViewModel model)
{
if (ModelState.IsValid)
{
foreach (ItemViewModel item in model.Items)
{
/* Create instance of OrderItemsModel (or whatever your
DB mapping class is), populate with appropriate data
from 'item' and commit to database. */
}
OrderModel order = new OrderModel();
order.OrderId = model.OrderId;
order.UserId = model.UserId;
order.Date = model.Date;
order.ShipLocation = model.ShippingLocation;
/* TODO: Commit new order to database */
}
}
Doing things this way adds a little overhead to your initial development time but allows you a great deal more flexibility as you aren't forced to mould all of your views to the shape of your entity classes.
I am new to ASP.net MVC. I am trying to create a viewmodel to display a join of data. Here is some example code:
public class Person
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public ICollection<Relative> Relatives { get; set; }
}
public class Relative
{
[Key]
public int ID {get; set; }
public Person Person { get; set; }
public RelationType RelationType { get; set; }
}
public class RelationType
{
[Key]
public int ID { get; set; }
public string Description { get; set; }
}
public class PersonViewModel
{
public string Name { get; set; }
public ICollection<string> RelativeNames { get; set; }
public ICollection<string> RelativeTypes { get; set; }
}
public class PersonContext : DbContext
{
public DbSet<PersonViewModel> people { get; set; }
}
When I try to create my controller through Visual Studio, I get the following error:
Unable to retrieve metadata for PersonViewModel. One or more validations errors were detected during generation:
EntityType 'PersonViewModel' has no key defined. Define the key for this EntityType.
The error is self explanatory. You need to add an Id field to the PersonViewModel which will have to be decorated with [Key] as you have rightly done in the classes above.
View Models are convenient classes for passing data between the controller and the view. The reason you are getting this exception is that because you are passing PersonViewModel class into your dbSet. You cannot do this unless PersonViewModel class has a corresponding table. In that case PersonViewModel should not be a view model but should be a entity,a model class to represent your table.
By Looking at your code I am guessing that you have tables for Person and Relative
in your database hence you shoud do the following
public class PersonContext : DbContext
{
public DbSet<Person> Person { get; set; }
public DbSet<Relative> Relative { get; set; }
}
and populate PersonViewModel through Person and Relative properties of your DbContext classes. This could be done inside the controller or in a repository class if you have one.
I have a domain model:
public class Project
{
[Key]
public int ProjectID { get; set; }
public string Title { get; set; }
public string Slug { get; set; }
public string Content { get; set; }
public string Category { get; set; }
public string Client { get; set; }
public int Year { get; set; }
}
I have a view model (which is a portion of the above model):
public class ListProjectsViewModel
{
public IEnumerable<ProjectStuff> SomeProjects { get; set; }
public class ProjectStuff
{
public int ProjectID { get; set; }
public string Title { get; set; }
public string Slug { get; set; }
public string Content { get; set; }
}
// Some other stuff will come here
}
I have an action controller:
public ActionResult List()
{
// Get a list of projects of type IEnumerable<Project>
var model = m_ProjectBusiness.GetProjects();
// Prepare a view model from the above domain entity
var viewModel = Mapper.Map..........
return View(viewModel);
}
How can I code the mapping '........' with automapper ?
Thanks.
There are two steps.
1) Define a mapping with AutoMapper (this is usually done in some sort of bootstrapper called by Global.asax, etc.)
// since all of your properties in Project match the names of the properties
// in ProjectStuff you don't have to do anything else here
Mapper.CreateMap<Project, ListProjectsViewModel.ProjectStuff>();
2) Map the object in your controller:
// Get a list of projects of type IEnumerable<Project>
var projects = m_ProjectBusiness.GetProjects();
// Prepare a view model from the above domain entity
var viewModel = new ListProjectsViewModel
{
SomeProjects = Mapper.Map<IEnumerable<Project>, IEnumerable<ListProjectsViewModel.ProjectStuff>>(projects)
};
return View(viewModel);
The thing to note here is that you are defining a mapping between Project and ProjectStuff. What you are trying to map is a list of Projects (IEnumerable) to a list of ProjectStuff (IEnumerable). AutoMapper can do this automatically by putting that in the generic arguments as I did above. Your View Model that your view is using is wrapping your list of ProjectStuff, so I just create a new ListProjectsViewModel and do the mapping inside of that.