Reference model class in controller, so muliple data can be in one view - sql

I am trying to get data from multiple SQL Server stored procedure to be accessible in 1 view so I can then run comparisons and create graphs/grids etc.
I got each section to work on their own, and I am now trying to get them to work together.
I have change my controller and put the field types into their own classes, and then created a "Ring of Rings" class, and put them all in.
namespace APP.Models
{
public class SP_RESULTS
{
public type Type { get; set; }
public status Status { get; set; }
public condition Condition { get; set; }
public rooms Rooms { get; set; }
}
public class type
{
[Key]
public decimal type_id { get; set; }
public string type_code { get; set; }
public string type_name { get; set; }
}
public class status
{
//status
public decimal status_id { get; set; }
public string status_code { get; set; }
public string status_name { get; set; }
public string rentable { get; set; }
}
public class condition
{
//condition
public decimal condition_id { get; set; }
public string condition_code { get; set; }
public string condition_name { get; set; }
public string rentable { get; set; }
public int colour_code { get; set; }
public int service_order { get; set; }
}
public class rooms
{
//rooms
public decimal room_id { get; set; }
public string room_no { get; set; }
public decimal type_id { get; set; }
public int floor { get; set; }
public decimal status_id { get; set; }
public decimal condition_id { get; set; }
}
}
I then amended each section of my controller that was running SQL Server stored procedures, to use the correct class name instead of the "ring of rings" name, IE:
var outputmodel4 = new List<rooms>();
var command4 = db.Database.Connection.CreateCommand();
command4.CommandText = "SELECT rooms.room_id , rooms.room_no , rooms.type_id , rooms.floor_no , rooms.status_id , rooms.condition_id FROM rooms";
using (var SPOutput4 = command4.ExecuteReader())
{
foreach (var row in SPOutput4)
{
outputmodel4.Add(new rooms()
{
room_id = (decimal)SPOutput4["room_id"],
room_no = (string)SPOutput4["room_no"],
type_id = (decimal)SPOutput4["type_id"],
floor_no = (int)SPOutput4["floor_no"],
status_id = (decimal)SPOutput4["status_id"],
condition_id = (decimal)SPOutput4["condition_id"],
});
}
db.Database.Connection.Close();
return View(outputmodel4);
}
...etc for other SQL stored procedures
..and the same with my view
#model IEnumerable<app.Models.SP_RESULTS >
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Rooms.room_id)
</th>
<th>
#Html.DisplayNameFor(model => model.Rooms.room_no)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Rooms.room_id)
</td>
<td>
#Html.DisplayFor(modelItem => item.Rooms.room_no)
</td>
</tr>
}
</table>
…etc for the other models
Everything looks fine in VBS (no red swiggles), but when I access the view in the browser, I get an error:
Server Error in '/' Application.
The model item passed into the dictionary is of type 'System.Collections.Generic.List1[app.Models.rooms]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable1[app.Models.SP_RESULTS]'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: The model item passed into the dictionary is of type 'System.Collections.Generic.List1[app.Models.rooms]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable1[app.Models.SP_RESULTS]'.
If I go back to my "rings of rings" model, and change it to this :
public class SP_RESULTS
{
public IEnumerable<type> Type { get; set; }
public IEnumerable<status> Status { get; set; }
public IEnumerable<condition> Condition { get; set; }
public IEnumerable<rooms> Rooms { get; set; }
}
and change the following lines in in my controller:
var outputmodel4 = new List<rooms>();
outputmodel4.Add(new rooms()
to
var outputmodel4 = new List<SP_RESULTS>();
outputmodel4.Add(new SP_RESULTS()
VBS tells me that that
SP_RESULTS does not contain a definition for room_id
I've tried prefixing the definition with the class name, with no luck.
I've looked on SO, fourms.asp.net and google.. can cannot see a solution (there probably is, but I am unsure what solution I an looking for.... if that makes sense).
Would someone be able to tell me what I need to do to get all my model classes working in the same view ?
I apologise now, as I realize that this question has probably been asked several (million) times, but I cannot seem to fine out that jumps out says THIS is that way to do it.

For anyone else looking for an answer (and for future me), I got this work by putting the models like this :
namespace APP.Models
{
public class SP_RESULTS
{
public type Type { get; set; }
public status Status { get; set; }
public condition Condition { get; set; }
public rooms Rooms { get; set; }
public class type
{
[Key]
public decimal type_id { get; set; }
public string type_code { get; set; }
public string type_name { get; set; }
}
public class status
{
//status
public decimal status_id { get; set; }
public string status_code { get; set; }
public string status_name { get; set; }
public string rentable { get; set; }
}
public class condition
{
//condition
public decimal condition_id { get; set; }
public string condition_code { get; set; }
public string condition_name { get; set; }
public string rentable { get; set; }
public int colour_code { get; set; }
public int service_order { get; set; }
}
public class rooms
{
//rooms
public decimal room_id { get; set; }
public string room_no { get; set; }
public decimal type_id { get; set; }
public int floor { get; set; }
public decimal status_id { get; set; }
public decimal condition_id { get; set; }
}
}
}
Using VIEWDATA in the controller for each Store procedure:
var outputmodel3 = new List<SP_RESULTS.conditions>();
var command3 = db.Database.Connection.CreateCommand();
command3.CommandText = "dbo.pr_PROCEDUREONE";
command3.CommandType = System.Data.CommandType.StoredProcedure;
using (var SPOutput3 = command3.ExecuteReader())
{
foreach (var row in SPOutput3)
{
outputmodel3.Add(new SP_RESULTS.conditions()
{
condition_id = (decimal)SPOutput3["condition_id"],
condition_code = (string)SPOutput3["condition_code"],
condition_name = (string)SPOutput3["condition_name"],
});
}
ViewData["CONDITIONSOutput"] = outputmodel3;
}
var outputmodel4 = new List<SP_RESULTS.rooms>();
var command4 = db.Database.Connection.CreateCommand();
command4.CommandText = "SELECT rooms.room_id , etc FROM rooms";
using (var SPOutput4 = command4.ExecuteReader())
{
foreach (var row in SPOutput4)
{
outputmodel4.Add(new SP_RESULTS.rooms()
{
room_id = (decimal)SPOutput4["room_id"],
room_no = (string)SPOutput4["room_no"],
});
}
ViewData["ROOMSOutput"] = outputmodel4;
db.Database.Connection.Close();
return View();
}
..and then changing my view to read :-
table class="table">
<tr>
<th>
Condition ID
</th>
<th>
Condition code
</th>
<th>
Condition name
</th>
<th>
is it rentable?
</th>
<th>
Condition color code
</th>
<th>
Condition service order
</th>
<th></th>
</tr>
#foreach (var item in ViewData["CONDITIONSOutput"] as IEnumerable<Happ.Models.SP_RESULTS.conditions>)
{
<tr>
<td>
#item.condition_id
</td>
<td>
#item.condition_code
</td>
<td>
#item.condition_name
</td>
<td>
#item.rentable
</td>
<td>
#item.colour_code
</td>
<td>
#item.service_order
</td>
</tr>
}
</table>
<table class="table">
<tr>
<th>
Room ID
</th>
<th>
Room No
</th>
<th>
Rooms type_id
</th>
<th></th>
</tr>
#foreach (var item in ViewData["ROOMSOutput"] as IEnumerable<APP.Models.SP_RESULTS.rooms>)
{
<tr>
<td>
#item.room_id
</td>
<td>
#item.room_no
</td>
</tr>
}
</table>

Related

How can I display the total number of records a table holds(the count) in a view by passing the count value in the "return view method"

How can I display the total number of records a table holds(the count). I would like to display the count in a view so I am trying to pass the count as a parameter on return view but I get an error saying cannot convert string to int. I am pretty sure there is a smarter way to do this. I have tried converting the int value using toString() but I still get syntax erros thereafter. I have placed both my controller and view below. Notice what I am trying to do in my controller in the return view method I am trying to insert the count but I get an error that says
cannot convert from int? to string
Controller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Data;
using System.Web.Http;
using System.Configuration;
using PagedList;
namespace App.Web.Controllers
{
public class DisplayUploadedFileController : Controller
{
private EntitiesModel db = new EntitiesModel();
public ActionResult DisplayUploadedFileContents(int? id, int? page, int? totalCount)
{
var vm = new dbclients_invalidEmailsVM();
vm.UploadId = id ?? default(int);
if (page == null)
{
page = 1;
}
int pageSize = 10;
int pageNumber = (page ?? 1);
var rows = from myRow in db.tbl_dataTable
select myRow;
totalCount = rows.Count();
return View(db.tbl_dataTable.OrderByDescending(r => r.ClientId).Where(r => r.UploadId == id).ToList().ToPagedList(pageNumber, pageSize), totalCount);
}
}
}
View
#model PagedList.IPagedList<App.Web.marketingdbclients_dataTable>
#using PagedList.Mvc;
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link href="http://www.jqueryscript.net/css/jquerysctipttop.css" rel="stylesheet" type="text/css">
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="pagination.js"></script>
</head>
<body>
<div class="container" style="margin-top:50px;">
<table class="table" id="table">
<tr>
<th>
First Name
</th>
<th>
Last Name
</th>
<th>
Cell1
</th>
<th>
Email1
</th>
<th>
Company
</th>
<th>
Job Title
</th>
<th>
Province
</th>
<th>
Source
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Cell1)
</td>
<td>
#Html.DisplayFor(modelItem => item.Email1)
</td>
<td>
#Html.DisplayFor(modelItem => item.Company)
</td>
<td>
#Html.DisplayFor(modelItem => item.JobTitle)
</td>
<td>
#Html.DisplayFor(modelItem => item.PhysicalProvince)
</td>
<td>
#Html.DisplayFor(modelItem => item.Source)
</td>
</tr>
}
</table>
</br>
Number of Records #Model.Count()<br />
Page #(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of #Model.PageCount
#Html.PagedListPager(Model, page => Url.Action("DisplayUploadedFileContents", new { uploadId = Model.First().UploadId, page }))
</div>
</body>
</html>
My Table Represented as a model
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace App.Web
{
using System;
using System.Collections.Generic;
public partial class marketingdbclients_dataTable
{
public int ClientDataId { get; set; }
public Nullable<int> ClientId { get; set; }
public Nullable<int> UploadId { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string IdentificationNumber { get; set; }
public string RaceId { get; set; }
public string DateOfBirth { get; set; }
public string Age { get; set; }
public string TitleTypeId { get; set; }
public string GenderTypeId { get; set; }
public string Nationality { get; set; }
public string PhysicalCountry { get; set; }
public string PhysicalProvince { get; set; }
public string PhysicalCity { get; set; }
public string Area { get; set; }
public string HighestQualification { get; set; }
public string CurrentQualification { get; set; }
public string PhysicalAddress { get; set; }
public string PostalAddress { get; set; }
public string Cell1 { get; set; }
public string Cell2 { get; set; }
public string Cell3 { get; set; }
public string Cell4 { get; set; }
public string Work1 { get; set; }
public string Work2 { get; set; }
public string Work3 { get; set; }
public string Work4 { get; set; }
public string Home1 { get; set; }
public string Home2 { get; set; }
public string Home3 { get; set; }
public string Home4 { get; set; }
public string LSMGroup { get; set; }
public string Municipality { get; set; }
public string Crediting_Rating { get; set; }
public string Email1 { get; set; }
public string Email2 { get; set; }
public string Email3 { get; set; }
public string Email4 { get; set; }
public string Income { get; set; }
public string Company { get; set; }
public string Industry { get; set; }
public string JobTitle { get; set; }
public string LeadStage { get; set; }
public string ReggieNumber { get; set; }
public string Source { get; set; }
public System.DateTime DateInserted { get; set; }
//public int totalEntriesCount { get; set; }
}
}
Please create a new ViewModel class and store your two inputs like so:
public class MyViewModel
{
public List<marketingdbclients_dataTable> marketingdbclients_dataTables { get; set; }
public int totalCount { get; set; }
public MyViewModel()
{
this.marketingdbclients_dataTables = new List<marketingdbclients_dataTable>();
this.totalCount = 0;
}
}
Controller file should be
public ActionResult DisplayUploadedFileContents(int? id, int? page, int? totalCount)
{
var vm = new dbclients_invalidEmailsVM();
vm.UploadId = id ?? default(int);
if (page == null)
{
page = 1;
}
int pageSize = 10;
int pageNumber = (page ?? 1);
var rows = from myRow in db.tbl_dataTable
select myRow;
totalCount = rows.Count();
MyViewModel model = new MyViewModel();
model.marketingdbclients_dataTables = db.tbl_dataTable.OrderByDescending(r => r.ClientId).Where(r => r.UploadId == id).ToList().ToPagedList(pageNumber, pageSize);
model.totalCount = totalCount ;
return View(model);
}
Then in your View (index.cshtml), declare MyViewModel like so:
#model WebApp.Models.MyViewModel
<div>
your html
</div>
The concept we just used is called View Model. Please read more about it here:
Understanding ViewModel
You may only pass one model object when calling View(model).
You can create an object that contains both the count and the datatable that you use as the view model.
A simple way to do this may be using an anonymous object:
return View(
new {
Page = db.tbl_dataTable.OrderByDescending(r => r.ClientId).Where(r => r.UploadId == id).ToList().ToPagedList(pageNumber, pageSize)db.tbl_dataTable.OrderByDescending(r => r.ClientId).Where(r => r.UploadId == id).ToList().ToPagedList(pageNumber, pageSize),
Count = totalCount
});

get values from two tables in one single view by stored procedure in mvc

My model is
public partial class Device
{
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Device_Id { get; set; }
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Device_Name { get; set; }
}
public partial class Customer
{
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Customer_id { get; set; }
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Customer_Name { get; set; }
}
I want to display the values in both tables in one view i am using stored procedure to get the values..
I have written procedure to get the details from the 2 tables..I need the view to be like this.
<table >
<tr>
<th>Device </th>
<th>Customer Name</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>#Html.LabelForModel(item.Device_ModelNo)</td>
<td>#Html.LabelForModel(item.Customer_Name)</td>
</tr>
}
</table>
Create a Master class and include this two classes like this
public class Master
{
public Device device { get; set; }
public Customer customer { get; set; }
}
Now type your view with the master class
#model MasterModel

