Pass Collection of Object from Controller to View Asp.Net MVC - c#

Whenever i m passing data from Controller to View this error is showing
Server Error in '/' Application.
The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[<>f__AnonymousType1`6[System.String,System.String,System.Nullable`1[System.DateTime],System.Nullable`1[System.DateTime],System.String,System.String]]', but this dictionary requires a model item of type 'System.Collections.Generic.IList`1[CaliberCoaching.Models.CareerInformation]'.
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.List`1[<>f__AnonymousType1`6[System.String,System.String,System.Nullable`1[System.DateTime],System.Nullable`1[System.DateTime],System.String,System.String]]', but this dictionary requires a model item of type 'System.Collections.Generic.IList`1[CaliberCoaching.Models.CareerInformation]'.
This is My Controller Code
public ActionResult JobList()
{
CaliberCoachingContext objCaliberCoachingContext = new CaliberCoachingContext();
var lstCareerInformation = (from job in objCaliberCoachingContext.CareerInformations
select new { job.NameOfPost, job.PostName, job.StartDate, job.LastDate, job.Eligibility, job.NoOfVacancies }).ToList();
return View(lstCareerInformation);
}
and here is my view
#model IEnumerable<CaliberCoaching.Models.CareerInformation>
#{
ViewBag.Title = "JobList";
Layout = "~/Views/Shared/_CommonLayout.cshtml";
}
#foreach (var item in Model)
{
<div class="single-item-wrapper">
<div class="courses-content-wrapper">
<h3 class="title-default-left-bold">#item.NameOfPost</h3>
</div>
</div>
}
Please Give me the solution for this Problem.

The exception is self explanatory! Your razor view is strongly typed to a collection of CareerInformation objects, but from your action method, you are passing a different type to the view!
In your action method, the variable lstCareerInformation is not a collection of CareerInformation objects, but a collection of anonymous objects. This is happening because your LINQ expression is doing a projection to an annonymous object.
select new { job.NameOfPost, job.PostName, job.StartDate,
job.LastDate, job.Eligibility, job.NoOfVacancies }
select new will create an anonymous object
To fix the error, you should return a collection of CareerInformation objects. Just remove the projection part from your LINQ expression.
public ActionResult JobList()
{
var db = new CaliberCoachingContext();
var careerInformationList = db.CareerInformations.ToList();
return View(careerInformationList);
}
EDIT : As per the comment
i have used anonymous object because i wants to select particular
columns instead of all the columns from CareerInformation properties.
Then you should be using a view model. Create a viewmodel class with properties needed in your view.
public class JobVm
{
public string PostName { set;get;}
public Eligibility { set;get;}
public DateTime StartDate { set;get;}
// Add other properties needed by the view
}
Now in your action method, project create view model objects from your entity object collection using the Select method.
public ActionResult JobList()
{
var db = new CaliberCoachingContext();
var careerInformationList = db.CareerInformations
.Select(a=> new JobVm { PostName = a.PostName,
StartDate = a.StartDate,
Eligibility = a.Eligibility })
.ToList();
return View(careerInformationList);
}
Here careerInformationList is a list of JobVm objects and that is what we are passing to the View. So make sure your view is strongly typed to a collection of the JobVm objects.
#model List<JobVm>
<h2>Jobs</h2>
#foreach(var job in Model)
{
<div>#job.PostName</div>
<p>#job.Eligibility</p>
}

Related

MVC: The model item passed into the dictionary is of type 'X', but this dictionary requires a model item of type 'Y' [duplicate]

This question and community wiki answer has been added to assist in closing out numerous unanswered questions as discussed in this meta post.
I have some code and when it executes, it throws an exception saying:
The model item passed into the dictionary is of type Bar but this dictionary requires a model item of type Foo
What does this mean, and how do I fix it?
The error means that you're navigating to a view whose model is declared as typeof Foo (by using #model Foo), but you actually passed it a model which is typeof Bar (note the term dictionary is used because a model is passed to the view via a ViewDataDictionary).
The error can be caused by
Passing the wrong model from a controller method to a view (or partial view)
Common examples include using a query that creates an anonymous object (or collection of anonymous objects) and passing it to the view
var model = db.Foos.Select(x => new
{
ID = x.ID,
Name = x.Name
};
return View(model); // passes an anonymous object to a view declared with #model Foo
or passing a collection of objects to a view that expect a single object
var model = db.Foos.Where(x => x.ID == id);
return View(model); // passes IEnumerable<Foo> to a view declared with #model Foo
The error can be easily identified at compile time by explicitly declaring the model type in the controller to match the model in the view rather than using var.
Passing the wrong model from a view to a partial view
Given the following model
public class Foo
{
public Bar MyBar { get; set; }
}
and a main view declared with #model Foo and a partial view declared with #model Bar, then
Foo model = db.Foos.Where(x => x.ID == id).Include(x => x.Bar).FirstOrDefault();
return View(model);
will return the correct model to the main view. However the exception will be thrown if the view includes
#Html.Partial("_Bar") // or #{ Html.RenderPartial("_Bar"); }
By default, the model passed to the partial view is the model declared in the main view and you need to use
#Html.Partial("_Bar", Model.MyBar) // or #{ Html.RenderPartial("_Bar", Model.MyBar); }
to pass the instance of Bar to the partial view. Note also that if the value of MyBar is null (has not been initialized), then by default Foo will be passed to the partial, in which case, it needs to be
#Html.Partial("_Bar", new Bar())
Declaring a model in a layout
If a layout file includes a model declaration, then all views that use that layout must declare the same model, or a model that derives from that model.
If you want to include the html for a separate model in a Layout, then in the Layout, use #Html.Action(...) to call a [ChildActionOnly] method initializes that model and returns a partial view for it.
This question already has a great answer, but I ran into the same error, in a different scenario: displaying a List in an EditorTemplate.
I have a model like this:
public class Foo
{
public string FooName { get; set; }
public List<Bar> Bars { get; set; }
}
public class Bar
{
public string BarName { get; set; }
}
And this is my main view:
#model Foo
#Html.TextBoxFor(m => m.Name, new { #class = "form-control" })
#Html.EditorFor(m => m.Bars)
And this is my Bar EditorTemplate (Bar.cshtml)
#model List<Bar>
<div class="some-style">
#foreach (var item in Model)
{
<label>#item.BarName</label>
}
</div>
And I got this error:
The model item passed into the dictionary is of type 'Bar', but this
dictionary requires a model item of type
'System.Collections.Generic.List`1[Bar]
The reason for this error is that EditorFor already iterates the List for you, so if you pass a collection to it, it would display the editor template once for each item in the collection.
This is how I fixed this problem:
Brought the styles outside of the editor template, and into the main view:
#model Foo
#Html.TextBoxFor(m => m.Name, new { #class = "form-control" })
<div class="some-style">
#Html.EditorFor(m => m.Bars)
</div>
And changed the EditorTemplate (Bar.cshtml) to this:
#model Bar
<label>#Model.BarName</label>
Observe if the view has the model required:
View
#model IEnumerable<WFAccess.Models.ViewModels.SiteViewModel>
<div class="row">
<table class="table table-striped table-hover table-width-custom">
<thead>
<tr>
....
Controller
[HttpGet]
public ActionResult ListItems()
{
SiteStore site = new SiteStore();
site.GetSites();
IEnumerable<SiteViewModel> sites =
site.SitesList.Select(s => new SiteViewModel
{
Id = s.Id,
Type = s.Type
});
return PartialView("_ListItems", sites);
}
In my case I Use a partial view but runs in normal views
Consider the partial map.cshtml at Partials/Map.cshtml. This can be called from the Page where the partial is to be rendered, simply by using the <partial> tag:
<partial name="Partials/Map" model="new Pages.Partials.MapModel()" />
This is one of the easiest methods I encountered (although I am using razor pages, I am sure same is for MVC too)
First you need to return an IEnumerable version of your model to the list view.
#model IEnumerable<IdentityManager.Models.MerchantDetail>
Second, you need to return a list from the database. I am doing it via SQL Server, so this is code I got working.
public IActionResult Merchant_Boarding_List()
List<MerchantDetail> merchList = new List<MerchantDetail>();
var model = new MerchantDetail();
try
{
using (var con = new SqlConnection(Common.DB_CONNECTION_STRING_BOARDING))
{
con.Open();
using (var command = new SqlCommand("select * from MerchantDetail md where md.UserGUID = '" + UserGUID + "'", con))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
model.biz_dbaBusinessName = reader["biz_dbaBusinessName"].ToString();
merchList.Add(model);
}
}
}
}
}
catch (Exception ex)
{
}
return View(merchList);
Passing the model value that is populated from a controller method to a view
public async Task<IActionResult> Index()
{
//Getting Data from Database
var model= await _context.GetData();
//Selecting Populated Data from the Model and passing to view
return View(model.Value);
}
one more thing.
if your view is a partial/sub page and the model for that partial view is null for some reason (e.g no data) you will get this error. Just need to handle the null partial view model

