Вывести содержимое List во view

104
14 июня 2019, 08:30

Каким образом можно вывести выборку на основе модели данных. но с полями в ней не описанными? Например имеется контроллер:

public ActionResult Index()
    {
       var asd = db.tbl
            .GroupBy(x => DbFunctions.TruncateTime(x.q_Date))
            .Select (x => new
                  {
                  Val = x.Count(),
                  Dat = (DateTime)x.Key
                  }).ToList();   
        ViewBag.Asd = asd;
        return View();
    }

здесь tbl таблица с полем q_Date.

Но данную выборку не получается вывести во view:

@foreach (var c in ViewBag.Asd)
{
    <tr>
        <td>
            @c.Dat
        </td>
        <td>
            @c.Val
        </td>
    </tr>
}

Ошибка - "object" не содержит определения для "Dat" : @c.Dat Неужели для каждого такого случая придется создавать отдельный класс в Models? нельзя это как-то обойти?

Answer 1

Подобные классы можно называть Dto, ViewModel - и складывать в отдельные от папки с моделями (если у вас единое приложение). Делайте примерно так:

Создаёте модель представления:

public class BookListViewModel
{
    public int Val { get; set; }
    public DateTime Dat { get; set; }
}

Делаете экшн контроллера вида:

public ActionResult Index()
{
    var model = db.tbl
        .GroupBy(x => DbFunctions.TruncateTime(x.q_Date))
        .Select (x => new
              {
                  V = x.Count(),
                  D = (DateTime)x.Key
              })
        .AsNoTracking()
        .AsEnumerable()
        .Select (x => new BookListViewModel
              {
                  Val = x.V,
                  Dat = (DateTime)x.D
              })
        .ToArray();
    return View(model);
}

(Тут надо хорошо понимать разницу между IEnumerable и IQueryable, см. например тут)

Ещё можно сделать конструктор в классе:

public class BookListViewModel
{
    public BookListViewModel (int val, DateTime dat)
    {
        this.Val = val;
        this.Dat = dat;
    }
    public int Val { get; private set; }
    public DateTime Dat { get; private set; }
}

И сократить запись до:

public ActionResult Index()
{
    var model = db.tbl
        .GroupBy(x => DbFunctions.TruncateTime(x.q_Date))
        .Select (x => new
              {
                  V = x.Count(),
                  D = (DateTime)x.Key
              })
        .AsNoTracking()
        .AsEnumerable()
        .Select (x => new BookListViewModel(x))
        .ToArray();
    return View(model);
}

Или вообще перейти на использование автомаппера.

В представлении итерируете модель:

@model IEnumerable<BookListViewModel>
@foreach (var item in Model)
{
    <tr>
        <td>
            @item.Dat
        </td>
        <td>
            @item.Val
        </td>
    </tr>
}
READ ALSO
Как открыть файл из ресурсов программы? [дубликат]

Как открыть файл из ресурсов программы? [дубликат]

На данный вопрос уже ответили:

119
Как правильно сравнить дату C#

Как правильно сравнить дату C#

Ребята подскажите как правильно сравнить дату? у меня есть запрос в бд, там отбирает строки и возвращает результат, как коллекцию обьекта...

108
Использование библиотеки DataAnnotations

Использование библиотеки DataAnnotations

Подскажите пожалуйста какой смысл от аннотации [DataType(DataTypePassword)]? Вот например если я использую во вью хелпер @Html

133