Take data from different tables and display it in View Index in mvc4

I have 2 tables Work_table and Employee_table.I want to display emp_id from Work_table and corresponding emp_name from Employee_table in the index view of Employee_table.
my models are:
namespace MvcConQuery.Models
{
[Table("Work_Table")]
public class EnquiryModel
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public Int32 Enq_id { get; set; }
[Required]
[Display(Name="Name")]
public string CustomerName { get; set; }
[ReadOnly(true)]
public string Date
{
get
{
DateTime Date = DateTime.Now;
return Date.ToString("yyyy-MM-dd"); ;
}
set{}
}
[Required]
[Display(Name = "Region")]
public string Region { get; set; }
[Required]
[RegularExpression(#"^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$", ErrorMessage = "Entered phone number format is not valid.")]
[Display(Name = "Phone number")]
public string Ph_No { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email_id")]
public string Email_id { get; set; }
[Required]
[Display(Name = "Address")]
public string Address { get; set; }
[Required]
[Display(Name = "Query")]
public string Query { get; set; }
public string Referral { get; set; }
public string Feedback { get; set; }
public string Status { get; set; }
public Int32? Emp_id { get; set; }
public string FollowUpDate { get; set; }
public List<EmployeeModel> Employees { get; set; }
}}
namespace MvcConQuery.Models
{
[Table("Employee_Table")]
public class EmployeeModel
{
[Key,Column(Order=0)]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
//[ForeignKey("EnquiryModel")]
public Int32 Emp_id { get; set; }
public string Emp_Name{ get; set; }
//[Key,Column(Order=1)]
public string Region { get; set; }
//[ForeignKey("Region")]
public string Emp_PhNo { get; set; }
public string Emp_Address { get; set; }
public List<EnquiryModel> Enquires { get; set; }
}
}
How to write controller?
I stucked when writing the function in controller.
public ActionResult Index()
{
}
Please suggest a solution. thanks in advance.
Regards
I was wrong earlier, I made out from your code that there is a many -to- many relationship between Employee and Work tables. For my convenience, I have used Job as the name for your Work table / model.
I hope that you want to display a list of EmployeeIds along with the corresponding EmployeeNames in the Index View. I have added an extra property called JobName to viewmodel, you can have other properties too.
For that matter, create a ViewModel EmployeeViewModel and bind the index view of your action result with an IEnumerable<EmployeeViewModel>. The definition for EmployeeViewModel can be something like -
public class EmployeeViewModel
{
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
public string JobName { get; set; }
//..Other memberVariables..
}
Suppose these are your models -
Employee
public class Employee
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
public string Address { get; set; }
public virtual ICollection<Job> Jobs { get; set; }
}
And WorkTable, renamed it as Job for my own convenience
public class Job
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int JobId { get; set; }
public string JobName { get; set; }
public JobCategory JobCategory { get; set; }
public int EmployeeId { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
In your Index Action, you create a result set by joining the two tables, bind it to IEnumerable<EmployeeViewModel> and pass that as a model to the view. The View should receive a model of type IEnumerable<EmployeeViewModel> as I mentioned earlier,so you need to query your entities which should be something like -
public ActionResult Index()
{
//..something like this..this is IQueryable..
//...convert this to IEnumerable and send this as the model to ..
//..the Index View as shown below..here you are querying your own tables,
//.. Employee and Job,and binding the result to the EmployeeViewModel which
//.. is passed on to the Index view.
IEnumerable<EmployeeViewModel> model=null;
model = (from e in db.Employees
join j in db.Jobs on e.EmployeeId equals j.EmployeeId
select new EmployeeViewModel
{
EmployeeId = e.EmployeeId,
EmployeeName = e.EmployeeName,
JobName = j.JobName
});
return View(model);
}
Your index view should be something like -
#model IEnumerable<MyApp.Models.EmployeeViewModel>
#{
ViewBag.Title = "Index";
}
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.EmployeeId)
</th>
<th>
#Html.DisplayNameFor(model => model.EmployeeName)
</th>
<th>
#Html.DisplayNameFor(model => model.JobName)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.EmployeeId)
</td>
<td>
#Html.DisplayFor(modelItem => item.EmployeeName)
</td>
<td>
#Html.DisplayFor(modelItem => item.JobName)
</td>
</tr>
}
</table>
In this above solution, I have made an attempt to generate a situation similar to yours and address your concerns. I hope this brings some sort of respite to your worries and helps you move ahead. Take this as a map and try follow the routes to find your own destination/solution. Btw, sorry for this delayed reply. Hope this helps.
This code has something missing select new EmployeeviewModel
model = (from e in db.Employees
join j in db.Jobs on e.EmployeeId equals j.EmployeeId
select new EmployeeViewModel
{
EmployeeId = e.EmployeeId,
EmployeeName = e.EmployeeName,
JobName = j.JobName
});

