ViewBag использует новую динамическую функцию .NET 4.0. Ваш код не работает по той же причине, по которой не работает следующий код:
IEnumerable<int> array = new int[] { 1, 2, 3 };
dynamic foo = array;
Console.WriteLine(foo.Count());
Методы расширения не могут быть разрешены для динамических объектов. Вы можете заставить его работать следующим чудовищем:
@(((System.Data.Objects.ObjectSet<Student>)Model).Count())
Но, пожалуйста, пообещай мне, что ты никогда не будешь делать ничего подобного.
Тот факт, что ваш код не работает, на самом деле хорошая вещь. Потому что ИМХО то, что вы пытаетесь сделать, неправильно во многих отношениях:
- Вы передаете модели доменов своим представлениям вместо использования моделей представлений.
- Вы передаете доступ к данным конкретным объектам, например
ObjectSet<T>
, вместо использования простых объектов CLR.
- Вы используете слабо типизированный ViewBag => вы теряете Intellisense, вам нужно будет выполнить некоторые приведения в ваших представлениях, чтобы вызвать определенные перегрузки некоторых вспомогательных методов (которые приведут к спагетти-коду), вы получите некоторое загадочное ошибки из-за динамической природы ViewBag, вы называете это, ...
Таким образом, правильный способ сделать это - определить модель представления, которая будет содержать только те свойства, которые важны для вашего представления. Например:
public class StudentViewModel
{
public string Name { get; set; }
}
и ваше действие контроллера выполнит запрос в хранилище и выберет модель, которая будет сопоставлена с моделью представления, переданной в соответствующее строго типизированное представление:
public ActionResult Index()
{
var model = context.GetStudents();
var viewModel = model.Select(x => new StudentViewModel
{
Name = string.Format("{0} {1}", x.FirstName, x.LastName)
}).ToArray();
return View(viewModel);
}
и, наконец, ваше строго типизированное представление будет зависеть только от конкретной модели представления (представление не должно заботиться о конкретных вещах для доступа к данным, его следует передавать только то, что ему нужно показать):
@model StudentViewModel[]
<div>We have @Model.Length students</div>