2012-10-11 2 views
0

Цель: создать раскрывающееся меню для повторного использования, в котором перечислены администраторы, менеджеры и агенты моего веб-сайта. Эти типы пользователей определяются таблицами .NET Simplemembership webpages_Roles и webpages_UsersInRoles.MVC ViewModel errors

До сих пор: У меня есть таблица UserProfile в моей базе данных, которая имеет 25 столбцов. У меня есть соответствующая модель домена с тем же именем, доступ к которой осуществляется из моего UserContext() EF.

Выпадающее меню нужно только перечислить ПгвЬЫат Пользователя, LastName и UserId так вместо того чтобы работать с полной моделью предметной области, я создали следующий ViewModel:

namespace MyModels.Models.ViewModels 
{ 
    public class AdminsAndAgentsListVM 
    { 
     public string FirstName { get; set; } 
     public string LastName { get; set; } 
     public int UserId { get; set; } 
    } 
} 

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

public ActionResult AdminsAndAgentsList() 
{ 
    UsersContext _db = new UsersContext(); //provides me access to UserProfiles data 
    var admins = Roles.GetUsersInRole("Admin"); //gets users with this role 

    var viewModel = _db.UserProfiles 
     .Where(x => admins.Contains(x.UserName)); //Selects users who match UserName list 
    return View(viewModel); 
} 

затем я эшафот представление списка и основывают его на строго типизированных ViewModel:

@model IEnumerable<MyModels.Models.ViewModels.AdminsAndAgentsListVM> 

@{ 
    ViewBag.Title = "AdminsAndAgentsList"; 
} 

<h2>AdminsAndAgentsList</h2> 

<p> 
    @Html.ActionLink("Create New", "Create") 
</p> 
<table> 
    <tr> 
     <th> 
      @Html.DisplayNameFor(model => model.FirstName) 
     </th> 
     <th> 
      @Html.DisplayNameFor(model => model.LastName) 
     </th> 
     <th> 
      @Html.DisplayNameFor(model => model.UserId) 
     </th> 
     <th></th> 
    </tr> 

@foreach (var item in Model) { 
    <tr> 
     <td> 
      @Html.DisplayFor(modelItem => item.FirstName) 
     </td> 
     <td> 
      @Html.DisplayFor(modelItem => item.LastName) 
     </td> 
     <td> 
      @Html.DisplayFor(modelItem => item.UserId) 
     </td> 
     <td> 
      @Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) | 
      @Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) | 
      @Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ }) 
     </td> 
    </tr> 
} 

</table> 

я успешно строить и когда я запускаю веб-страницы, я получаю следующее сообщение об ошибке:

The model item passed into the dictionary is of type'System.Data.Entity.Infrastructure.DbQuery 1[My.Models.UserProfile]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable 1[My.Models.ViewModels.AdminsAndAgentsListVM]'.

Если я воссоздать вид, но сильно ввести его Agains UserProfile, он отлично работает. Итак, как это сделать, чтобы я мог вместо этого использовать TypeModel вместо этого? Приведите примеры, если это возможно. Я новичок в C# и MVC и действительно получаю удовольствие от просмотра кода из первых рук. Очень ценю помощь!

EDIT ----------------------------- Вот объект для UserProfile:

public class UsersContext : DbContext 
{ 
    public UsersContext() 
     : base("DefaultConnection") 

    { 
    } 

    public DbSet<UserProfile> UserProfiles { get; set; } 
} 

[Table("UserProfile")] 
public class UserProfile 
{ 

    [Key] 
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
    public int UserId { get; set; } 
    public string UserName { get; set; } 

    [Required] 
    [ReadOnly(true)] 
    [DisplayName("SubscriberID")] 
    public int? SubscriberId { get; set; } //Foreign key 