How to make this razor view working?

in my MVC web apps, this is the models which uses icollection object,
public class EmpProfile
{
public int EmpProfileID { get; set; }
public string EmpName { get; set; }
public string EmpNum { get; set; }
public string ManagerEditor { get; set; }
public string DocCreatedBy { get; set; }
public virtual ICollection<PerfPlan> PerfPlans { get; set; }
public virtual ICollection<ProgReview> ProgReviews { get; set; }
}
and this is PerfPlan model, the other model ProgReviews is similar like this one.
public class PerfPlan
{
public int ID { get; set; }
public int EmpProfileID { get; set; }
public string EmpName { get; set; }
public string EmpNum { get; set; }
public string Title { get; set; }
....
public virtual EmpProfile EmpProfile { get; set; }
}
Basically, it builds one to many relationship between EmpProfile and PerfPlan, ProgReview. So one EmpProfile has 0 or many Performance plan and Progress Review data (model).Now, in my Index razor of EmpProfile, I want to list all PerfPlan and ProgReview which related to each EmpProfile, I build something like this:
#model IEnumerable<PerfM.Models.EmpProfile>
<table>
#foreach (var item in Model)
{
<tr class="#selectedRow">
<td >
#Html.ActionLink(#item.EmpName, "Index", new { id = item.EmpProfileID })
</td>
</tr>
//here I need to list all PerfPlan and ProgReview related to this EmpProfile and list under this row.
Can any expert help me to continue the codes below?
Thanks a lot,
Just use simple foreach loops like this (inside of your foreach loop) :
foreach(var plan in item.PerfPlans)
{
// here you can access your PerfPlan properties like:
<tr>
<td> #plan.Id </td>
<td> #plan.EmpName</td>
<td> #plan.EmpNum </td>
...
</tr>
}
foreach(var review in item.ProgReviews)
{
...
}
And in your Controller don't forget to include your collections:
var profiles = context.EmpProfiles.Include("PerfPlans").Include("ProgReviews");

MVC ViewModel errors

Goal: To create a re-usable drop down menu that lists my website's administrators, managers and agents. These types of users are defined by the .NET Simplemembership webpages_Roles and webpages_UsersInRoles tables.
So Far:
I have a UserProfile table in my database which has 25 columns. I have a corresponding domain model of the same name which is accessed from my UsersContext() EF.
The drop down menu only needs to list the User's FirstName, LastName and UserId so instead of working with the complete domain model, I created the following ViewModel:
namespace MyModels.Models.ViewModels
{
public class AdminsAndAgentsListVM
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int UserId { get; set; }
}
}
I then added the following to my Account controller (notice I'm not working with partial view yet):
public ActionResult AdminsAndAgentsList()
{
UsersContext _db = new UsersContext(); //provides me access to UserProfiles data
var admins = Roles.GetUsersInRole("Admin"); //gets users with this role
var viewModel = _db.UserProfiles
.Where(x => admins.Contains(x.UserName)); //Selects users who match UserName list
return View(viewModel);
}
I then scaffold a list view and base it on the strongly typed ViewModel:
#model IEnumerable<MyModels.Models.ViewModels.AdminsAndAgentsListVM>
#{
ViewBag.Title = "AdminsAndAgentsList";
}
<h2>AdminsAndAgentsList</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.FirstName)
</th>
<th>
#Html.DisplayNameFor(model => model.LastName)
</th>
<th>
#Html.DisplayNameFor(model => model.UserId)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.UserId)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
</tr>
}
</table>
I do a successful build and when I run the web page I get the following error:
The model item passed into the dictionary is of type'System.Data.Entity.Infrastructure.DbQuery1[My.Models.UserProfile]',
but this dictionary requires a model item of type
'System.Collections.Generic.IEnumerable1[My.Models.ViewModels.AdminsAndAgentsListVM]'.
If I recreate the view but strongly type it agains the UserProfile, it works fine. So how to re work this so I can strongly type against my ViewModel instead? Please provide examples if possible. I am new to C# and MVC and really benefit from the seeing the code first hand. Much appreciate the help!
EDIT -----------------------------
Here is the object for the UserProfile:
public class UsersContext : DbContext
{
public UsersContext()
: base("DefaultConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
}
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
[Required]
[ReadOnly(true)]
[DisplayName("SubscriberID")]
public int? SubscriberId { get; set; } //Foreign key
[StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.")]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.")]
[Display(Name = "Last Name")]
public string LastName { get; set; }
//public DateTime DOB { get; set; }
[DataType(DataType.Date)]
public DateTime? DOB { get; set; } //This allows null
public bool? Gender { get; set; }
[Required]
[MaxLength(250)]
[EmailAddress]
public string Email { get; set; }
[MaxLength(250)]
[EmailAddress]
[NotEqualTo("Email", ErrorMessage = "Alt Email and Email cannot be the same.")]
public string AltEmail { get; set; }
[MaxLength(250)]
[EmailAddress]
public string FormEmail { get; set; }
public Address Address { get; set; }
[MaxLength(20)]
public string Telephone { get; set; }
[MaxLength(20)]
public string Mobile { get; set; }
[Required]
[DataType(DataType.Date)]
public DateTime DateAdded { get; set; }
[DataType(DataType.DateTime)]
public DateTime? LastLoginDate { get; set; }
public bool? OffersOptIn { get; set; } //any offers we may have with us or partners
public bool? NewsOptIn { get; set; } //newsletter
public bool? SubscriptionOptIn { get; set; } //account, technical, renewal notices, pp invoices, pp receipts
public bool? OrderOptIn { get; set; } //orders - workflow notices
[DataType(DataType.DateTime)]
public DateTime? LastUpdatedAccountDate { get; set; } //Last time user updated contact info
}
Try this. It will cast your query into your view model.
var viewModel = _db.UserProfiles
.Where(x => admins.Contains(x.UserName))
.Select(x => new AdminsAndAgentsListVM {
FirstName = x.FirstName,
LastName = x.LastName,
UserId = x.UserId});
You're passing the view your query, not your model.
Execute the query as you have it
var query = _db.UserProfiles
.Where(x => admins.Contains(x.UserName));
Then instantiate and populate your view model
var viewModels = new List<AdminsAndAgentsListVM>();
foreach (var item in query)
{
var viewModel = new AdminsAndAgentsListVM();
viewodel.FirstName = item.FirstName;
viewodel.LastName = item.LastName;
viewodel.UserId = item.UserId;
viewModels.Add(viewModel);
}
return View(viewModels);
This assumes, of course, that a UserProfile and AdminsAndAgentsListVM have matching properties.
Change your return line to:
return View(viewModel.AsEnumerable());
You aren't selecting your ViewModel. You need to do a Select(x => new AdminsAndAgentsListVM on your query. I would also do ToList() on there.