Passing object to view error - c#

I am getting this error when trying to pass my object to the view. I am new to MVC so please forgive me.
The model item passed into the dictionary is of type 'System.Collections.Generic.List1[<>f__AnonymousType13[System.Int32,System.String,System.Nullable1[System.DateTime]]]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable1[MvcApplication1.Models.storageProperty]'
I am trying to pass a list for a table that will show objects from the storageProperty table with the last date (if there is one) from the expenses table. Most properties have had at least one expense audit, some have had many, and others have had none.
Here is the code from the controller:
var viewModel = db.storageProperties.Select(s => new
{
s.storagePropertyId,
s.BuildName,
latestExpenseSurvey = (DateTime?)s.expenses.Max(e => e.expenseDate)
}).ToList();
return View(viewModel);
}
and the #model statement in the view calls for a storageproperty object. I am using mvc3 with the entity framework. It appears obvious that I cannot pass this list object in place of the storageproperty object, but I can't figure out what to do instead, how should I do this?
Thanks in advance.

Never pass anonymous objects to views. You should always pass view models.
So as always in an ASP.NET MVC application you start by defining a view model which will reflect the requirements of your view:
public class MyViewModel
{
public int StoragePropertyId { get; set; }
public string BuildName { get; set; }
public DateTime? latestExpenseSurvey { get; set; }
}
Then in your controller return an IEnumerable<MyViewModel>:
public ActionResult Index()
{
var viewModel = db.storageProperties.Select(s => new MyViewModel
{
StoragePropertyId = s.storagePropertyId,
BuildName = s.BuildName,
LatestExpenseSurvey = (DateTime?)s.expenses.Max(e => e.expenseDate)
}).ToList();
return View(viewModel);
}
and finally strongly type your view to a collection of this view model:
#model IEnumerable<MyViewModel>
<div>
#Html.EditorForModel()
</div>

Your Linq query projects to an anonymous type. You need to create a named type for this projection in order to refer to it from the view.

Related

Passing model data to view in MVC 5

I am darned new to the world of MVC 5 .NET... I am trying to get my head around the Tree Control from Ignite UI.
I need to retrieve my data from my model and pass it to my view... However, I keep getting the following error:
The model item passed into the dictionary is of type 'System.Data.Entity.Infrastructure.DbQuery1[System.String]', but this dictionary requires a model item of type 'System.Linq.IQueryable1[DataViewer.Models.Viewer]'.
Here is my model:
namespace DataViewer.Models
{
[Table("dbo.table")]
public class Viewer
{
[Key, Column(Order=0)] public long id { get; set; }
public int Revision { get; set; }
public string GeoPSRType { get; set; }
public string GeoName { get; set; }
public string L2Name { get; set; }
public string L3Name { get; set; }
}
}
etc.
And my Controller:
namespace DataViewer.Controllers
{
public class ViewerController : Controller
{
private ViewerDBContext db = new ViewerDBContext();
public ActionResult Index()
{
var result = db.Items.Select(i => i.GeoName).Distinct().OrderBy(n => n);
return View(result);
}
}
}
And my view:
#model IQueryable<DataViewer.Models.Viewer>
#using Infragistics.Web.Mvc
#(Html.Infragistics().Tree()
.DataSource(Model)
.Bindings(b =>
b.TextKey("GeoName")
.PrimaryKey("ID")
.ValueKey("ID")
.ChildDataProperty("L2PSRType")
)
)
.DataSource(Model)
.LoadOnDemand(true)
.DataSourceUrl(Url.Action("tree-data-on-demand"))
.DataBind()
.Render()
)
I figured the issue was that I should be passing a strongly typed return-type by using
IQueryable<Viewer> result =
db.Items.Select(i => i.GeoName).Distinct().OrderBy(n => n);
but that throws a different error:
InvalidOperationException: The model item passed into the dictionary is of type
'System.Data.Entity.Infrastructure.DbQuery`1[System.String]',
but this dictionary requires a model item of type
'System.Linq.IQueryable<DataViewer.Models.Viewer>.'
An explicit conversion exists, are you missing a cast?
Is this relating to the fact that I'm pretty rusty on strongly typed syntax, or am I just being a total maroon (or is it a combination)?
P.S. Also, I have no doubt that the Infragistics().Tree() portion of the view is not correct, I am really more concerned about getting my data to my view (at this point). I just wanted to include all code I had...
You're passing the wrong type to your view. Look at the type of model the view expects:
#model IQueryable<DataViewer.Models.Viewer>
A queryable collection of Viewer objects. But look at what you're giving it:
db.Items.Select(i => i.GeoName).Distinct().OrderBy(n => n);
A collection of GeoName properties. Is GeoName by any chance a string? (The error implies that it is.)
If your model is expecting a collection of objects, you need to give it such a collection. You can't just give it some strings and expect it to convert those strings into objects.
The problem is the view is expecting different data than you're providing it with your controller.
Inside your view:
#model IQueryable<DataViewer.Models.Viewer>
means the view is expecting an IQueryable<> collection of Viewer's, but inside your controller:
// GET: /Viewer/
public ActionResult Index()
{
var result = db.Items.Select(i => i.GeoName).Distinct().OrderBy(n => n);
return View(result);
}
You are passing a collection of strings.
You need to either return Viewer's, or change the model of the view.
Change your Action Result to this...
public ActionResult Index()
{
// var result = db.Items.Select(i => i.GeoName).Distinct().OrderBy(n => n);
Viewer model = new Viewer();
model = (from x in db.Items
select new Viewer
{
GeoPSRType = x.FieldName
}).Distinct().FirstOrDefault().OrderBy(x => x.SomeField);
return View(model);
}
There's probably some syntax errors in that query but this gives you a general understanding of what you need to pass into the View