    [StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.")] 
    [Display(Name = "First Name")] 
    public string FirstName { get; set; } 

    [StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.")] 
    [Display(Name = "Last Name")] 
    public string LastName { get; set; } 

    //public DateTime DOB { get; set; } 
    [DataType(DataType.Date)] 
    public DateTime? DOB { get; set; } //This allows null 

    public bool? Gender { get; set; } 

    [Required] 
    [MaxLength(250)] 
    [EmailAddress] 
    public string Email { get; set; } 

    [MaxLength(250)] 
    [EmailAddress] 
    [NotEqualTo("Email", ErrorMessage = "Alt Email and Email cannot be the same.")] 
    public string AltEmail { get; set; } 

    [MaxLength(250)] 
    [EmailAddress] 
    public string FormEmail { get; set; } 

    public Address Address { get; set; } 

    [MaxLength(20)] 
    public string Telephone { get; set; } 

    [MaxLength(20)] 
    public string Mobile { get; set; } 

    [Required] 
    [DataType(DataType.Date)] 
    public DateTime DateAdded { get; set; } 

    [DataType(DataType.DateTime)] 
    public DateTime? LastLoginDate { get; set; } 

    public bool? OffersOptIn { get; set; } //any offers we may have with us or partners 

    public bool? NewsOptIn { get; set; } //newsletter 

    public bool? SubscriptionOptIn { get; set; } //account, technical, renewal notices, pp invoices, pp receipts 

    public bool? OrderOptIn { get; set; } //orders - workflow notices 

    [DataType(DataType.DateTime)] 
    public DateTime? LastUpdatedAccountDate { get; set; } //Last time user updated contact info 
} 
+0

Если force View (viewModel.ToList()); , Я получаю аналогичную ошибку, Элемент модели, переданный в словарь, имеет тип «System.Collections.Generic.List'1 [My.Models.UserProfile]», но для этого словаря требуется элемент модели типа «System.Collections» .Generic.IEnumerable'1 [My.Models.ViewModels.AdminsAndAgentsListVM]. –

ответ

2

Попробуйте это. Он отправит ваш запрос в вашу модель просмотра.

var viewModel = _db.UserProfiles 
     .Where(x => admins.Contains(x.UserName)) 
     .Select(x => new AdminsAndAgentsListVM { 
         FirstName = x.FirstName, 
         LastName = x.LastName, 
         UserId = x.UserId}); 
+0

Это еще одно хорошее решение. Я использовал это в конце, поскольку он был менее подробным. Благодаря! –

0

Измените линию возврата к:

return View(viewModel.AsEnumerable());

+0

View возвращает ActionResult, так что не будет работать –

+0

Crap, который должен был быть на 'viewModel'. Исправлено, спасибо за головы. – Gromer

0

Вы не выбираете свой ViewModel. Вы должны сделать Select (х => новый AdminsAndAgentsListVM на запрос. Я хотел бы также сделать ToList() там.

1

можно передать мнение, запрос, не модель.

Выполнить запрос как у вас это

var query = _db.UserProfiles 
      .Where(x => admins.Contains(x.UserName)); 

Затем экземпляр и заполнить ваш взгляд модель

var viewModels = new List<AdminsAndAgentsListVM>(); 
foreach (var item in query) 
{ 
var viewModel = new AdminsAndAgentsListVM(); 
    viewodel.FirstName = item.FirstName; 
    viewodel.LastName = item.LastName; 
    viewodel.UserId = item.UserId; 
viewModels.Add(viewModel); 
} 



    return View(viewModels); 

Это предполагает, конечно, что UserProfile и AdminsAndAgentsListVM имеют соответствующие свойства.

+0

Я добавил ваш код, но я получаю красные squiggles под query.FirtName, query.LastName и т. Д. Ошибка: «System.Linq.IQueryable » не содержит определения для «UserId», и не может быть найден метод расширения 'UserId', принимающий первый аргумент типа 'System.Linq.IQueryable ' (вам не хватает директивы using или ссылки на сборку?) –

+0

Спасибо, что ответили путь! Я добавил объект UserProfile выше для вашей справки. –

+0

@JulianDormon глупый, запрос IQueryable. Проверьте мой отредактированный ответ –