The model item passed into the dictionary is of type 'x' but this dictionary requires a model item of type PagedList.IPagedList [duplicate]

This question and community wiki answer has been added to assist in closing out numerous unanswered questions as discussed in this meta post.
I have some code and when it executes, it throws an exception saying:
The model item passed into the dictionary is of type Bar but this dictionary requires a model item of type Foo
What does this mean, and how do I fix it?
The error means that you're navigating to a view whose model is declared as typeof Foo (by using #model Foo), but you actually passed it a model which is typeof Bar (note the term dictionary is used because a model is passed to the view via a ViewDataDictionary).
The error can be caused by
Passing the wrong model from a controller method to a view (or partial view)
Common examples include using a query that creates an anonymous object (or collection of anonymous objects) and passing it to the view
var model = db.Foos.Select(x => new
{
ID = x.ID,
Name = x.Name
};
return View(model); // passes an anonymous object to a view declared with #model Foo
or passing a collection of objects to a view that expect a single object
var model = db.Foos.Where(x => x.ID == id);
return View(model); // passes IEnumerable<Foo> to a view declared with #model Foo
The error can be easily identified at compile time by explicitly declaring the model type in the controller to match the model in the view rather than using var.
Passing the wrong model from a view to a partial view
Given the following model
public class Foo
{
public Bar MyBar { get; set; }
}
and a main view declared with #model Foo and a partial view declared with #model Bar, then
Foo model = db.Foos.Where(x => x.ID == id).Include(x => x.Bar).FirstOrDefault();
return View(model);
will return the correct model to the main view. However the exception will be thrown if the view includes
#Html.Partial("_Bar") // or #{ Html.RenderPartial("_Bar"); }
By default, the model passed to the partial view is the model declared in the main view and you need to use
#Html.Partial("_Bar", Model.MyBar) // or #{ Html.RenderPartial("_Bar", Model.MyBar); }
to pass the instance of Bar to the partial view. Note also that if the value of MyBar is null (has not been initialized), then by default Foo will be passed to the partial, in which case, it needs to be
#Html.Partial("_Bar", new Bar())
Declaring a model in a layout
If a layout file includes a model declaration, then all views that use that layout must declare the same model, or a model that derives from that model.
If you want to include the html for a separate model in a Layout, then in the Layout, use #Html.Action(...) to call a [ChildActionOnly] method initializes that model and returns a partial view for it.
This question already has a great answer, but I ran into the same error, in a different scenario: displaying a List in an EditorTemplate.
I have a model like this:
public class Foo
{
public string FooName { get; set; }
public List<Bar> Bars { get; set; }
}
public class Bar
{
public string BarName { get; set; }
}
And this is my main view:
#model Foo
#Html.TextBoxFor(m => m.Name, new { #class = "form-control" })
#Html.EditorFor(m => m.Bars)
And this is my Bar EditorTemplate (Bar.cshtml)
#model List<Bar>
<div class="some-style">
#foreach (var item in Model)
{
<label>#item.BarName</label>
}
</div>
And I got this error:
The model item passed into the dictionary is of type 'Bar', but this
dictionary requires a model item of type
'System.Collections.Generic.List`1[Bar]
The reason for this error is that EditorFor already iterates the List for you, so if you pass a collection to it, it would display the editor template once for each item in the collection.
This is how I fixed this problem:
Brought the styles outside of the editor template, and into the main view:
#model Foo
#Html.TextBoxFor(m => m.Name, new { #class = "form-control" })
<div class="some-style">
#Html.EditorFor(m => m.Bars)
</div>
And changed the EditorTemplate (Bar.cshtml) to this:
#model Bar
<label>#Model.BarName</label>
Observe if the view has the model required:
View
#model IEnumerable<WFAccess.Models.ViewModels.SiteViewModel>
<div class="row">
<table class="table table-striped table-hover table-width-custom">
<thead>
<tr>
....
Controller
[HttpGet]
public ActionResult ListItems()
{
SiteStore site = new SiteStore();
site.GetSites();
IEnumerable<SiteViewModel> sites =
site.SitesList.Select(s => new SiteViewModel
{
Id = s.Id,
Type = s.Type
});
return PartialView("_ListItems", sites);
}
In my case I Use a partial view but runs in normal views
Consider the partial map.cshtml at Partials/Map.cshtml. This can be called from the Page where the partial is to be rendered, simply by using the <partial> tag:
<partial name="Partials/Map" model="new Pages.Partials.MapModel()" />
This is one of the easiest methods I encountered (although I am using razor pages, I am sure same is for MVC too)
First you need to return an IEnumerable version of your model to the list view.
#model IEnumerable<IdentityManager.Models.MerchantDetail>
Second, you need to return a list from the database. I am doing it via SQL Server, so this is code I got working.
public IActionResult Merchant_Boarding_List()
List<MerchantDetail> merchList = new List<MerchantDetail>();
var model = new MerchantDetail();
try
{
using (var con = new SqlConnection(Common.DB_CONNECTION_STRING_BOARDING))
{
con.Open();
using (var command = new SqlCommand("select * from MerchantDetail md where md.UserGUID = '" + UserGUID + "'", con))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
model.biz_dbaBusinessName = reader["biz_dbaBusinessName"].ToString();
merchList.Add(model);
}
}
}
}
}
catch (Exception ex)
{
}
return View(merchList);
Passing the model value that is populated from a controller method to a view
public async Task<IActionResult> Index()
{
//Getting Data from Database
var model= await _context.GetData();
//Selecting Populated Data from the Model and passing to view
return View(model.Value);
}
one more thing.
if your view is a partial/sub page and the model for that partial view is null for some reason (e.g no data) you will get this error. Just need to handle the null partial view model

