Подтвердить что ты не робот

'object' не содержит определения для 'X'

У меня была эта проблема раньше и не разрешала ее. У меня есть список (сгенерированный в контроллере 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'

хотя любопытно, что если я введу в окно Immediate (во время отладки):

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

так что очевидно, что это поле. В чем моя проблема?

4b9b3361

Ответ 1

Вы используете анонимный объект здесь:

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

Ответ 2

Это заставило меня сесть, пока я не проверил свой код и не нашел это:

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 

Исправлено.

Ответ 3

Используйте 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 *@
}

Ответ 4

Это может произойти, если имя вашего класса не совпадает с именем файла (я знаю, что это глупо, но это может вам помочь)