我曾经遇到过这个问题并且没有解决它。我有一个列表(在MVC3控制器中生成):
ViewBag.Languages = db.Languages
.Select(x => new { x.Name, x.EnglishName, x.Id })
.ToList();
在我的页面(Razor)上我尝试迭代它:
foreach (var o in ViewBag.Languages)
{
string img = "Lang/" + o.EnglishName + ".png";
@* work *@
}
但是对o.EnglishName
的引用失败并显示错误:
'object'不包含'EnglishName'的定义
虽然奇怪的是,如果我输入立即窗口(在调试时):
很明显这个领域就在那里。我的问题在这里是什么?o { Name = བོད་སྐད་, EnglishName = Tibetan, Id = 31 } EnglishName: "Tibetan" Id: 31 Name: "བོད་སྐད་"
答案 0 :(得分:62)
您在这里使用匿名对象:
ViewBag.Languages = db.Languages
.Select(x => new { x.Name, x.EnglishName, x.Id })
.ToList();
编译器将匿名对象作为internal
发出。 Razor视图由ASP.NET运行时自动编译为单独的程序集。这意味着您无法访问控制器中生成的任何匿名对象。
因此,为了解决您的问题,您可以定义一个视图模型:
public class LanguageViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public string EnglishName { get; set; }
}
然后在您的控制器中使用此视图模型:
ViewBag.Languages = db.Languages
.Select(x => new LanguageViewModel
{
Name = x.Name,
EnglishName = x.EnglishName,
Id = x.Id
})
.ToList();
现在你有了一个视图模型,你的代码的下一个改进当然是摆脱ViewBag
这个我厌倦了看到并简单地使用视图模型和强类型的垃圾:
public ActionResult Foo()
{
var model = db
.Languages
.Select(x => new LanguageViewModel
{
Name = x.Name,
EnglishName = x.EnglishName,
Id = x.Id
})
.ToList();
return View(model);
}
然后当然有一个强类型视图:
@model IEnumerable<LanguageViewModel>
@Html.DisplayForModel()
然后定义相应的显示模板,该模板将由ASP.NET MVC引擎为视图模型的每个元素自动呈现,这样您甚至不需要在视图中编写单个foreach({{1} }):
~/Views/Shared/DisplayTemplates/LanguageViewModel.cshtml
答案 1 :(得分:4)
在检查我的代码并发现这个问题之前,这让我很开心:
class AdsViewModel
{
public int Id { get; set; }
public string City { get; set; }
public string CompanyName { get; set; }
public string ContactName { get; set; }
public string UserEmail { get; set; }
public string ContactPhone { get; set; }
public string ShortTitle { get; set; }
public string AdUrl { get; set; }
}
将其更改为:
public class AdsViewModel
修正了它。
答案 2 :(得分:0)
如果您的类名与文件名不匹配,也会发生这种情况(我知道它很愚蠢但可能对您有所帮助)
答案 3 :(得分:0)
请使用ViewData而不是ViewBag。
ViewData["Lang"] = db.Languages
.Select(x => new { x.Name, x.EnglishName, x.Id })
.ToList();
然后
foreach (var o in (dynamic) ViewData["Lang"])
{
string img = "Lang/" + o.EnglishName + ".png";
@* work *@
}