Causing problems with foreach into my mvc

This is how I have made a previous post as you can see here.
must retrieve the list from the database
I have tried to make my foreach which have been previously described. but it causes problems for not running my foreach in through while making the mistake on it.
Index.cshtml
#foreach (var u in Model)
{
<div class="col-md-6 col-sm-6">
<div class="plan">
<h3>#u.Name<span>$#u.Price</span></h3>
<p>#u.Text</p>
</div>
</div>
}
and undervisningController.cs
// GET: Undervisning
public ActionResult Index()
{
DatabaseClasseDataContext db = new DatabaseClasseDataContext();
var model = db.Packages.ToList();
return View(model);
}
And the top on index.cshtml have i:
#model MentorOrdblind_MVC.Models.Undervisning.Undervisning
Model Undervisning.cs
public class Undervisning
{
public string Name { get; set; }
public decimal Price { get; set; }
public int Hours { get; set; }
public string Text { get; set; }
}
You are passing your view a List<T> but your model is not a type of IEnumerable. So your view is only expecting a single object of the type Undervisning and not a collection.
Use this:
#model IEnumerable<MentorOrdblind_MVC.Models.Undervisning.Undervisning>
Change your model delcaration to:
#model IEnumerable<MentorOrdblind_MVC.Models.Undervisning.Undervisning>
At this moment your model is a single class, not a list of objects
Always keep in mind what is being passed from controller action to view. If you pass only model from the action then use the model reference in the respective view of the action. If you pass List then use IEnumerable model reference in the view.
If you pass list from action then in the view use:
#model IEnumerable<your model> in the top as reference
If you pass model without a list then use:
#model your model
In your case you are passing list so use IEnumerable of your desired model class.
Thanks

