0

Я выполняю роли пользователя в MVC6 (используя EF7), и я думаю, что я просто что-то упустил, но в форме, используемой для определения ролей пользователя, я ничего не получаю в опубликованной обратной модели контроллерПолучение данных CheckList в сообщении MVC6

Это моя модель

public class UserRoleItem 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public IdentityUserRole<int> userRole { get; set; } 
    public bool HasRole { get; set; } 
} 

public class UsersRolesViewModel 
{ 
    public int UserId { get; set; } 
    public string FullName { get; internal set; } 

    public List<UserRoleItem> UserRoles; 
} 

Это мнение

@model Skill.ViewModels.Manage.UsersRolesViewModel 
<br /> 
<h3>Set Roles for user - @Model.FullName</h3> 
<form asp-action="ChangeUsersRoles" > 
    <div class="form-horizontal"> 
     <hr /> 
     <input type="hidden" asp-for="UserId" /> 

     @foreach (var userRole in Model.UserRoles) 
     { 
      <input type="hidden" asp-for="@userRole.Id" /> 
      <div class="form-group"> 
       <div class="inline-block col-md-8"> 
        <span class="col-md-1" align="center"> 
         <input type="checkbox" asp-for="@userRole.HasRole" /> 
        </span> 
        <div class="col-md-7"> 
         @userRole.Name (@userRole.Description) 
        </div> 
       </div> 
      </div> 
     } 
     <hr /> 
     <div class="form-group"> 
      <div class="col-md-10"> 
       <input type="submit" value="Save" class="btn btn-default" /> 
      </div> 
     </div> 
    </div> 
</form> 

Это контроллер

// GET: Users/ChangeUserRoles/5 
public async Task<IActionResult> ChangeUserRoles(int? id) 
{ 
    if (id == null) 
    { 
     return HttpNotFound(); 
    } 

    var model = new UsersRolesViewModel(); 
    ApplicationUser appUser = await _context.ApplicationUsers.SingleAsync(m => m.Id == id); 
    if (appUser == null) 
    { 
     return HttpNotFound(); 
    } 
    else 
    { 
     model.UserId = (int)id; 
     model.FullName = appUser.FullName; 
     var some = from r in _context.Roles 
        from ur in _context.UserRoles 
        .Where(inner => r.Id == inner.RoleId && inner.UserId == id) 
        .DefaultIfEmpty() 
        select new UserRoleItem 
        { 
         Id = (int)r.Id, 
         Name = r.Name, 
         Description = r.NormalizedName, 
         userRole = ur, // this is needed else it has a hissy fit 
         HasRole = (ur != null) 
        }; 
     // get all of the Roles and then also link to the ones the user currently has 
     model.UserRoles = (some).ToList(); 
    } 
    return View(model); 
} 

// POST: Users/ChangeUserRoles/5 
[HttpPost] 
[ValidateAntiForgeryToken] 
public async Task<IActionResult> ChangeUserRoles([Bind(include:"UserId,UserRoles")]UsersRolesViewModel userModel) 
{ 
    if (ModelState.IsValid) 
    { 
     // update based on the changes 

     // return RedirectToAction("Edit", new { userModel.UserId }); 
    } 
    return View(userModel); 
} 

Так что, когда я получаю сообщение обратно в Save, список UserRoles имеет значение NULL, поэтому я предполагаю, что здесь просто отсутствует очевидная вещь?

Также еще одна небольшая проблема - заявление EF Linq. Если я удалю заявление

userRole = ur, 

от Выбрать части запроса Linq, система имеет истерику и говорит моя схема устарела (что это не так). Я думаю, что это связанно со следующим утверждением, где я тестированием внешнего соединения значения,

HasRole = (ur != null) 

Хотя это кажется вполне разумным и работает, если переменная Ур используются перед тестированием на нуль (или нет)

+0

Вы не можете использовать цикл foreach для создания элементов управления формы для коллекции (если вы проверите html, вы увидите, что ваши входы имеют одинаковый атрибут name, который не имеет отношения к вам). Используйте цикл 'for' или' EditorTemplate' для 'UserRoleItem' для создания правильных атрибутов' name' с индексаторами. Для примера, использующего цикл 'for', см. [Этот ответ] (http://stackoverflow.com/questions/29542107/pass-list-of-checkboxes-into-view-and-pull-out-ienumerable/29554416# 29554416) –

+0

Спасибо Стивен. После того, как я ввел проблему, я фактически изменил код для использования EditorTemplates, а затем массив данных был правильно сгенерирован. Может быть, я должен загрузить решение для потомков? –

+0

Добавьте свой ответ и примите его, чтобы закрыть это. :) –

ответ

0

После ввода этого вопроса я еще раз исследовал проблему и обнаружил, что могу делать то, что мне нужно, используя EditorTemplate . Поэтому я создал папку EditorTemplate в моей папке «Пользователи», так как она была UserController, а затем добавила следующий файл UserRoleItem.cshtml

@model UserRoleItem 

<input type="hidden" asp-for="Id" /> 
<div class="form-group"> 
    <div class="inline-block col-md-8"> 
     <span class="col-md-1" align="center"> 
      <input type="checkbox" asp-for="HasRole" /> 
     </span> 
     <div class="col-md-7"> 
      @Model.Name (@Model.Description) 
     </div> 
    </div> 
</div> 

Затем я изменил мнение (так называемый ChangeUsersRole.cshtml), чтобы быть

@model Skill.ViewModels.Manage.UsersRolesViewModel 

<br /> 
<h3>Set Roles for user - @Model.FullName</h3> 
<hr /> 
<form asp-action="ChangeUsersRoles"> 
    <div class="form-horizontal"> 
     <input type="hidden" asp-for="UserId" /> 
     @Html.EditorFor(m => m.UserRoles) 
     <hr /> 
     <div class="form-group"> 
      <div class="col-md-10"> 
       <input type="submit" value="Save" class="btn btn-default" /> 
      </div> 
     </div> 
    </div> 
</form> 

Отметим также: что я попытался использовать новый формат

<input asp-for="UserRoles" /> 

вместо этой строки в представлении

@Html.EditorFor(m => m.UserRoles) 

Но это не сработало, как ожидалось. Опять же, возможно, я все еще что-то не так - или, может быть, эта функция еще не работает?