Error when passing multiple tables from controller to view MVC4 - asp.net-mvc

I tried to pass 2 tables from Controller to view by using ViewModel
I declared:
public class Temp
{
public Models.ORDER_HEADER_INFO ORDER_HEADER_INFO { get; set; }
public Models.ORDER_ROUTING_DETAIL ORDER_ROUTING_DETAIL { get; set; }
}
In controller I write:
public ActionResult DataLoading()
{
using (Models.AllDataEntities et = new Models.AllDataEntities())
{
var Odata = (from ord in et.ORDER_ROUTING_DETAIL join
oh in et.ORDER_HEADER_INFO on ord.ORDER_NO equals oh.ORDER_NO
orderby ord.TARGET_COMPLETION_FLAG,oh.PRODUCT_START_DATE
select new {Order_No = oh.ORDER_NO,ROUTING_NAME = ord.ROUTING_NAME,
PJNO = oh.PJNO,DELIVERY_DESTINATION = oh.DELIVERY_DESTINATION,
}).ToList();
return View(Odata);
}
}
In view:
<table>
#for (int i = 0; i < Model.Count; i++ )
{
<tr>
<td>#Html.DisplayFor(m=>m[i].ORDER_HEADER_INFO.ORDER_NO)</td>
<td>#Html.DisplayFor(m=>m[i].ORDER_HEADER_INFO.PJNO)</td>
<td>#Html.DisplayFor(m=>m[i].ORDER_ROUTING_DETAIL.ROUTING_NAME)</td>
<td>#Html.DisplayFor(m=>m[i].ORDER_HEADER_INFO.DELIVERY_DESTINATION)</td>
</tr>
}
</table>
When i run the code, there is the exception like this:
The model item passed into the dictionary is of type
'System.Collections.Generic.List1[<>f__AnonymousType34[System.String,System.String,System.String,System.String]]',
but this dictionary requires a model item of type
'System.Collections.Generic.List`1[TIS.Models.Temp]'.
When I debug, Data is completely loaded to Odata, but I cannot understand what type of Odata.

You need to have this select statement. Instead of Anonymous Type, Select new Temp() { ... }. Reason is that your View Expects List<temp>, but you are passing list<AnonymousType> from controller.
var Odata = (from ord in et.ORDER_ROUTING_DETAIL join
oh in et.ORDER_HEADER_INFO on ord.ORDER_NO equals oh.ORDER_NO
orderby ord.TARGET_COMPLETION_FLAG,oh.PRODUCT_START_DATE
select new Temp() {ORDER_HEADER_INFO = oh, ORDER_ROUTING_DETAIL = ord }).ToList();
If you dont not want to use all the properties in the entities, then you need to create your DTO with the properties you want to use and map them in the linq query.

Your server side code should instantiate the Temp object while creating the list:
public ActionResult DataLoading()
{
using (Models.AllDataEntities et = new Models.AllDataEntities())
{
var Odata = (from ord in et.ORDER_ROUTING_DETAIL join
oh in et.ORDER_HEADER_INFO on ord.ORDER_NO equals oh.ORDER_NO
orderby ord.TARGET_COMPLETION_FLAG, oh.PRODUCT_START_DATE
select new Temp()
{
ORDER_HEADER_INFO = new ORDER_HEADER_INFO()
{
ROUTING_NAME = ord.ROUTING_NAME
},
ORDER_ROUTING_DETAIL = new ORDER_ROUTING_DETAIL()
{
Order_No = oh.ORDER_NO
}
}).ToList();
return View(Odata);
}
}
Your view can operate on this list like so:
#model IEnumerable<MvcApplication16.Models.Temp>
<table>
#foreach (var item in Model)
{
<tr>
<td>#Html.DisplayFor(item.ORDER_HEADER_INFO.ORDER_NO)</td>
<td>#Html.DisplayFor(item.ORDER_HEADER_INFO.PJNO)</td>
<td>#Html.DisplayFor(item.ORDER_ROUTING_DETAIL.ROUTING_NAME)</td>
<td>#Html.DisplayFor(item.ORDER_HEADER_INFO.DELIVERY_DESTINATION)</td>
</tr>
}
</table>
Note: As in your original Temp object definition, you have mapped entity directly, LINQ will throw error as you mentioned in the comment.
The entity or complex type 'Model.ORDER_HEADER_INFO' cannot be
constructed in a LINQ to Entities query.
You cannot (and should not be able to) project onto a mapped entity. You can, however, project onto an anonymous type or onto a DTO.
I suggest you create you modify your Temp definition and include properties that your want to send to view. That will make it a ViewModel object which is the right approach.
public class Temp
{
public string ORDER_NO { get; set; }
public string ROUTING_NAME { get; set; }
}