mvc cannot call view from controller

I am trying to get started learning MVC. I built the MVC Music Store project that I found on the Microsoft site. http://www.asp.net/mvc/tutorials/mvc-music-store/mvc-music-store-part-1.
I got it working pretty well but I ran into trouble when I tried to modified it. I want to put the data in a separate project. I used Linq to Entities for the data access.
Here is my class to access the data
public class clsUtilities
{
Utilities.MVCMusicStoreEntities db = new Utilities.MVCMusicStoreEntities();
public object GetAlbums(string GenreName)
{
var query = from tags in db.vieAlbumArtists
where tags.GenreName.Equals(GenreName)
select tags;
return query;
}
}
In my Controller my code is
public ActionResult Browse2(string genre)
{
// retrieve Genre and its associated albums from the database
var genreModel = mcloUtilities.GetAlbums(genre);
return View(genreModel);
}
I generate a cshtml file in my view
#model Utilities.vieAlbumArtist
#{
ViewBag.Title = "Browse2";
}
This all compiles ok but when I run it I get:
The model item passed into the dictionary is of type System.Data.Objects.ObjectQuery'1[Utilities.vieAlbumArtist], but this dictionary requires a model item of type Utilities.vieAlbumArtist.
Change
#model Utilities.vieAlbumArtist
to
#model IEnumerable<Utilities.vieAlbumArtist>
You are returning a list of vieAlbumArtist, not just a single instance.
You might also want to change
public object GetAlbums(string GenreName)
to
public IEnumerable<Utilities.vieAlbumArtist> GetAlbums(string GenreName)
Passing objects around is not the best idea.
This is your problem:
public object GetAlbums(string GenreName)
You're returning the data as an object. But the view expects to receive an item of type Utilities.vieAlbumArtist. Either change the GetAlbums() method to return the appropriate type, or make sure you cast it in the controller to the type the view is expecting.
I was able to solve this with the help of the hints you guys gave me.
From clsUtilies
public class clsUtilities
{
Utilities.MVCMusicStoreEntities db = new Utilities.MVCMusicStoreEntities();
public IEnumerable<Utilities.vieAlbumArtist> GetAlbums(string GenreName)
{
IEnumerable<vieAlbumArtist> query = from tags in db.vieAlbumArtists
where tags.GenreName.Equals(GenreName)
select tags;
foreach (var n in query)
{
}
return query;
}
From Controller
public ActionResult Browse2(string genre)
{
// retrieve Genre and its associated albums from the database
var genreModel = mcloUtilities.GetAlbums(genre);
return View(genreModel );
}
From Views
#model IEnumerable< Utilities.vieAlbumArtist>
#{
ViewBag.Title = "Browse Albums";
}
#foreach(var album in Model)
{
<ul>
<a href="#Url.Action("Details", new { id=album.AlbumId})">
<img alt="#album.Title" src="#album.AlbumArtUrl" />
<span>#album.Title ( #album.Name ) </span> </a>
</ul>
}
}
To display a list of albums try this:
<ul>
#foreach(var item in vieAlbumArtist)
{
<li>item.Name</li> //Not sure if you actually have a name property
}
</ul>

