用户创建时未保存多选值

时间:2019-01-13 22:25:44

标签: model-view-controller asp.net-mvc-5 multi-select

我正在尝试在MVC 5中创建的用户上保存一个多选列表,但是这些值没有保存。值仅在编辑时保存。由于某种原因,它无法在创建上工作,并且问题似乎与身份用户有关。我在另一个实体的不同控制器中实现了相同的方法,并且效果很好。

我正在尝试通过以下代码向用户分配多位医疗专业人员。我没有收到任何错误或保存中断,只是没有保存值。

任何人都可以看看我的代码,并为我解决这个问题。

以下是与创建用户有关的控制器代码:

public ActionResult Create()
        {
            PopulateDepartmentsDropDownList();
            PopulateSuperiorsDropDownList();
            // Show a list of available groups:
            ViewBag.GroupsList = new SelectList(this.GroupManager.Groups, "Id", "Name");
            var applicationUser = new ApplicationUser();
            applicationUser.HealthProfessionals = new List<HealthProfessional>();
            PopulateAssignedHealthProfessionals(applicationUser);
            return View();
        }


        [HttpPost]
        public async Task<ActionResult> Create([Bind(Exclude = "ProfilePicture")]RegisterViewModel userViewModel, ApplicationUser applicationUser, string[] selectedHealthProfessionals, params string[] selectedGroups)
        {
            if (selectedHealthProfessionals != null)
            {
                applicationUser.HealthProfessionals = new List<HealthProfessional>();
                foreach (var healthProfessional in selectedHealthProfessionals)
                {
                    var healthProfessionalToAdd = db.HealthProfessionals.Find(int.Parse(healthProfessional));
                    applicationUser.HealthProfessionals.Add(healthProfessionalToAdd);
                }
            }
            if (ModelState.IsValid)
            {
                // To convert the user uploaded Photo as Byte Array before save to DB
                byte[] imageData = null;
                if (Request.Files.Count > 0)
                {
                    HttpPostedFileBase poImgFile = Request.Files["UserPhoto"];

                    using (var binary = new BinaryReader(poImgFile.InputStream))
                    {
                        imageData = binary.ReadBytes(poImgFile.ContentLength);
                    }
                }

                var user = new ApplicationUser
                {
                    UserName = userViewModel.Email,
                    FirstName = userViewModel.FirstName,
                    LastName = userViewModel.LastName,
                    Position = userViewModel.Position,
                    DepartmentID = userViewModel.DepartmentID,
                    SuperiorID = userViewModel.SuperiorID,
                    OfficeNumber = userViewModel.OfficeNumber,
                    CellNumber = userViewModel.CellNumber,
                    Email = userViewModel.Email
                };

                //Here we pass the byte array to user context to store in db
                user.ProfilePicture = imageData;

                var adminresult = await UserManager
                    .CreateAsync(user, userViewModel.Password);

                //Add User to the selected Groups 
                if (adminresult.Succeeded)
                {
                    if (selectedGroups != null)
                    {
                        selectedGroups = selectedGroups ?? new string[] { };
                        await this.GroupManager
                            .SetUserGroupsAsync(user.Id, selectedGroups);
                    }
                    return RedirectToAction("Users");
                }
            }
            ViewBag.Groups = new SelectList(await RoleManager.Roles.ToListAsync(), "Id", "Name");
            PopulateDepartmentsDropDownList(userViewModel.DepartmentID);
            PopulateSuperiorsDropDownList(userViewModel.SuperiorID);
            PopulateAssignedHealthProfessionals(applicationUser);
            return View(applicationUser);
        }