Related

How to implement GroupBy using linq in razor view

How can this nested grouping be implemented in razor view?
This is what i have tried
Controller
public ActionResult SeniorityList()
{
var employee = db.Employees.GroupBy(f => f.Facility.FacilityName).ToList();
return View(employee.ToList());
}
However I don't know how to implement the foreach loop in view
Since you want the grouped data, i suggest you create a new class for that
public class GroupedItem
{
public string GroupName { set; get; }
public IEnumerable<Employee> Items { set; get; }
}
Now you can use the GroupBy method on your db.Employees collection and project the results to a collection of GroupedItem class objects.
var grouped = db.Employees
.GroupBy(f => f.Facility.FacilityName,i=>i,
(key,v)=>new GroupedItem { GroupName = key,Items = v})
.ToList();
return View(grouped);
the type of grouped variable will be a list of GroupedItem and we are passing that to the view. So make sure that your view is strongly typed to a collection of GroupedItem class.
#model IEnumerable<GroupedItem>
#foreach (var group in Model)
{
<h3>#group.GroupName</h3>
foreach (var p in group.Items)
{
<p>#p.Name</p>
}
}

display data from multiple tables to mvc view does not work

I have two unrelated tables. I want to display data from them to my view. I tried to add a class to bring the data to it like the following:
public class OrderViewData
{
public List<EventHome> Events { get; set; }
public List<Portfolio> Portfolio{ get; set; }
}
EventHome and Portfolio are my tables's names
then I used LinQ select in my Controller to get my list and send it to the view
like this
ToddlerEntities db=new ToddlerEntities();
public ActionResult Index()
{
OrderViewData orderView = new OrderViewData();
orderView.Events = (from o in db.EventHome select o).ToList();
orderView.Portfolio = (from o in db.Portfolio select o).ToList();
return View(orderView);
}
and in my view I tried to bring my list
#model List<Toddlers.Models.OrderViewData>
and
#foreach (var ev in Model)
{
#Html.DisplayFor(modelItem => ev.Events.EventsImg)
}
but I get the following error
The model item passed into the dictionary is of type 'Toddlers.Models.OrderViewData', but this dictionary requires a model item of type 'System.Collections.Generic.List`1[Toddlers.Models.OrderViewData]
Your passing a single instance of OrderViewData to the view so your view needs to be
#model Toddlers.Models.OrderViewData
and then loop through its collections
#foreach (var ev in Model.Events)
{
#Html.DisplayFor(m => ev.EventsImg)
}
Side note: There is no real need to make the collections List<T> - they could just be IEnumarable<T>

MVC pass viewmodel view with viewmodel containing parent values and child list