Pass multiple objects to view through controller

I am developing an asp.net mvc web app in which I want to send 2 objects to View through Controller now I am sending only one object to view through controller
return View(repository.func(id));
and in view I am getting
<% var data = Model.First %>
But now I am confused how to send 2 objects and how to get it.
An excellent occasion to (learn to) use a ViewModel:
class MyViewModel { ... }
// and in the Action:
var view = new MyViewModel();
view.First = repository.func(id) ;
view.Second = ....;
return View(view);
You can use ViewBag (Personally I don't like this approach) or create class which will hold both values and use it for model for your view
I assume your view is strongly-typed to be of the same type as whatever you're returning from:
repository.func(id)
lets say object 'Foo'
Assuming you are using a strongly-typed view:
#model Foo
You can change this to be:
#model IEnumerable<Foo>
Then, your view will be strongly-typed to a collection (IEnumerable) of Foo
and in your view you can do:
foreach(var foo in Model)
{
//Do stuff
}
Naturally, your repository method will have to return a collection of objects (via something that implements IEnumerable - List<> for example)
Just a slight elaboration of Henk's answer
class MyViewModel {
TMyEntityType1 First { get; set; }
IQueryable<TMyEntityType2> Second { get; set; }
}
And then in the action you collect your 2 sets of data and house it in an instance of MyViewModel
var viewModel = new MyViewModel();
viewModel.First = repository.func(id);
viewModel.Second = repository.containing("?");
return View(viewModel);
An in your view you may want to change it to:
<% var dataFirst = Model.First;
var dataSecond = Model.Second;%>
Where Model is now of type MyViewModel and not the return type of repository.func(id)

Categories

Resources