I'm learning to write MVC websites in C# with ASP.NET and the Entity Framework.
However, I'm struggling to write a dictionary lookup that would work with the Html.DisplayFor
method.
Say I have the following two models:
public class Dog
{
public int Id;
public string Name;
public int BreedId;
(...)
}
public class Breed
{
public int Id;
public string Name;
(...)
}
Then, somewhere in the controller, I'm creating a dictionary containing all the Breeds , indexed by the Id
, and assigning it to ViewBag.Breeds
.
In the Dogs/Index
View, I use something like that:
@model IEnumerable<App.Models.Dog>
<table>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@(ViewBag.Breeds[item.BreedId].Name)
</td>
</tr>
}
</table>
And it generates a table of the Dogs and their Breeds , as intended.
However, if I try to use the dictionary lookup inside the Html.DisplayFor
method, I get an error because an expression tree may not contain a dynamic operation :
@Html.DisplayFor(modelItem => ViewBag.Breeds[item.BreedId].Name)
Casting it to an explicitly typed dictionary doesn't work either:
@Html.DisplayFor(modelItem => ((Dictionary<int, Breed>)ViewBag.Breeds)[item.BreedId].Name)
Is there a way to make it work?
You should check out this question which explores why DisplayFor
has such a funny syntax. It isn't just a simple function that accepts a string. It accepts an expression, which is never executed but parsed, so that the Razor engine can find one of the model's properties and all of its attributes-- that is how is discovers scaffolding and knows how to render a model member.
Bottom line is-- you can't just put any old string in DisplayFor
. But then again, you shouldn't need to-- to display a string, you don't need it.
Option 1
Instead of
@Html.DisplayFor(modelItem => ViewBag.Breeds[item.BreedId].Name)
Just use
@ViewBag.Breeds[item.BreedId].Name
or if your breed names might contain a <
or &
character, you might need to HTML-escape them, so use
@Html.Encode(ViewBag.Breeds[item.BreedId].Name)
Option 2
If you really want to take advantage of DisplayFor
and MVC scaffolding, add the desired computed field to the model itself, and reference it plainly in the view.
public class Dog
{
public int Id;
public string Name;
public int BreedId;
[Display(Name = "Breed Name")] //Optional scaffolding attributes
public string BreedName
{
get
{
return ViewBag.Breeds[BreedId].Name;
}
}
}
and in your view
@Html.DisplayFor(modelItem => item.BreedName)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.