«объект» не содержит определения для «X» - PullRequest
37 голосов
/ 04 октября 2011

Однажды у меня была эта проблема, и я не решил ее.У меня есть список (сгенерированный в контроллере 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 терпит неудачу с ошибкой:

'объект' не содержит определения для 'EnglishName'

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

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

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

Ответы [ 4 ]

63 голосов
/ 04 октября 2011

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

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
4 голосов
/ 22 декабря 2015

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

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 

Исправлено.

0 голосов
/ 14 ноября 2016

Пожалуйста, используйте 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 *@
}
0 голосов
/ 12 августа 2016

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...