private void PopulateAssignedHealthProfessionals(ApplicationUser applicationUser)
        {
            var allHealthProfessionals = db.HealthProfessionals;
            var userHealthProfessionals = new HashSet<int>(applicationUser.HealthProfessionals.Select(i => i.HealthProfessionalID));
            var viewModel = new List<AssignedHealthProfessionals>();
            foreach (var healthProfessional in allHealthProfessionals)
            {
                viewModel.Add(new AssignedHealthProfessionals
                {
                    HealthProfessionalID = healthProfessional.HealthProfessionalID,
                    HealthProfessionalName = healthProfessional.Name,
                    HealthProfessionalSurname = healthProfessional.Surname,
                    Assigned = userHealthProfessionals.Contains(healthProfessional.HealthProfessionalID)
                });
            }
            ViewBag.HealthProfessionals = viewModel;
        } 

这是我的创建视图:

@model MyApp.Models.RegisterViewModel

@{
    ViewBag.Title = "Create User";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<link href="@Url.Content("~/Content/CSS/dropify.min.css")" rel="stylesheet" type="text/css" />

<div class="m-grid__item m-grid__item--fluid m-wrapper">
    <div class="m-subheader ">
        <div class="d-flex align-items-center">
            <div class="mr-auto">
                <h3 class="m-subheader__title m-subheader__title--separator">
                    Add User
                </h3>
                <ul class="m-subheader__breadcrumbs m-nav m-nav--inline">
                    <li class="m-nav__item m-nav__item--home">
                        <a href="@Url.Action("Dashboard","Home")" class="m-nav__link m-nav__link--icon">
                            <i class="m-nav__link-icon la la-home"></i>
                        </a>
                    </li>
                    <li class="m-nav__separator">
                        -
                    </li>
                    <li class="m-nav__item">
                        <a href="@Url.Action("Users","UserManagement")" class="m-nav__link">
                            <span class="m-nav__link-text">
                                Users
                            </span>
                        </a>
                    </li>
                </ul>
            </div>
            <div>
            </div>
        </div>
    </div>

    @using (Html.BeginForm("Create", "UserManagement", FormMethod.Post, new { @class = "m-form m-form--fit m-form--label-align-right", role = "form", enctype = "multipart/form-data" }))
    {
        @Html.AntiForgeryToken()
        <div class="m-content">

            <div class="m-portlet m-portlet--mobile">
                <div class="m-portlet__head">
                    <div class="m-portlet__head-caption">
                        <div class="m-portlet__head-title">
                            <h3 class="m-portlet__head-text">
                                User Details
                            </h3>
                        </div>
                    </div>
                </div>

                <div class="m-portlet__body">
                    <div class="m-form__section m-form__section--first">
                        <div class="row">
                            <div class="col-lg-4">
                                <div class="form-group">
                                    <label>
                                        Email Address
                                    </label>
                                    @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
                                    @Html.ValidationMessageFor(m => m.Email, "", new { @class = "text-danger" })
                                </div>
                            </div>
                            <div class="col-lg-4">
                                <div class="form-group">
                                    <label>
                                        First Name
                                    </label>
                                    @Html.TextBoxFor(m => m.FirstName, new { @class = "form-control" })
                                    @Html.ValidationMessageFor(m => m.FirstName, "", new { @class = "text-danger" })
                                </div>
                            </div>
                            <div class="col-lg-4">
                                <div class="form-group">
                                    <label>
                                        Last Name
                                    </label>
                                    @Html.TextBoxFor(m => m.LastName, new { @class = "form-control" })
                                    @Html.ValidationMessageFor(m => m.LastName, "", new { @class = "text-danger" })
                                </div>
                            </div>
                        </div>
                        <div class="row">
                            <div class="col-lg-4">
                                <div class="form-group">
                                    <label>
                                        Position
                                    </label>
                                    @Html.TextBoxFor(m => m.Position, new { @class = "form-control" })
                                    @Html.ValidationMessageFor(m => m.Position, "", new { @class = "text-danger" })
                                </div>
                            </div>
                            <div class="col-lg-4">
                                <div class="form-group">
                                    <label>
                                        Department
                                    </label>
                                    @Html.DropDownList("DepartmentID", null, "Choose Department", htmlAttributes: new { @class = "form-control" })
                                    @Html.ValidationMessageFor(m => m.DepartmentID, "", new { @class = "text-danger" })
                                </div>
                            </div>
                            <div class="col-lg-4">
                                <div class="form-group">
                                    <label>
                                        Superior
                                    </label>
                                    @Html.DropDownList("SuperiorID", null, "Choose Superior", htmlAttributes: new { @class = "form-control" })
                                    @Html.ValidationMessageFor(m => m.SuperiorID, "", new { @class = "text-danger" })
                                </div>
                            </div>
                        </div>
                        <div class="row">
                            <div class="col-lg-6">
                                <div class="form-group">
                                    <label>
                                        Password
                                    </label>
                                    @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
                                    @Html.ValidationMessageFor(m => m.Password, "", new { @class = "text-danger" })
                                </div>
                            </div>
                            <div class="col-lg-6">
                                <div class="form-group">
                                    <label>
                                        Confirm Password
                                    </label>
                                    @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" })
                                    @Html.ValidationMessageFor(m => m.ConfirmPassword, "", new { @class = "text-danger" })
                                </div>
                            </div>
                        </div>
                        <div class="row">
                            <div class="col-lg-6">
                                <div class="form-group">
                                    <label>
                                        Office Number
                                    </label>
                                    @Html.TextBoxFor(m => m.OfficeNumber, new { @class = "form-control" })
                                    @Html.ValidationMessageFor(m => m.OfficeNumber, "", new { @class = "text-danger" })
                                </div>
                            </div>
                            <div class="col-lg-6">
                                <div class="form-group">
                                    <label>
                                        Cell Number
                                    </label>
                                    @Html.TextBoxFor(m => m.CellNumber, new { @class = "form-control" })
                                    @Html.ValidationMessageFor(m => m.CellNumber, "", new { @class = "text-danger" })
                                </div>
                            </div>
                        </div>
                        <div class="row">
                            <div class="col-lg-6">
                                <div class="form-group">
                                    <label>
                                        User Groups
                                    </label>
                                    <div class="m-checkbox-list">
                                        @foreach (var item in (SelectList)ViewBag.GroupsList)
                                        {
                                            <label class="m-checkbox m-checkbox--success">
                                                <input type="checkbox" name="selectedGroups" value="@item.Value">
                                                @Html.Label(item.Text, new { @class = "control-label" })
                                                <span></span>
                                            </label>
                                        }
                                    </div>
                                </div>
                            </div>
                            <div class="col-lg-6">
                                <div class="form-group">
                                    <label>
                                        Health Professionals
                                    </label>
                                    <div class="m-checkbox-list">
                                        @{
                                            int cnt = 0;
                                            List<MyApp.ViewModels.AssignedHealthProfessionals> healthProfessionals = ViewBag.HealthProfessionals;
                                            foreach (var healthProfessional in healthProfessionals)
                                            {
                                                if (cnt++ % 3 == 0)
                                                {

                                                }
                                                <label class="m-checkbox m-checkbox--success">
                                                    <input type="checkbox" name="selectedHealthProfessionals" value="@healthProfessional.HealthProfessionalID" @(Html.Raw(healthProfessional.Assigned ? "checked=\"checked\"" : ""))>
                                                    @Html.Label(healthProfessional.HealthProfessionalName, new { @class = "control-label" }) @Html.Label(healthProfessional.HealthProfessionalSurname, new { @class = "control-label" })
                                                    <span></span>
                                                </label>
                                            }
                                        }
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="row">
                            <div class="col-lg-12">
                                <div class="form-group">
                                    <label>
                                        Profile Picture
                                    </label>
                                    <input type="file" name="UserPhoto" id="fileUpload" accept=".png,.jpg,.jpeg,.gif,.tif" class="dropify" />
                                </div>
                            </div>
                        </div>
                    </div>
                </div>

            </div>

            <div class="m-portlet__body">

                <!-- Form Actions Start -->

                <div class="m-portlet">

                    <div class="m-portlet__head">
                        <div class="m-portlet__head-caption">
                            <div class="m-portlet__head-title">
                                <h3 class="m-portlet__head-text">
                                    Actions
                                </h3>
                            </div>
                        </div>
                    </div>
                    <div class="m-portlet__foot m-portlet__foot--fit">
                        <div class="m-form__actions">
                            <input type="submit" class="btn btn-accent m-btn m-btn--custom m-btn--icon m-btn--air m-btn--pill" value="Save" />
                            @Html.ActionLink("Cancel", "Users", null, new { @class = "btn m-btn--pill m-btn--air btn-brand m-btn m-btn--custom" })
                        </div>
                    </div>

                </div>

                <!-- Form Actions End -->

            </div>

        </div>

    }

</div>

<script src="@Url.Content("~/Scripts/jquery.min.js")"></script>
<script src="@Url.Content("~/Scripts/dropify.min.js")"></script>

<script>
    $(document).ready(function () {
        // Basic
        $('.dropify').dropify();

        // Translated
        $('.dropify-fr').dropify({
            messages: {
                default: 'Glissez-déposez un fichier ici ou cliquez',
                replace: 'Glissez-déposez un fichier ou cliquez pour remplacer',
                remove: 'Supprimer',
                error: 'Désolé, le fichier trop volumineux'
            }
        });

        // Used events
        var drEvent = $('#input-file-events').dropify();

        drEvent.on('dropify.beforeClear', function (event, element) {
            return confirm("Do you really want to delete \"" + element.file.name + "\" ?");
        });

        drEvent.on('dropify.afterClear', function (event, element) {
            alert('File deleted');
        });

        drEvent.on('dropify.errors', function (event, element) {
            console.log('Has Errors');
        });

        var drDestroy = $('#input-file-to-destroy').dropify();
        drDestroy = drDestroy.data('dropify')
        $('#toggleDropify').on('click', function (e) {
            e.preventDefault();
            if (drDestroy.isDropified()) {
                drDestroy.destroy();
            } else {
                drDestroy.init();
            }
        })
    });
</script> 

这是编辑功能起作用的控制器:

public async Task<ActionResult> Edit(int id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            ApplicationUser applicationUser = db.Users.Include(h => h.HealthProfessionals).Where(h => h.Id == id).Single();
            PopulateAssignedHealthProfessionals(applicationUser);
            var user = await UserManager.FindByIdAsync(id);
            if (user == null)
            {
                return HttpNotFound();
            }

            // Display a list of available Groups:
            var allGroups = this.GroupManager.Groups;
            var userGroups = await this.GroupManager.GetUserGroupsAsync(id);

            var model = new EditUserViewModel()
            {
                Id = user.Id,
                Email = user.Email,
                FirstName = user.FirstName,
                LastName = user.LastName,
                Position = user.Position,
                DepartmentID = user.DepartmentID,
                SuperiorID = user.SuperiorID,
                OfficeNumber = user.OfficeNumber,
                CellNumber = user.CellNumber
            };

            foreach (var group in allGroups)
            {
                var listItem = new SelectListItem()
                {
                    Text = group.Name,
                    Value = group.Id,
                    Selected = userGroups.Any(g => g.Id == group.Id)
                };
                model.GroupsList.Add(listItem);
            }
            PopulateDepartmentsDropDownList(user.DepartmentID);
            PopulateSuperiorsDropDownList(user.SuperiorID);
            return View(model);
        }

        private void PopulateAssignedHealthProfessionals(ApplicationUser applicationUser)
        {
            var allHealthProfessionals = db.HealthProfessionals;
            var userHealthProfessionals = new HashSet<int>(applicationUser.HealthProfessionals.Select(i => i.HealthProfessionalID));
            var viewModel = new List<AssignedHealthProfessionals>();
            foreach (var healthProfessional in allHealthProfessionals)
            {
                viewModel.Add(new AssignedHealthProfessionals
                {
                    HealthProfessionalID = healthProfessional.HealthProfessionalID,
                    HealthProfessionalName = healthProfessional.Name,
                    HealthProfessionalSurname = healthProfessional.Surname,
                    Assigned = userHealthProfessionals.Contains(healthProfessional.HealthProfessionalID)
                });
            }
            ViewBag.HealthProfessionals = viewModel;
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Edit([Bind(Include = "Email,Id,FirstName,LastName,Position,DepartmentID,SuperiorID,OfficeNumber,CellNumber", Exclude = "ProfilePicture")] EditUserViewModel editUser, ApplicationUser applicationUser, int? id, string[] selectedHealthProfessionals, params string[] selectedGroups)
        {
            if (ModelState.IsValid)
            {
                // To convert the user uploaded Photo as Byte Array before save to DB
                byte[] imageData = null;
                if (Request.Files.Count > 0)
                {
                    HttpPostedFileBase poImgFile = Request.Files["UserPhoto"];

                    using (var binary = new BinaryReader(poImgFile.InputStream))
                    {
                        imageData = binary.ReadBytes(poImgFile.ContentLength);
                    }
                }

                var user = await UserManager.FindByIdAsync(editUser.Id);
                if (user == null)
                {
                    return HttpNotFound();
                }

                var applicationUserToUpdate = db.Users.Include(h => h.HealthProfessionals).Where(h => h.Id == id).Single();

                if (TryUpdateModel(applicationUserToUpdate, "",
               new string[] { }))
                {
                    try
                    {
                        UpdateUserHealthProfessionals(selectedHealthProfessionals, applicationUserToUpdate);

                        db.SaveChanges();

                        return RedirectToAction("Users");
                    }
                    catch (RetryLimitExceededException /* dex */)
                    {
                        //Log the error (uncomment dex variable name and add a line here to write a log.
                        ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
                    }
                }
                PopulateAssignedHealthProfessionals(applicationUserToUpdate);

                // Update the User:
                user.UserName = editUser.Email;
                user.Email = editUser.Email;
                user.FirstName = editUser.FirstName;
                user.LastName = editUser.LastName;
                user.Position = editUser.Position;
                user.DepartmentID = editUser.DepartmentID;
                user.SuperiorID = editUser.SuperiorID;
                user.OfficeNumber = editUser.OfficeNumber;
                user.CellNumber = editUser.CellNumber;

                //Here we pass the byte array to user context to store in db
                user.ProfilePicture = imageData;
                await this.UserManager.UpdateAsync(user);

                // Update the Groups:
                selectedGroups = selectedGroups ?? new string[] { };
                await this.GroupManager.SetUserGroupsAsync(user.Id, selectedGroups);
                return RedirectToAction("Users");
            }
            ModelState.AddModelError("", "Something failed.");
            PopulateDepartmentsDropDownList(editUser.DepartmentID);
            PopulateSuperiorsDropDownList(editUser.SuperiorID);
            return View();
        } 

1 个答案:

答案 0 :(得分:0)

方法中的参数有点奇怪。

最好的方法是将用户对象作为参数传递。 https://stackoverflow.com/a/18005264/2114398

要快速修复,您可以通过从方法中删除selectedHealthProfessionals和selectedGroups参数,然后将它们初始化为局部变量来手动更新多选参数

    [HttpPost]
    public async Task<ActionResult> Create([Bind(Exclude = "ProfilePicture")]RegisterViewModel userViewModel, ApplicationUser applicationUser)
    {
        var selectedGroups = (Request.Form["selectedGroups"] ?? "").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
        var selectedHealthProfessionals = (Request.Form["selectedHealthProfessionals"] ?? "").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);

        applicationUser.HealthProfessionals = new List<HealthProfessional>();
        foreach (var healthProfessional in selectedHealthProfessionals)
        {
            var healthProfessionalToAdd = db.HealthProfessionals.Find(int.Parse(healthProfessional));
            applicationUser.HealthProfessionals.Add(healthProfessionalToAdd);
        }
        if (ModelState.IsValid)
        {
        ...