2011-10-04 223 views
31

我曾經遇到過這個問題,但沒有解決它。我有一個列表(在MVC3控制器生成):'object'不包含'X'的定義

ViewBag.Languages = db.Languages 
    .Select(x => new { x.Name, x.EnglishName, x.Id }) 
    .ToList(); 

和我的網頁(剃刀)對我試着來遍歷它:

foreach (var o in ViewBag.Languages) 
{ 
    string img = "Lang/" + o.EnglishName + ".png"; 
    @* work *@ 
} 

而是參考o.EnglishName失敗,出現錯誤:

'object' does not contain a definition for 'EnglishName'

雖然奇怪的是,如果我鍵入到立即窗口(同時調試):

o 
{ Name = བོད་སྐད་, EnglishName = Tibetan, Id = 31 } 
    EnglishName: "Tibetan" 
    Id: 31 
    Name: "བོད་སྐད་" 

顯然這個領域是存在的。我這裏有什麼問題?

回答

58

您在這裏使用匿名對象:

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(~/Views/Shared/DisplayTemplates/LanguageViewModel.cshtml):

@model LanguageViewModel 
... generate the image or whatever you was attempting to do in the first place 
+1

哇。真棒回覆(+1)。非常感謝 - 是的,我正在移除所有對ViewBag的引用,以支持視圖模型... – ekkis

+1

非常好,但我們有時可能需要ViewBag。我們只能將一個模型傳遞給一個視圖。但是,我們可能想要發送一些其他小數據收集,不是嗎?在這種情況下,使用ViewBag發送該小數據集合更容易。當然,您也可以使用PartialViews發送它。我不知道有沒有其他建議。 – oneNiceFriend

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 

固定它。

-1

如果你的類的名稱不匹配的文件(我知道這是愚蠢的,但它可以幫助你)

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 *@ 
} 
相關問題