MVC: best way to display data from 2 tables in 1 view - asp.net-mvc

I'm trying to make a view that has data from 2 tables in my database. I have looked up a couple things and I tried to use a ViewModel but I can't get it to work. Then I was thinking about using a view and a partial view to display data from the 2 tables. What is the best way using the ViewModel or using a view and a partial view?
Also if someone knows what I am doing wrong with my ViewModel and wants to help that would be awesome.
my 2 models:
public partial class prospect
{
public prospect()
{
this.result = new HashSet<result>();
}
public int id { get; set; }
public int testid { get; set; }
public string name { get; set; }
public string surname { get; set; }
public string email { get; set; }
public string cellnumber { get; set; }
public System.DateTime timestampstart { get; set; }
public Nullable<System.DateTime> timestampend { get; set; }
public Nullable<int> totalresult { get; set; }
public string birthdate { get; set; }
public string school { get; set; }
public Nullable<int> grade { get; set; }
public string address { get; set; }
public string cityandcode { get; set; }
public virtual ICollection<result> result { get; set; }
public virtual resultpersection resultpersection { get; set; }
}
public partial class resultpersection
{
public int id { get; set; }
public int prospectid { get; set; }
public int sectionid { get; set; }
public Nullable<int> result { get; set; }
public virtual prospect prospect { get; set; }
public virtual section section { get; set; }
}
The things I want to display are:
prospect.name , prospect.surname, prospect.totalresult and all the results per section of this prospect(this comes from the resultpersection table)
my viewmodel:
namespace testAptitude.Models
{
public class ResultsPerProspect
{
public List<prospect> prospect { get; set; }
public List<resultpersection> resultPerSection { get; set; }
}
}
my controller
public ActionResult Index()
{
ResultsPerProspect vm = new ResultsPerProspect();
vm.prospect = (from p in db.prospect select p).ToList();
vm.resultPerSection = (from rps in db.resultpersection select rps).ToList(); ;
List<ResultsPerProspect> viewModelList = new List<ResultsPerProspect>();
viewModelList.Add(vm);
return View(viewModelList.AsEnumerable());
}
my view
#model IEnumerable<testAptitude.Models.ResultsPerProspect>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<table>
<thead>
<tr>
<th class="col-sm-3">
#Html.DisplayNameFor(model => model.prospect)
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(model => item.prospect)
</td>
</tr>
}
</tbody>
</table>
I can't do item.prospect.name because it say's that is doesn't contain a definition for name
and what is dispalys now is this:
prospect
System.Collections.Generic.HashSet`1[testAptitude.Models.result]
Thanks in advance!

With your current code you can access it using
#Html.DisplayNameFor(model => model.FirstOrDefault().prospect)
You are passing IEnumerable<testAptitude.Models.ResultsPerProspect> to your view i.e multiple objects of class ResultsPerProspect. You would need to iterate throught this List. Each items in this list will contain definition for prospect and resultPerSection.
Or you can pass single object of class ResultsPerProspect as you are just adding single element in list.
UPDATE
You have List Of ResultsPerProspect. and each item of ResultsPerProspect has List of prospect and List of resultPerSection. So you would need to first iterate for loop over List Of ResultsPerProspect. and inside that for loop , for loop for List of prospect List of and resultPerSection
CODE
#foreach (var item in Model)
{
foreach (var pros in item.prospect)
{
<tr>
<td>
#Html.DisplayFor(model => pros.Name)
</td>
</tr>
}
}

Why don't you create a class ("Container") that consists of your two (sub)classes (let's say A and B)? You can then create a Container object and put the needed objects in Container.A and Container.B. You can then easly pass "Container" to your view and access your objects.

Related

Eager Loading in ASP MVC returns null from navigation property

I have an ASP MVC 5 Web application with code first migrations enabled. I have two tables/classes named Post.cs and PostSubject.cs.
Post.cs
public class Post
{
public int Id { get; set; }
[Required(ErrorMessage="Title is required")]
[MaxLength(255,ErrorMessage="Title too long")]
public string Title { get; set; }
[MaxLength(1023,ErrorMessage="Description too long")]
[Required(ErrorMessage = "Description is required")]
public string Description { get; set; }
public PostSubject PostSubject { get; set; }
[Display(Name="Stream")]
[Required(ErrorMessage="Choose a Stream")]
public int PostSubjectId { get; set; }
[NotMapped]
public HttpPostedFileBase Attachment { get; set; }
}
PostSubject.cs
public class PostSubject
{
public short Id { get; set; }
public string SubjectName { get; set; }
}
I am trying to load all the Posts along with their PostSubjects in the index view.
Index Action
[HttpGet]
public ActionResult Index()
{
var contributions =_context.Posts.Include(m=>m.PostSubject).ToList();
return View(contributions);
}
Index Html
#model IEnumerable<Cluster_University.Models.Post>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<table>
<tr>
<td>Title</td>
<td>Descripttion</td>
<td>Subject</td>
</tr>
#foreach (var posts in Model)
{
<tr>
<td>#posts.Title</td>
<td>#posts.Description</td>
<td>#posts.PostSubject.SubjectName</td>
</tr>
}
</table>
Problem: I have a null reference error at #Posts.PostSubject.SubjectName
Please make me understand the problem in my code.

Include query result to List

I have a list of Hospitals
Hospital model:
public class Hospital
{
[Key]
public int HospitalID { get; set; }
public string Name { get; set; }
public virtual ICollection<HospitalSpeciality> HospitalSpecialities { get; set; }
public virtual ICollection<UserHospital> UserHospitals { get; set; }
}
and I have users associated to hospital. Model:
public class UserHospital
{
[Key]
public int UserHospitalID { get; set; }
public int HospitalID { get; set; }
public Hospital Hospitals { get; set; }
public string Id { get; set; }
public ApplicationUser Users { get; set; }
}
I need, on my list, return also the number of the user's that are associated to the Hospital.
This query is easy if I have only 1 hospital, but in my scenario, I have a list of hospitals
Controller:
public ActionResult Index()
{
var result = db.Hospitals.ToList();
return View(result);
}
I really don't know how to include the result of the query (number of users) on my list.
My view:
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.HospitalID }) |
#Html.ActionLink("Details", "Details", new { id=item.HospitalID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.HospitalID })
</td>
</tr>
}
It looks like you need to ensure the users are being returned in the query... Like so:
public ActionResult Index()
{
var result = db.Hospitals
.Include("UserHospitals")
.Include("UserHospitals.Users")
.ToList();
return View(result);
}
Even if they are virtual, lazy loading won't occur because you are accessing the property in your razor view. The Include is forcing Eager Loading.
Alternatively, expose another Dbset...
public DbSet<User> Users { get; set; }
Now you can select the following:
db.Users.Where(x => !x.active).ToList();
Let me know how you get on :)

How to Use a View Model with LINQ to Entities

I'm new to ASP.NET MVC, but I cant seem to understand the rules concerning View Models. The example I'm showing here definitely resembles other examples from various sources so I'm totally flumuxed.
I've used Code First With Entity Framework 6 on VS 2013 MVC 5, and created the following two Models.
public class Task
{
public int TaskId { get; set; }
public int UserId { get; set; }
public String Title { get; set; }
public String Description { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public virtual User User { get; set; }
}
public class User
{
public int UserId { get; set; }
public String UserName { get; set; }
public String Password { get; set; }
public String FullName { get; set; }
public String Email { get; set; }
public String Status { get; set; }
public String Role { get; set; }
public virtual ICollection<Task> Tasks { get; set; }
}
And here is my Context.
public class FRESHContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Task> Tasks { get; set; }
public DbSet<Artefact> Artefacts { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
public System.Data.Entity.DbSet<FRESH.ViewModel.ManageTasksViewModel> ManageTasksViewModels { get; set; }
}
Now seeing that there is a one to many relationship between User and Task, I want to list tasks out showing which User has been assigned to them (Well this 'is' just a learning example), so I figured that this would benefit from designing a special View Model to strongly type to the View page and to use a LINQ to Entities query to derive the model to send to the View Page. Here is my View Model to be used with the strongly typed View Page.
public class ManageTasksViewModel
{
public int TaskId { get; set; }
public int UserId { get; set; }
public String FullName { get; set; }
public String Title { get; set; }
public String Description { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
And don't worry, I've correctly strongly typed the View Page as follows;
#model IEnumerable<FRESH.ViewModel.ManageTasksViewModel>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.UserId)
</th>
<th>
#Html.DisplayNameFor(model => model.FullName)
</th>
<th>
#Html.DisplayNameFor(model => model.Title)
</th>
<th>
etc etc .............(with brevity in mind lol.)
So now I create a LINQ to Entities query, which seems quite reasonable to me after watching, oh I don't know a thousand videos, lol.
public class ManageTasksController : Controller
{
private FRESHContext db = new FRESHContext();
// GET: ManageTasks
public ActionResult Index()
{
var query = (from U in db.Users
join T in db.Tasks on U.UserId equals T.UserId
select new ManageTasksViewModel
{
TaskId = T.TaskId,
UserId = U.UserId,
FullName = U.FullName,
Title = T.Title,
Description = T.Title,
StartDate = T.StartDate,
EndDate = T.EndDate
}).Take(10).ToList();
return View("Index",query);
}
And of course it built! yeehaar!, but when the code gets to the ActionResult Index(), I get this Exception.
An exception of type 'System.NotSupportedException' occurred in EntityFramework.SqlServer.dll but was not handled in user code
Additional information: The entity or complex type 'FRESH.DAL.ManageTasksViewModel' cannot be constructed in a LINQ to Entities query.
So what have I done wrong, and also could I do this better another way, I haven't looked into LINQ to SQL, as I thought that this method would surely work. Any help would be much appreciated. Thank you.
You should not have a viewmodel in your dbcontext. This is a viewModel only and is totally different than your entities.
public System.Data.Entity.DbSet<FRESH.ViewModel.ManageTasksViewModel>
ManageTasksViewModels { get; set; }
Thanks for all those who gave their time to help me on this, Basically I was going over the Contoso University tutorial again and got the answer to this, basically it's ridiculously similar to my first attempt, except that I was trying.
select new ManageTasksViewModel
{
.
.
.
};
whereas I should have been saying;
select new ManageTasksViewModel()
{
.
.
.
}
public class ManageTasksController : Controller
{
private FRESHContext db = new FRESHContext();
// GET: ManageTasks
public ActionResult Index()
{
IQueryable<ManageTasksViewModel> query = from tasks in db.Tasks
join users in db.Users on tasks.UserId equals users.UserId
select new ManageTasksViewModel()
{
TaskId = tasks.TaskId,
UserId = users.UserId,
FullName = users.FullName,
Title = tasks.Title,
Description = tasks.Description,
StartDate = tasks.StartDate,
EndDate = tasks.EndDate
};
return View(query.ToList());
}
Anyway hope this is useful to someone.

Kendo Grid edit popup complex model submitting

I’m trying to use complex models with Kendo grid edit popup. When submitting ALResults object properties are always null. It works fine when I’m not using Kendo. Is there a problem with kendo complex model submitting?
public class InitialApplicantLevel2Model
{
public InitialApplicantLevel2Model()
{
alResultsModel = new ALResults();
}
public int InitialApplicantLevel2ID { get; set; }
public string ApplicantName { get; set; }
public string ContactNumber { get; set; }
public string School { get; set; }
[Required(ErrorMessage="Ref No. required.")]
public int? EnquiryID { get; set; }
public ALResults alResultsModel { get; set; }
}
public class ALResults
{
public int ResultsID { get; set; }
public int InitialApplicantLevel2ID { get; set; }
public string Stream { get; set; }
public string Grading { get; set; }
public string IndexNo { get; set; }
public int? Year { get; set; }
public int? Attempt { get; set; }
public double? ZScore { get; set; }
public string Medium { get; set; }
}
#model SIMS.Models.StudentIntake.InitialApplicantLevel2Model
<tr>
<td>Year: </td>
<td>#Html.TextBoxFor(o=>o.alResultsModel.Year)</td>
<td>Index No: </td>
<td>#Html.TextBoxFor(o=>o.alResultsModel.IndexNo)</td>
<td>Medium: </td>
<td>#Html.TextBoxFor(o=>o.alResultsModel.Medium)</td>
</tr>
<tr>
<td>Stream: </td>
<td>#Html.TextBoxFor(o=>o.alResultsModel.Stream)</td>
<td>Attempt: </td>
<td>#Html.TextBoxFor(o=>o.alResultsModel.Attempt)</td>
<td>Zscore: </td>
<td>
#Html.TextBoxFor(o=>o.alResultsModel.ZScore)
</td>
</tr>
I found the answer here
Unfortunately Kendo UI doesn't support Class Composition / View Models
containing complex objects, your View Models need to be completely
flat to avoid unexpected behaviour.

How to get Country Name based on its Id in Entity framework using Mvc?You can just have a look at the following things

The above is my database .I have for tables Contact,Countries,States,Cities.The Country in contact table is foreign key to the Id in countries table. And I am using entity framework to get the data.I am using database first approach.I am getting my Contact details by the following code
public class ContactManager
{
public static List<Contact> GetContacts()
{
using (var obj = new EntityDBConnectionString())
{
return obj.Contacts.ToList();
}
}
}
And in the Controller part I have like this
public ActionResult ViewContacts()
{
return View("ViewContacts",ContactManager.GetContacts());
}
and atlast the View(cshtml)
#model List<Entity.Data.Contact>
#{
ViewBag.Title = "ViewContacts";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>ViewContacts</h2>
<table style="font-family:'Segoe UI';font-size:20px;display:table" border="1" cell-spacing="1" >
#foreach (var item in Model)
{
<tr style="border:1px solid black;padding-right:3px;background-color:lightblue;display:table-row">
<td>#item.Id</td>
<td>#item.Name</td>
<td>#item.Mobile</td>
<td>#item.EmailId</td>
<td>#item.Address</td>
<td>#item.Country</td>
</tr>
}
</table>
My problem is that I am getting the CountryId's in the output table as it is a foreign.Can I get the Country Name as output
The output I am getting is the below one
How to get the Country name in the data part and pass to the controller and how to pass it to the view? Can anyone help me out .Thanks in advance!!!!!!
The below is my Contact class
public partial class Contact
{
public int Id { get; set; }
public string Name { get; set; }
public string EmailId { get; set; }
public string Mobile { get; set; }
public string Address { get; set; }
public Nullable<int> City { get; set; }
public Nullable<int> State { get; set; }
public Nullable<int> Country { get; set; }
public virtual City City1 { get; set; }
public virtual Country Country1 { get; set; }
public virtual State State1 { get; set; }
}
and the edmx file is
I asume that you have set database realtionship for country and contact table. now in view you can get country name using
<td>#item.Country.Name</td>
Please Include your Country table in EF query like to bring the country
public static List<Contact> GetContacts()
{
using (var obj = new EntityDBConnectionString())
{
return obj.Contacts.Include("Country").ToList();
}
}
and use the below in your view
#item.Country.Name

Resources