My application has multiple areas within one facility. I am trying to pass a single model to the view that contains facility values (facility_id, facility_name), and a list of areas. I currently have the list of areas as a type of the entity model for the table (area_list).
My viewmodel is as follows:
public class AreaView
{
public string facility_name { get; set; }
public int facility_id { get; set; }
public int group_id { get; set; }
public IList<area_list> areas { get; set; }
}
As an aside, I had originally tried setup the list of areas as a separate viewmodel (AreaS) instead of the model area_list, but I had other issues there so went back to directly referencing the for simplicity. I am assuming this would be more appropriate...
My Controller:
public ActionResult List(int id = 0)
{
var model = (from f in areaDB.facility_list
where f.facility_id == id
select new AreaView
{
facility_id = f.facility_id,
facility_name = f.facility_name,
areas = (from a in areaDB.area_list
orderby a.area_name
where a.facility_id == id
select a).ToList()
});
return View(model);
}
My View (abbreviated):
#model SkyeEnergy.Models.AreaView
Facility: #Model.facility_name
#foreach (var item in Model.areas) {
<tr>
<td>
#Html.ActionLink(item.vendor_name,"Details","Area",new {id = item.vendor_id},null)
</td>
</tr>
}
I have tried numerous variations to accomplish what's below, which has given me numerous errors, but the most recent is below:
The model item passed into the dictionary is of type
'System.Data.Entity.Infrastructure.DbQuery`1[MyApp.Models.AreaView]',
but this dictionary requires a model item of type
'MyApp.Models.AreaView'.
I understand that I am not passing the correct type for what the view is expecting, but I cannot seem to figure out:
Is the viewmodel setup correctly in the firstplace (how to mix values and a list of children
How to structure my linq query to get one AreaView object with
all my data
Pass it appropriately (in the correct type) to my
view
I have read about 45 posts on Stackoverflow, but can't seem to piece them together to accomplish what's above. If anyone has a correct solution (or even a direction), I would be very appreciative.
Thanks for any help.
I think you should add FirstOrDefault() at the end of your query to return the AreaView
public ActionResult List(int id = 0)
{
var model = (from f in areaDB.facility_list
where f.facility_id == id
select new AreaView
{
facility_id = f.facility_id,
facility_name = f.facility_name,
areas = (from a in areaDB.area_list
orderby a.area_name
where a.facility_id == id
select a).ToList()
}).FirstOrDefault();
return View(model);
}
I would not combine both object in the same query. I would do
1) Select AreaView where id = xxxx
2) Select Areas where id = xxxx
3) Assign areas to my AreaView
Example
AreaView model = GetAreaView(id);
model.Areas = GetAreas(id);
return View(model);
Also, try the following for your current code
return View(model.FirstOrDefault());

pass an anonymous type to my ASP.NET MVC view

I have a problem, I have the next controller
namespace RolesMVC3.Areas.Administrador.Controllers
{
[Authorize(Roles = "Adminr")]
public class HomeController : Controller
{
private BASEDATOSCJ_2Entities db = new BASEDATOSCJ_2Entities();
public ActionResult Index()
{
string username = User.Identity.Name;
MembershipUser user = Membership.GetUser(username);
Guid key = (Guid)Membership.GetUser().ProviderUserKey;
var Universities = (from u in db.UNIVERSITy
join s in db.CAMPUS_UNIVERSITy on u.IdUniversity equals s.IdUniversity
join c in db.CIUDAD_CAMPUS on s.IdCiudadSede equals c.IdCiudadSede
join co in db.OFFICE on s.Idoffice equals co.Idoffice
join uxc in db.USERxOFFICE on co.Idoffice equals uxc.Idoffice
where uxc.UserId == key
select new { u.Name, namecity = c.Nombre, s.Idoffice}).ToList();
return View(Universities);
}
With this controller I just want send to View u.Name, and s.Idoffice. How I do? (in fact do not know if this controllet is fine), I want to send fields belong to different tables. I want to send the query as a list and present at the View, ViewBag go with it?, How do I pass these data to the view and display with a foreach?.
I use razor
If you change the following line:
select new { u.Name, namecity = c.Nombre, s.Idoffice}
To
select new { Name = u.Name, Idoffice = s.Idoffice }
This only selects the two fields into a list. In your view you can do the following:
#model List<dynamic>
#foreach(dynamic d in Model) {
<p>#d.Name</p>
<p>#d.Idoffice</p>
}
Edit:
You might want to define a ViewModel to contain your data.
public class MyViewModel {
string Name {get;set;}
string Idoffice {get;set;}
}
Now you can change your select statement as follows:
select new MyViewModel { Name = u.Name, Idoffice = s.Idoffice }
And update your Razor file as such:
#model List<MyViewModel>
#foreach(MyViewModel d in Model) {
<p>#d.Name</p>
<p>#d.Idoffice</p>
}
I would use a view model. I have learnt not to expose my domain objects to the view, I rather map my domain object to the view model and return this view model to the view.
Separate you data access logic from your view logic. You can put that whole statement into a repository class and then you just call this method from the controller.
Here is a partial view model, you might have more properties if you need more data to be displayed:
public class UniversityViewModel
{
IEnumerable<University> Universities { get; set; }
}
University class:
public class University
{
public string Name { get; set; }
public string Idoffice { get; set; }
}
In my action method of my controller it would look something like this:
public ActionResult Index(int id)
{
UniversityViewModel viewModel = new UniversityViewModel
{
Universities = universityRepository.GetAll()
};
return View(viewModel);
}
And in my view I would have the following:
<table>
#foreach(University university in Model.Universities)
{
<tr>
<td>Name:</td>
<td>university.Name</td>
</tr>
}
</table>
This is just a basic display of data in the view, you can use 3rd party components to display your data with some features.

