This question already has answers here:
The model item passed into the dictionary is of type .. but this dictionary requires a model item of type
(7 answers)
Closed 6 years ago.
It seems like this question has been asked and asnwered a lot on this site, but I still cannot seem to get my problem solved. I'm getting the The model item passed into the dictionary is of type 'X', but this dictionary requires a model item of type 'Y' error, even though I'm pretty sure my code is pointing to the right place and receiving the correct viewModel.
View (Index)
#model EveryNationRandburg.ViewModels.AllUsers
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Church Members</h2>
<p>#Html.ActionLink("New Member", "Register", "Account", null, new { #class = "btn btn-primary" })</p>
<table class="table table-bordered table-hover" id="kerkmembers">
<thead>
<tr>
<th>Member</th>
<th>Email</th>
<th>Contact Number</th>
</tr>
</thead>
<tbody>
#foreach (var member in Model.AlleKerkMembers)
{
<tr>
<td>#Html.ActionLink(#member.UserName, "Edit", "KerkMember", new {id = #member.Id}, null)</td>
<td>#member.Email</td>
<td>#member.PhoneNumber</td>
</tr>
}
</tbody>
</table>
#section scripts
{
<script>
$(document).ready(function (){
$("#kerkmembers").DataTable();
})
</script>
}
ViewModel
public class AllUsers
{
public List<ApplicationUser> AlleKerkMembers = new List<ApplicationUser>();
}
Account Controller
public ActionResult Index()
{
var viewModel = new AllUsers
{
AlleKerkMembers = _context.Users.ToList()
};
return View(viewModel);
}
StackTrace
InvalidOperationException: The model item passed into the dictionary is of type 'EveryNationRandburg.ViewModels.AllUsers', but this dictionary requires a model item of type 'EveryNationRandburg.ViewModels.KonnekGroepViewModel'.
What is slightly different for my problem is that whenever I try to send a viewModel to a view, I always get the error saying it is expecting item of type 'Y' (always the same one, no matter what model I declare at the top of my view)
First thing I'd suggest is to attach a debugger to your code and see values you are handling. With debugger you can see call stack which we can't see here.
Where do you use result for return View(viewModel); ?
You don't have listing for your view's constructor.
What is the type of object your view is expecting?
Should be AllUsers since you are passing AllUsers object to it.
You can try using explicit types instead of var to be sure you are passing right object type. Code would be easier to read too.
Please attach your debugger and try to solve it out that way.
Related
In my controller I do have this endpoint:
async Task<FileResult> DownloadSelection(AssignedDatabaseSelection selection)
And my HTML looks like:
#if (Model.AssignedDatabaseSelections.Any())
{
<table>
#foreach (var selection in Model.AssignedDatabaseSelections)
{
<tr>
<td>#selection.DisplayName</td>
<td width="10%">
#Html.ActionLink(Strings.CsvLabel, "DownloadSelection", "Home", selection, null)
</td>
</tr>
}
</table>
}
Now I wanted to add another parameter to my controller method:
async Task<FileResult> DownloadSelection(AssignedDatabaseSelection selection, DownloadFormat format)
And
#if (Model.AssignedDatabaseSelections.Any())
{
<table>
#foreach (var selection in Model.AssignedDatabaseSelections)
{
<tr>
<td>#selection.DisplayName</td>
<td width="10%">
#Html.ActionLink(Strings.CsvLabel, "DownloadSelection", "Home", new {selection = selection, Format = DownloadFormat.CSV}, null)
</td>
<td width="10%">
#Html.ActionLink(Strings.ExcelLabel, "DownloadSelection", "Home", new { selection = selection, Format = DownloadFormat.CSV }, null)
</td>
</tr>
}
</table>
}
When I make an inspect elements I got this:
Excel
Now, the format is filled, but the selection is always null. What am I missing?
In you first example, the 3rd parameter is a complex object (typeof AssignedDatabaseSelections) and the method will correctly serialize each property of your object to a query string. Note that it only works because your object contains only simple properties.
In the second example, your creating a new object containing a complex object. The ActionLink() method (and all methods that generate route/query string values) call the .ToString() method on each property in the object (hence you get the name of the class) and do not do recursion.
If you want to pass back all properties of the AssignedDatabaseSelections object plus another property, you need to generate a new object containing each property of AssignedDatabaseSelections, for example (assuming it contains properties ID and Name)
#Html.ActionLink(Strings.CsvLabel, "DownloadSelection", "Home",
new { ID = selection.ID, Name = selection.Name, ......, Format = DownloadFormat.CSV }, null)
Note that if AssignedDatabaseSelections contains a lot of properties and/or larger values, you risk exceeding the query string limit and throwing an exception. A better approach is just to pass the ID property of the AssignedDatabaseSelection and get the object again in the GET method if you need other properties of it.
#Html.ActionLink(Strings.CsvLabel, "DownloadSelection", "Home",
new { ID = selection.ID, Format = DownloadFormat.CSV }, null)
Here is an example of how to create a link with properties from an object. I am including the code of creating a new Employee within the view but this can/should be in the model:
#{ var emp = new Employee { Name = "Tom", Age = 44 }; }
#Html.ActionLink("Test", "Test2", "Account", new {Name = emp.Name, Age = emp.Age }, null)
Please note how I am passing each property of the Employee into the anonymous object for the route values.
The above link will work with this action. The DefaultModeBinder will take the names from the query string in the link and assign it to the properties of the Employee and pass it to the action below:
public ActionResult Test2(Employee emp)
{
return null;
}
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 6 years ago.
So I am very new to MVC and development. What I am trying to do is basically create a single row table view of an user so that I can edit and update on that single row. (I hope I am making sense)
So I am using MVC Razor View and I want to create a table and edit within that table without using the CRUD functionality that is already built into MVC. I want to do inline editing of my tabular view.
So I have create a view that also has a partial view. I have a Model and my Repository as well. WHen I run this, it says Object not set to an instance of an object, and it's talking about my foreach loop. Here is the data below. If someone can offer assistance, that would be greatly appreciated. I am very new and only been really coding for about 3 months now.
Controller
public ActionResult Index(string id)
{
var attendee = (Guid)Membership.GetUser(id).ProviderUserKey;
CatalogAttendeeModel model = new CatalogAttendeeModel();
model.getAttendeesList(attendee);
var catalog = from ca in db.text
join a in db.text on ca.textID equals a.textID
where ca.textID== attendee
select ca;
foreach (var item in catalog)
{
if (item.IsActive == null)
{
item.IsActive = true;
}
}
return PartialView();
}
Index View
#model ODT4.Models.CatalogAttendeeModel
<table>
<thead>
<tr>
<th>
#Html.Label("Catalog")
#Html.Label("Role")
#Html.Label("Is Admin")
#Html.Label("Certificate Printed")
#Html.Label("Percent Watched")
#Html.Label("Percent Updated")
#Html.Label("PI Name")
#Html.Label("Action")
</th>
</tr>
</thead>
<tbody>
#foreach (var row in Model.catalogAttendees) //this is where I get the errormessage
{
{
Html.RenderPartial("CatalogAttendeeSingleRow", row);
}
}
</tbody>
</table>
Partial View
#model ODT4.Models.CatalogAttendeeModel
#{
<div id = "crud_tableEdit" >
<table>
<tr>
<td>#Html.DisplayFor(m => m.Catalog.CatalogCode)</td>
<td>#Html.DisplayFor(m => m.StudyRole)</td>
<td>#Html.DisplayFor(m => m.IsAdmin)</td>
<td>#Html.DisplayFor(m => m.IsTrainingDocPrinted)</td>
<td>#Html.DisplayFor(m => m.PercentWatched)</td>
<td>#Html.DisplayFor(m => m.PercentUpdatedOn)</td>
<td>#Html.DisplayFor(m => m.PIName)</td>
</tr>
</table>
</div>
}
CatalogModel
public List<Catalog_Attendee> catalogAttendees { get; set; }
public CatalogAttendeeModel()
{
}
public void getAttendeesList(Guid id)
{
//catalogAttendees = new List<Catalog_Attendee>();
CatalogAttendeeRepository rep = new CatalogAttendeeRepository();
catalogAttendees = rep.getAttendeesAll();
}
Repository
public List<Catalog_Attendee> getAttendeesAll()
{
return db.Catalog_Attendee.ToList();
}
public Catalog_Attendee getAttendeeByID(Guid id)
{
return db.Catalog_Attendee.FirstOrDefault(i => i.AttendeeID == id);
}
Here is the error message:
Server Error in '/' Application.
________________________________________
Object reference not set to an instance of an object.
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.NullReferenceException: Object reference not set to an instance of an object.
Source Error:
Line 17: </thead>
Line 18: <tbody>
Line 19: #foreach (var row in Model.catalogAttendees)
Line 20: {
Line 21: {
Model.catalogAttendees is null - hence the exception.
As to why ... maybe the linq expression is not returning what it should. I'm not seeing what db.text should be, but then again I'm not seeing all the code.
Edit: Also, you're not returning the model to the view. return PartialView(model);
I'm trying to retrieve a list of file info for .dll files from a specific directory to display on a ASP.NET webpage. The info I want displayed is the file name, the date it was last modified and the version.
So far I have the data being stored in a ViewBag and being displayed in the view, however it's messy and I want it to be displayed in a table.
Is there a way to take data from a ViewBag and place it in a table or is there better way than using the ViewBag?
This is the code I have for the View so far:
#using System.Diagnostics
#{
ViewBag.Title = "Versions";
}
<h2>Versions</h2></br>
<h3>File Name Last Modified Version</h3>
#ViewBag.FileList
#for(int i =0; i < ViewBag.FileList.Length;i++)
{
<p>
#ViewBag.FileList[i];
#{ FileInfo f = new FileInfo(ViewBag.FileList[i]);
<table>
<td><tr>#f.Name</tr></td>
<td><tr> #f.LastAccessTime</tr></td>
</table>
FileVersionInfo currentVersion = FileVersionInfo.GetVersionInfo(ViewBag.FileList[i]);
#currentVersion.FileVersion
}
</p>
}
ViewBag should not be exploited this way. Use a View Model
In your controller's action pass the data like this,
public ActionResult Files()
{
List<FileInfo> fileNames = ...get file names
return View(fileNames);
}
In your view,
Right at the top, define the type of object
#model IEnumerable<System.IO.FileInfo>
Your table should be layed out in a way similar to the below.
<table>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>#item.Name</td>
<td>#item.LastAccessTime</td>
</tr>
}
</tbody>
</table>
I have the following problem - I am developing an ASP.NET MVC 3 application and I have view which is strongly typed. Because of the complexity of the data the model in the view looks like this :
#model List<List<DataAccess.MCS_DocumentFields>[]>
Then I render the view like this :
#using (Html.BeginForm("ActionMethodName", "Forms"))
{
<table border="1">
<tbody>
#for (int i = 0; i < Model.Count(); i++)
{
if (Model[i][0][0].ContentTypeId == 1)
{
#Html.Partial("_PartialHeader", Model[i])
}
else if (Model[i][0][0].ContentTypeId == 2)
{
#Html.Partial("_PartialDrawing", Model[i])
}
else if (Model[i][0][0].ContentTypeId == 3)
{
#Html.Partial("_PartialBody", Model[i])
}
else if (Model[i][0][0].ContentTypeId == 4)
{
#Html.Partial("_PartialFooter", Model[i])
}
}
</tbody>
</table>
<button type="submit">Save</button>
}
and this is one of my partial views :
if (string.IsNullOrEmpty(item.FieldValue))
{
<td colspan="2">
#Html.DisplayFor(y => y[i][0].QuestionText)
#Html.HiddenFor(y => y[i][0].QuestionText)
</td>
}
else
{
<td colspan="2">
#Html.DisplayFor(y => y[i][0].QuestionText)
#Html.HiddenFor(y => y[i][0].QuestionText)
:
#Html.DisplayFor(y => y[i][0].FieldValue)
#Html.HiddenFor(y => y[i][0].FieldValue)
</td>
}
This is just a snippet, what I want to say is that my table has at least 8-9 rows and almost each row has #Html.HiddenFor so I expect to get data when I'm submiting the form.
In my controller I have this method :
[HttpPost]
public ActionResult ActionMethodName(List<MCS_DocumentFields>[] collection)
{
var test = collection;
List<MCS_Documents> model = DocumentService.All().ToList();
return View("Index", model);
}
I tried a lot of different types for the collection argument. Most of the time I get null, at best I get the first two row (No idea why exactly the first two) but nothing more. If I use FormCollection then I have all my submitted data, but it's not related to my MCS_DocumentFields class in any way.
I don't know what I'm doing wrong. I don't think that the type for the method should be guessed I think it must be determined by something and if there is some problem in code (most possibly in the partial view) because I've posted here almost all of my main view, then any suggestions why my logic is not working and why I can't bind the data to the original type of the model?
I suggest you to look at the BeginCollectionItem package (http://nuget.org/packages/BeginCollectionItem/), allthough I can see that your model is really complex (3 dimensions), sou you'll have to nest them in a really nasty manner.
Also you should consider (due to your model complexity) creating a custom model binder (http://www.codeproject.com/Articles/605595/ASP-NET-MVC-Custom-Model-Binder).
Just one last remark - your model in View differs from your model that you expect in action:
List<MCS_DocumentFields>[] collection != List<List<DataAccess.MCS_DocumentFields>[]>
Ivan
I have this one in View:
<%
foreach (var item in (List<MyType>)ViewData["MyTypeArray"])
{
%><tr>
<td>
<%=Html.Encode(item.Name)%>
</td>
<td>
<%=Html.CheckBox("MyTypeFlags" + item.BitNumber),
/* Model goes here*/,
new {#value = (1 << item.BitNumber)})%> // html attr
</td>
</tr>
<%
}
%>
and I want do smth like this in Controller:
foreach (var item in MyDynamicallyCreatedArray)
{
//if (["MyTypeFlags" + item.BitNumber] != 0) // This shoud be changed
}
Question is how should I declare MyDynamicallyCreatedArray and go through the cycle?
You should look at using a "view model". You basically create "Models" just for your view that contain the data items you need in your view.
I use these quite often and they are really a great way of getting data in and out of your view.
For an example you can view here: http://stephenwalther.com/blog/archive/2009/04/13/asp.net-mvc-tip-50-ndash-create-view-models.aspx
Take a look at Phil Haack's post, it gets a bit tricker with checkboxes as if a box is unchecked then it doesnt submit a value.
Model Binding to a List
http://haacked.com/archive/0001/01/01/model-binding-to-a-list.aspx