MVC 4 how pass data correctly from controller to view

I currently have a controller with a LINQ statement that i am passing data from to my view. I am trying to find a more efficient and better coding method to do this.
My home controller statement is as follows.
Var Melt
Furnace1 =
(from item in db.tbl_dppITHr
where item.ProductionHour >= StartShift && item.ProductionHour <= EndDate
select item).Sum(x => x.Furnace1Total),
ViewData["Furnace1Total"] = Melt.Furnace1;
In my view i then reference the ViewData To show this. Using
#model dynamic
Now i have quite alot of linq statements inside the Index method. And for each one i am doing the ViewData[]
I am hoping that someone can show how i pass more than one var from a controller across to a view without the ViewData or ViewBag methods. And how i would get access to this within my view.
You should create a ViewModel with all of your data needed and then pass that down to the view.
public class ViewModel
{
public List<int> Melt1 { get; set; }
public void LoadMeltProperties()
{
if (Melt1 == null)
{
Melt1 = new List<int>();
}
Melt1 = (from item in db.tbl_dppITHr
where item.ProductionHour >= StartShift && item.ProductionHour <= EndDate
select item).Sum(x => x.Furnace1Total).ToList();
}
public ViewModel Load()
{
LoadMeltProperties();
return this;
}
}
public ActionResult YourControllerAction()
{
var vm = new ViewModel().Load();
return View("ViewName", vm);
}
Then in your View you can use a strongly typed model rather than dynamic
#model ViewModel
You can then iterate over your ViewModel properties via:
foreach(var melt in Model.Melt1) {
// do what you require
}
IMHO, you should create a ViewModel an pass data using it.
Create a class
public class MyViewModel
{
public <MeltFurnace1Type> MeltFurnace1{get;set;}
}
In Action Method
public ActionResult Action()
{
MyViewModel vm = new MyViewModel();
vm.MeltFurnace1 = something;
return View("YourViewName", vm);
}
In View
#model MyViewModel
//You can access your property using
Model.MeltFurnace1
If you need to pass data actually from the controller and its data is depend on internal state or input controller parameters or has other properties of "business data" you should use Model part from MVC pattern:
Model objects are the parts of the application that implement the
logic for the application's data domain. Often, model objects retrieve
and store model state in a database. For example, a Product object
might retrieve information from a database, operate on it, and then
write updated information back to a Products table in a SQL Server
database.
You can see details here or look to the Models and Validation in ASP.NET MVC part of Microsoft tutorial.
Add model class:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string City { get; set; }
}
Pass model object to the view:
public ActionResult Index()
{
var model = GetModel();
return View(model);
}
Add strongly typed View via define model type:
#model Person
Use Model variable in your view:
#Model.City
Use models instead
var Melt
Furnace1 =
(from item in db.tbl_dppITHr
where item.ProductionHour >= StartShift && item.ProductionHour <= EndDate
select item).Sum(x => x.Furnace1Total),
return View("SomeVIew",MeltFurnace1)
In view#model "TypeOfMeltFurnace1"
You can reference model in view by property Model
If someone is still looking for options…
You also can pass object from Controller to View, if you don’t use any particular Model for the View. To pass just a single (or maybe few) parameter from the Controller to the View, you can do it inside View() Method.
In the Controller:
public async Task<IActionResult> Update(int id)
{
return View(new { Id = id });
}
Then in the View you can access your parameter like this (assuming you don’t use any other Model inside your View):
<div>
#Html.ActionLink("Link name", "ControllerMethod", "ControllerName", new { id = (int)Model.Id })
</div>
Otherwise, like already mentioned, pass your model inside View() Method.

Which model I have to pass to view?