Accessing group by fields from Controller to View in MVC 3

How can I write code in View so as to access the groupby fields in linq. Here the data is rendered through a web service.
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Find Member";
var obj = new SearchMemberServiceClient();
List<MemberProxy> members = obj.FindMember("Mason", "Birkes", "", "", "", "").Members;
var sorted = from a in members
orderby a.FirstName ascending
group a by new { a.FormattedFullName, a.PersonId, a.Associations, a.MembershipsProxy[0].MembershipId } into k
select new { formattedname = k.Key.FormattedFullName, id = k.Key.PersonId, assoc = k.Key.Associations, memprox = k.Key.MembershipId };
return View(sorted.ToList());
}
}
You are passing an anonymous object to your view. Anonymous objects are emitted as internal by the compiler. Internal classes can only be used within the same assembly. ASP.NET MVC views are dynamically compiled by the ASP.NET runtime in separate assemblies. This basically means that you cannot access the anonymous types created in your controller actions inside your views. As a consequence this means that you should absolutely never pass anonymous objects to your views. So if you cannot pass anonymous objects, well, pass a named object by creating one. In this case they will be called a view model. A view model is class that you specifically define to meet the requirements of your view.
So what are the requirements of your view is the first question you should ask yourself when designing an ASP.NET MVC application? Well, in this case you seem to need a couple of properties (formattedname, id, assoc and memprox). Great, let's write a view model:
// you probably want to find a more suitable name
public class MyViewModel
{
public int Id { get; set; }
public int MemProx { get; set; }
public string FormattedName { get; set; }
public IEnumerable<Association> Associations { get; set; }
}
and then have your action pass this view model to the view:
public ActionResult Index()
{
var obj = new SearchMemberServiceClient();
var members = obj.FindMember("Mason", "Birkes", "", "", "", "").Members;
IEnumerable<MyViewModel> sorted =
from a in members
orderby a.FirstName ascending
group a by new
{
a.FormattedFullName,
a.PersonId,
a.Associations,
a.MembershipsProxy[0].MembershipId
} into k
select new MyViewModel
{
FormattedName = k.Key.FormattedFullName,
Id = k.Key.PersonId,
Associations = k.Key.Associations,
MemProx = k.Key.MembershipId
};
return View(sorted.ToList());
}
OK, now you can strongly type your view to this view model and present the information that it contains however you want:
#model IEnumerable<MyViewModel>
#foreach (var item in Model)
{
<div>#item.FormattedName</div>
...
}

Resources