'object'不包含'X'的定义

时间:2011-10-04 18:58:35

标签: c# asp.net-mvc razor

我曾经遇到过这个问题并且没有解决它。我有一个列表(在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: "བོད་སྐད་"
很明显这个领域就在那里。我的问题在这里是什么?

4 个答案:

答案 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 *@
}