Reputation: 1329
Why can my viewmodel not iterate through my List Books variable?
Model Definitions
public class Shelf
{
public int bookId { get; set; }
public string Name { get; set; }
public string Notes { get; set; }
public List<Book> Books { get; set; }
}
public class Book
{
public int BookId { get; set; }
public string Name { get; set; }
public string Notes { get; set; }
public Shelf shelf { get; set; }
}
public class ReadViewModel
{
public int ShelfId { get; set; }
public string Name { get; set; }
public List<Book> Books { get; set; }
}
The controller seems to be fine since I am able to display ShelfId and Name for the ReadViewModel. Edit I have the action method it at the request of users here.
[HttpGet]
public ViewResult Details(int ShelfId)
{
//find the right building for edit
var shelfs = from shelf in applicationDBContext.Shelfs
where shelf.ShelfId == ShelfId
select shelf;
ReadViewModel readViewModel = new ReadViewModel
{
ShelfId = shelfs.First().ShelfId,
Name = shelfs.First().Name,
Books = shelfs.First().Books, //Error still present despite this
};
return View("Details", readViewModel);
}
I know, I should be using async and await in the above, but I am teaching myself mvc, vnext, and etc. So using the above to teach me how the flow works before I use more "best practices".
View
@model Application.Model.ReadViewModel
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
@{
ViewBag.Title = "Shelf Details";
}
<h1>Building Details</h1>
<table>
<tr>
<td>@Html.LabelFor(model => model.ShelfId)</td>
<td>@Html.DisplayTextFor(model=>model.ShelfId)</td>
</tr>
<tr>
<td>@Html.LabelFor(model => model.Name)</td>
<td>@Html.DisplayTextFor(model => model.Name)</td>
</tr>
</table>
<h2>Rooms</h2>
<table>
<tr>
<td>@Html.LabelFor(model => model.Books.First().BookId)</td>
<td>@Html.LabelFor(model => model.Books.First().Name)</td>
</tr>
@*@foreach (var book in Model.Books)
{
}*@
@*@for(var booksIndex = 0; booksIndex < Model.Books.Count(); booksIndex++)
{
<tr>
<td>@Html.DisplayTextFor(model => model.Books[booksIndex].BookId)</td>
<td>@Html.DisplayTextFor(model => model.Books[booksIndex].Name)</td>
<td></td>
</tr>
}*@
</table>
I keep getting an error like Value cannot be null
or something like Object instance cannot be null
when I try to iterate through rooms with either a for or a foreach. If I comment out the loops, I can display the shelf id and name.
This doesn't make sense to me. At one time I had no data for books given the shelf, so I thought that was the issue. So I put in some data and I still get the exact same error. So I am convinced that my view is unable to iterate through my books and list them.
Both loops as given above give no errors until I try to access the view through the browser.
Upvotes: 1
Views: 903
Reputation: 9821
Yea controller is important and also how the data is being bound. How are you population the model? What framework are you using? Entiry, Linq2SQL, dapper?
The reason you are getting null or object is not set, is clearly because those values are not set. Nobody is trying to trick you.
The project will compile fine because the code syntax is correct, at build time. The reason you get errors at the view, known as runtime errors, is because the data that is being bound is incorrect or missing. The compiler cannot verify against runtime data... because it doesn't know anything about that.
With Visual Studio you can set a break point in the View, on the @code section. I would suggest setting a break point right at the first loop. Click on the far left margin to get a red dot.
Run the site in Debug (F5) and Visual Studio will stop at the break point on the View. You can then inspect your Model
or List<Model>
and see what data is there. Make sure the properties you need are populated. (The image shows the breakpoint hit after running debug. A yellow line appears and you can hover over variables to inspect the values or right click them and add them to the watch panel)
That is the only reason you will get these errors at runtime.
Upvotes: 1