В вашем случае было бы намного проще создать модель для хранения ваших данных, чем использовать анонимный тип.
Проблема, с которой вы столкнулись, заключается в том, что ваш анонимный тип преобразуется в объект, когда он хранится в ViewData. Со стороны пользовательского интерфейса, когда вы получаете этот объект, единственный способ получить доступ к его свойствам - это использовать отражение. Вы НЕ хотите делать это в своем пользовательском интерфейсе. Это будет очень некрасиво. Вместо этого просто добавьте следующий класс в свои Модели:
public class Project{
public string Title {get;set;}
public string DevUrl {get;set;}
public string QAUrl {get;set;}
public string LiveUrl {get;set;}
public IEnumerable<User> Users {get;set;}
public static IEnumerable<Project> RetrieveAllProjects()
{
return from p in db.Projects
orderby p.title
select new Project
{
Title = p.title,
DevURL = p.devURL ?? "N/A",
QAURL = p.qaURL ?? "N/A",
LiveURL = p.liveURL ?? "N/A",
Users = p.GetUsers().MakeUserList()
};
}
В вашем контроллере сделайте это:
public ActionResult Index()
{
return View("Index", Project.RetrieveAllProjects());
}
и в коде вашего взгляда строго наберите его так:
//snip
public partial class Index : ViewPage<IEnumerable<Project>>
{
//snip
Вы можете подумать, что все эти модели лежат на одном месте, но это намного проще для понимания и делает код пользовательского интерфейса намного тоньше, если вы используете их с умом.
Кроме того, модель - это отличное место (и, фактически, оно должно быть там, где вы это делаете) для размещения логики загрузки ваших данных и построения самих моделей. Подумайте ActiveRecord. И пока вы все это кодируете, поймите, что такие проекты, как SubSonic, создают ваши модели для вас без суеты и суеты.