The goal
Work with a model in my view.
The problem
I'm getting the follow exception:
The model item passed into the dictionary is of type 'System.Linq.Enumerable+WhereSelectListIterator2[MyApp.Models.Data.bm_product_categories,<>f__AnonymousType31[System.String]]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[MyApp.Models.Data.bm_product_categories]'.
Details
I'm using:
C#.Net
Razor Engine
MVC 4
Visual Studio 2012
My partial view (_CategoriesList):
#model IEnumerable<BluMercados.Models.Data.bm_product_categories>
<h1>Testing</h1>
My controller (CategoriesController) and his method:
public ActionResult Render()
{
var sluggifiedProjection =
db.bm_product_categories
.ToList()
.Select(category => new
{
CategoryNameSlugged = category.Category_Name.GenerateSlug()
});
return PartialView("_CategoriesList", sluggifiedProjection);
}
The question
How can I fix this problem? I really do not know what is the model that I have to pass from controller to view.
you are passing an anonymous type as part of the model. While you can do this with the dynamic keyword, you are probably better off making a ViewModel.
Something like
public class CategoryViewModel
{
public WhatEverTypeThisIs NameSlugged { get; set; }
}
then
public ActionResult Render()
{
var sluggifiedProjection =
db.bm_product_categories
.ToList()
.Select(category => new CategoryViewModel
{
NameSlugged = category.Category_Name.GenerateSlug()
});
return PartialView("_CategoriesList", sluggifiedProjection);
}
and the model will be something like
#model IEnumerable<BluMercados.ViewModels.CategoryViewModel>
depending what namespace you put it in
The problem is caused by the select where you currently create instances of an anonymous type with a single property CategoryNameSlugged. You should make sure that your select operation does not change the type of the enumerable. This might work out if the property can be set:
.Select(category =>
{
category.CategoryNameSlugged = category.Category_Name.GenerateSlug();
return category;
});

how to Bind dropdownList using Entity Framework in MVC 3

i want to show a dropdownList on a page using Entity Framework in my MVC app, but i am just stuck here to do this using using HTML Helper. so if anyone having knowledge of entity framework, help me...
my dataContext partial class is Entities, in which an entity named MemberInfo have some fields including MemberID & MemberName, so my dropdownList should show the field MemberName & behind this the value should be MemberID,
the code i tried yet--->
#Html.DropDownListFor(Model => Model.MemberID, MemberInfo)
in controller i am returning the Model--->
var MemberNameList = FinanceDBContext.MemberInfoes.Select(x => new { x.MemberID, x.Name });
return View(MemberNameList);
but its not working (errors).
You need to pass in all of your objects as the "model". Best practice is to use a ViewModel which will contain the list of data and a property to store the selected item.
ViewModel
public class MyViewModel
{
// The drop-down list and variable to get selection
public List<Member> Members { get; set; }
public int SelectedMemberId { get; set; }
}
Controller
[HttpGet]
public ActionResult Index()
{
var viewModel = new MyViewModel();
viewModel.Members = FinanceDBContext.MemberInfoes.ToList();
return View(viewModel);
}
[HttpPost]
public ActionResult Index(MyViewModel viewModel)
{
string debug = string.Format("You selected member: {0}", viewModel.SelectedMemberId);
return View(viewModel);
}
Finally, in your view (these lines need to be inside a BeginForm { ... } and ensure your View is strongly typed to MyViewModel
#Html.DropDownList("SelectedMemberId", new SelectList(Model.Members, "MemberID", "Name"))
<input type="submit" value="Save etc..." />
In this example you could put a break-point on the HttpPost action and check the debug string to check the correct Member is returned and proceed as required.

Sending IEnumerable to a view that already contains a model

This is the view:
#model tgpwebged.Models.sistema_DocType
...
this model is an entity used with textBoxFor and others html helpers
This is the controller.
public ActionResult AdminSettingAddTipo()
{
IEnumerable<string> indices;
using (tgpwebgedEntities context = new tgpwebgedEntities())
{
var obj = from u in context.sistema_Indexes select u.idName;
indices = obj.ToList();
}
return PartialView(indices);
}
I have all I need here, I am using a model to create with the view so I am not allowed to send ´indices´ as a model because it´s not allowed to have 2 models in one view.
I don´t want to use ´Tupe´ now a parent view. I just want to know how is the best way to send my IEnumerable to the view.
I was thinking of ViewBag for the last option but I am avoiding ViewBag.
thanks
ViewBag is not a good choice. Create ViewModel using your list and your current Model:
public class YourViewModel
{
public sistema_DocType Type { get; set; }
public IEnumerable<string> Indices {get;set;}
}
Hope,it will help.
If you don't want to use ViewBag for whatever reason, you could create a Model specifically for the view that contains the info from the old model and the new indices you want. This is a common pattern in MVC development. You can even have the ViewModel be a Decorator for your current Model.
http://geekswithblogs.net/michelotti/archive/2009/10/25/asp.net-mvc-view-model-patterns.aspx
Use strongly defined where you can, apply this to a model and send that model:
Model
public class MyModel{
public List<sistema_Indexes> indecies {get;set;}
}
Controller
MyModel model = new MyModel();
model.indecies = context.sistema_Indexes.Select(u=> u.idName).ToList();

Categories