I'm working on a basic application.
This is the main controller:
public ActionResult Index()
{
var all = _context.mainz.ToList();
var vm = new mainViewModel()
{
main_lst = all
};
return View(vm);
}
public ActionResult Details()
{
var dtl = _context.mainz.ToList();
var vm = new mainViewModel()
{
main_lst = dtl
};
return View(vm);
}
public ActionResult count()
{
var ct = (from i in _context.mainz
where i.event_title != null
select i).ToList();
var vm = new countVm()
{
count = ct
};
return View(vm);
}
In this controller Index and Details Methods are connected to two different razor views as follows:
This is the razor view for Index
#model testtt.ViewModel.mainViewModel
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<ul>
#foreach (var item in Model.main_lst)
{
<li>#item.event_title</li>
}
</ul>
This is the razor view for Details
#model testtt.ViewModel.mainViewModel
#{
ViewBag.Title = "Details";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<ul>
#foreach (var item in Model.main_lst)
{
<li>#item.event_description</li>
}
</ul>
This is the mainViewModel
namespace testtt.ViewModel
{
public class mainViewModel
{
public List<main> main_lst { get; set; }
public mainViewModel()
{
main_lst = new List<main>();
}
}
}
Now in the main controller above, if you have noticed i have a third method as count which is connected to a partial view as follows:
#model testtt.ViewModel.countVm
<p>count is #Model.count.Count()</p>
And the countVm or (count view model) is as follows:
namespace testtt.ViewModel
{
public class countVm
{
public List<main> count { get; set; }
public countVm()
{
count = new List<main>();
}
}
}
Everything is working fine till this moment,
Now as per application requirement i have to add this count partial view to all other razor views as follows:
#Html.Partial("count")
But when i add it into Index or Details razor views it generates an error as:
The model item passed into the dictionary is of type 'testtt.ViewModel.mainViewModel', but this dictionary requires a model item of type 'testtt.ViewModel.countVm'.
Now lets say this count method has some identical data that has to be passed to all other razor views but not separately, because separately passing will be time consuming and suppose tomorrow due to any reason if the logic is updated then i have to go to each and every single method individually and have to update them accordingly, which is not possible if we are assuming more than 100 methods.
So in short, i am looking for a way to retrieve data from two view models in a single razor view?
Use ViewBag or ViewData to pass any kind of information when you are bounded to one Model.
ViewBag is dynamic : #ViewBag. - just fill data in controller and you will have it in view.
ViewData - is a dictionary and use is ViewData["any_name"]
Of course appropriate casting is required in a view.
If you want to store global variable accessed to all views then it is on application level :
Application["Counter"] = 1234;
Also you can pass model to partial :
#Html.Partial("count", Model)
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
I have an action controller that returns a partial view with a query. In this controller I have a viewbag with another query that I want to pass to the partial view so I can use it in a foreach.
Here is my code:
public ActionResult GetQuizResults(string ProfileResult, short occupationID)
var query = from o in db.Occupations
where o.Profile.Equals(ProfileResult, StringComparison.InvariantCulture)
select new QuestionnaireViewModel
{
OccupationID = o.OccupationID,
OccupationName = o.OccupationName,
OccupationDescription = o.OccupationDescription
};
QuestionnaireViewModel occDetails = new QuestionnaireViewModel();
ViewBag.OccDetails = occDetails.GetOccupationDetails(occupationID);
return PartialView("_QuizResults", query.ToList());
}
How can I pass ViewBag.OccDetails to the _QuizResults partial view?
In my partial view I have:
#model IEnumerable<Proj.Models.QuestionnaireViewModel>
#foreach (var item in ViewBag.OccDetails)
{
#item.OccupationDescriptionOc
}
But I get the error: "Object reference not set to an instance of an object"
You do not need to send ViewBag, everything is already done for you just use this way...
For example:
#foreach (var item in (IEnumerable<OccupationDetails>)ViewBag.OccDetails)
{
}
What does your _QuizResults partial view look like? You should be able to access it directly in the view using:
#ViewBag.OccDetails
I have to pass a model object to my create view , so that on submit click this model object gets updated.
But at the same time iam using a list of data in its main Layout for rendering a dynamic menu.
Both use the same model class. But for one i give as
#model IEnumerable<DynaPortalMVC.Models.Page>
and in the create view i give as
#model DynaPortalMVC.Models.Page
In Controller:-
public ActionResult Create()
{
return View();
}
But this gives me an error in _Layout.cshtml, hence the above actionresult is not even executed.
Exception Details: System.ArgumentNullException: Value cannot be null.Parameter name: source
So i think i should pass the Ienumerable object to create view and then convert it there to simple model object, so that it can be updated. Please advice on this.
It's questionable whether you should have #model directive in your Layout. In my opinion you should render your dynamic menu by using a partial view and an action in your controller invoked from Layout by calling HtmlHelper.Action method, something like this:
Partial view for the menu (file named _Menu.cshtml):
#model IEnumerable<DynaPortalMVC.Models.Page>
<ul>
#foreach (var page in Model)
{
<li>#page.Name</li>
}
</ul>
Action named _Menu in your Home controller (or any other):
public ActionResult _Menu()
{
IEnumerable<DynaPortalMVC.Models.Page> model = new List<DynaPortalMVC.Models.Page>
{
new DynaPortalMVC.Models.Page { Name = "Page1" },
new DynaPortalMVC.Models.Page { Name = "Page2" },
new DynaPortalMVC.Models.Page { Name = "Page3" },
new DynaPortalMVC.Models.Page { Name = "Page4" },
};
return PartialView("_Menu", model);
}
This line of code in your Layout to render a menu:
#Html.Action("_Menu", "Home")
I am working on MVC-3. I am facing the following exception on my view :
cannot perform runtime binding on a null reference
Model class
public class HomeModel
{
public IEnumerable<Html> Template { get; set; }
}
View Code
#model Project.Models.HomeModel
#{
ViewBag.Title = "Home Page";
int i = 0;
}
<div class="container">
#foreach (var e in Model.Template) //getting exception on this foreach loop
{
//loop content
}
</div>
Controller
public ActionResult Index()
{
HomeModel model = new HomeModel();
model.Template = db.Templates();
return View(model);
}
My view is strongly typed to HomeModel model class. Can anyone please help me to solve this out?
This is due to the deferred execution of LINQ. The results of Model.Template are not calculated until you try to access them and in this case db.Template is out of scope from view.
You can do it by using ToList() to ToArray() and ToDictionary() with db.Templates.
Your Controller's code should look like:
public ActionResult Index()
{
HomeModel model = new HomeModel();
model.Template = db.Templates.ToList();
return View(model);
}