根据提交表单视图中的多选输入多次调用控制器方法 [ASP.NET 核心]

Call controller method multiple times based on input in multiselect from view on submitting form [ASP.NET Core]

问题摘要:

我有一个现有的 asp.net 核心应用程序,它从下拉列表中获取 3 个输入(每个允许单个输入),并根据这些值首先验证它们,然后在数据库中添加一条新记录,例如 Table_Abc。例如:

我正在尝试修改它,以便可以从第二个下拉列表中选择多个输入,但在后端,它添加到 Table_Abc= 我选择的输入数,以便所有值的记录保持不变,唯一的区别是第二个下拉列表的不同输入。

前端(VIEW):

视图中的现有代码(例如:demoview.cshtml):

    <div id="newAccess">
        <div>
            <br />
            <form method="post" id="form-submission-id" asp-action="RequestAccessSubmit">
                <div class="form-horizontal">                   
<div class="form-group">
                        <label class="col-md-3 text-left">User Type:</label>
                        <select asp-items="ViewBag.GroupTypes" id="UserTypeID" class="form-control" name="GroupTypeID">
                            <option value="null">--Select User Types--</option>
                        </select>
                    </div>

                    <div class="form-group">
                        <label class="col-md-3 text-left">Application/Business Group:</label>
                        <select class="form-control" asp-items="ViewBag.ContainerSelect" id="BusinessGroup" name="ContainerID" disabled>
                            <option value="null">--Select Business Group--</option>
                        </select>
                    </div>

                    <div class="form-group">
                        <label class="col-md-3 text-left">Requested Permissions:</label>
                        <select asp-items="ViewBag.APSelect" id="RequestedPermission" class="form-control fa-align-left" name="AppPermissionID" disabled>
                            <option value="null">--Select Requested Permission--</option>
                        </select>
                    </div>
                    <div class="form-group">
                        <label class="col-md-3 text-left">Business Justification:</label>
                        <textarea id="Description" name="BusinessJustification" style="width: 40%" rows="4" cols="20" resize="none" class="form-control" placeholder="Provide business justification." required="required" disabled></textarea>
                    </div>

                    </div>


                    <div class="form-group">
                        <div class="col-md-5">
                            <br />
                            <button id="btn-submit-user" type="submit" class="btn btn-success" asp-action="RequestAccessSubmit" disabled>Submit</button>
                            <button id="btn-cancel-request" type="button" class=" btn btn-danger" onclick="redirecttoHome(this); ">Cancel</button>
                        </div>
                    </div>
                </div>
                <br />
            </form>
        </div>
    </div>

在上面,通过更改

中的代码,成功地更改了视图 以在第二个下拉列表中接受多个输入
<select class="form-control" asp-items="ViewBag.ContainerSelect" id="BusinessGroup" name="ContainerID" disabled>

<select class="form-control custom-select" multiple asp-items="ViewBag.ContainerSelect" id="BusinessGroup" name="ContainerID" disabled>

Objective(需要帮助):

为 app/business 组下拉列表中选择的每个值调用方法 RequestAccessSubmit,而其他下拉列表中的值保持不变。

当前流量:

Javascript:

<script type="text/javascript">

        $(function () {
            $('#UserTypeID').on('change', null, null, function (e) {
                getGroupsandApplications(e);
            });
            $('#RequestedPermission').on('change', null, null, function (e) {
                ValidatePermissions(e);
            });
            $('#BusinessGroup').on('change', null, null, function (e) {
                ValidatePermissions(e);
            });
        });

此处 getGroupsandApplications() 仅用于根据第一个下拉列表中的输入填充第二个和第三个下拉列表,因此可以安全地忽略它。至于 ValidatePermissions() javascript 函数,它调用控制器中的 ValidatePermissions() 使用第二个和第三个下拉列表的当前值来验证它们(请注意,此代码仅考虑这两个下拉列表中的一个值,因此 需要修改) -

      function ValidatePermissions(e)
        {
            var businessGroupID = $('#BusinessGroup').val();
            var requestedPermission = $('#RequestedPermission').val();

            if (businessGroupID!='null') {

                $.ajax({
                    url: '@Url.Action("ValidatePermissions")',
                    method: 'GET',
                    cache: false,
                    data: { containerID: businessGroupID, appPermissionID: requestedPermission },
                    success: handleSuccess
                });
            }

        }

控制器:

ValidatePermissions() 方法 -

public JsonResult ValidatePermissions(int containerID, int appPermissionID)
{
    //code to validate containerID and appPermissionID
    var sampleRecord = new sampleModel();
    sampleRecord = _context.Table_Abc
.FirstOrDefault(x => x.UserId.Equals(user.UserID) && x.ContainerId.Equals(containerID) && x.AppPermissionId.Equals(appPermissionID));

return Json(new
            {
                success = true
            });

}

请注意,sampleModel 控制在数据库 Table_Abc 中插入记录所需的值。

RequestAccessSubmit() 方法 -

[HttpPost]
[Authorize]
public async Task<IActionResult> RequestAccessSubmit(sampleModel xyz)
{
   //some code for variable user

   var sampleRecord = new sampleModel();
   sampleRecord = _context.Table_Abc.FirstOrDefault(x => x.UserId.Equals(user.UserID)
                                                                    && x.ContainerId.Equals(xyz.ContainerId)
                                                                    && x.AppPermissionId.Equals(xyz.AppPermissionId)


 if (sampleRecord == null)
            {
                xyz.BusinessJustification = xyz.BusinessJustification;               
                //fills other needed information in the record
                _context.Table_Abc.Add(xyz);
                await _context.SaveChangesAsync();
            }

return RedirectToAction("Index");


}

型号:

public class UserAccess
    {
        public string BusinessJustification { get; set; }
        public int RequestAccessId { get; set; }
        public int AppPermissionId { get; set; }
        public int ContainerId { get; set; }
        public GroupType GroupType { get; set; }
        //rest of the columns in Table_Abc
    }

方法:

修改上述代码,调用控制器中的上述两种方法,以便为不同的 containerId 值插入多条记录

我终于想出了一个成功的解决方案。对此进行优化是最受欢迎的。

控制器:不变

型号:不变

查看: 形式变化 -

  1. 更改自:
    <form method="post" asp-action="RequestAccessSubmit" id="form-submission-id">

至:

    <form method="post" id="form-submission-id">
  1. 更改自:
    <select asp-items="ViewBag.ContainerSelect" id="BusinessGroup" class="form-control custom-select" multiple name="ContainerID" disabled>

至:

    <select asp-items="ViewBag.ContainerSelect" id="BusinessGroup" class="form-control custom-select" multiple disabled>
  1. 更改自:
<button id="btn-submit-user" type="submit" class="btn btn-success" asp-action="RequestAccessSubmit" disabled>Submit</button>                         

<button id="btn-submit-user" type="submit" class="btn btn-success" disabled>Submit</button>

简而言之,我删除了提交按钮与控制器的 RequestAccessSubmit 方法的直接连接,并删除了第二个下拉列表的值到 ContainerID 列。

Javascript 变化:

添加了一个新函数来处理提交按钮的执行:

$("#btn-submit-user").click(function (event) {
            event.preventDefault(); 
            var businessGroupID = $('#BusinessGroup').val();

            for (var i = 0; i < businessGroupID.length; i++) {

                if (businessGroupID[i] != 'null') {

                    var requestObj = {
                        BusinessJustification : $('#Description').val(),
                        GroupTypeId : $('#UserTypeID').val(),
                        AppPermissionId : $('#RequestedPermission').val(),
                        ContainerId : businessGroupID[i]
                    };

                    $.ajax({
                        url: '@Url.Action("RequestAccessSubmit")',
                        type: 'POST',
                        data: { 'requestAccess': requestObj },
                        success: handleSuccess
                    });
                }

            }
        });

将 ValidatePermissions() 脚本方法修改为:

 function ValidatePermissions(e)
        {
            var businessGroupID = $('#BusinessGroup').val();
            var requestedPermission = $('#RequestedPermission').val();

            //validating each selected container id with the selected permission id

            for (var i = 0; i < businessGroupID.length; i++)
            {
                if (businessGroupID[i] != 'null') {
                    $.ajax({
                        url: '@Url.Action("ValidatePermissions")',
                        method: 'GET',
                        cache: false,
                        data: { containerID: businessGroupID[i], appPermissionID: requestedPermission },
                        success: handleSuccess
                    });
                }
            }

        }

我实现此要求的方法是强类型 Model 绑定 View。如果您想保持数据库上下文模型的原样,您可以在您的模型 类 中使用继承。在此示例中,我为下拉列表和列表框设置了硬编码值。您可以根据您的实施定制该要求。所以我开始了:

Model 看起来像:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace SampleMultiSelectListExample.Models
{
    //No touchy as per requirement
    public class UserAccess
    {
        //Assumption: This is your textarea
        public string BusinessJustification { get; set; }
        //This is user type id
        public int RequestAccessId { get; set; }
        //This is requested permission id
        public int AppPermissionId { get; set; }
        //This is application/business group which is a multi select
        public int ContainerId { get; set; }
        //public GroupType GroupType { get; set; }
        //rest of the columns in Table_Abc
    }

    //Make our class for our purpose. More of a viewmodel
    public partial class UserAccessData : UserAccess
    {
        //These two variables are to hold only one value as per  requirement
        public string requestAccessId { get; set; }
        public string appPermissionId { get; set; }

        public MultiSelectList RequestAccessIdList { get; set; }
        public MultiSelectList AppPermissionIdList { get; set; }
        public MultiSelectList ContainerIdList { get; set; }

        //Define multiselect list to capture multiple application/business role
        public List<string> containerIds { get; set; }

        //Define our constructor to get these values
        public UserAccessData()
        {
            this.RequestAccessIdList = GetRequestAccessIdList(null);
            this.AppPermissionIdList = GetAppPermissionIdList(null);
            this.ContainerIdList = GetContainerIdList(null);
        }

        public MultiSelectList GetRequestAccessIdList(string[] selectedValues)
        {
            List<Common> getRequestAccessList = new List<Common>()
            {
                new Common() { ID = 1, Name= "User 1" },
                new Common() { ID = 2, Name= "User 2" },
                new Common() { ID = 3, Name= "User 3" },
                new Common() { ID = 4, Name= "User 4" },
                new Common() { ID = 5, Name= "User 5" },
                new Common() { ID = 6, Name= "User 6" },
                new Common() { ID = 7, Name= "User 7" }
            };

            return new MultiSelectList(getRequestAccessList, "ID", "Name", selectedValues);
        }

        public MultiSelectList GetAppPermissionIdList(string[] selectedValues)
        {
            List<Common> getAppPermissionList = new List<Common>()
            {
                new Common() { ID = 1, Name= "User 1" },
                new Common() { ID = 2, Name= "User 2" },
                new Common() { ID = 3, Name= "User 3" },
                new Common() { ID = 4, Name= "User 4" },
                new Common() { ID = 5, Name= "User 5" }
            };

            return new MultiSelectList(getAppPermissionList, "ID", "Name", selectedValues);
        }

        //This will multi selectable as per our view
        public MultiSelectList GetContainerIdList(string[] selectedValues)
        {
            List<Common> getContainerList = new List<Common>()
            {
                new Common() { ID = 1, Name= "User 1" },
                new Common() { ID = 2, Name= "User 2" },
                new Common() { ID = 3, Name= "User 3" }
            };

            return new MultiSelectList(getContainerList, "ID", "Name", selectedValues);
        }
    }


    //Generic class to match what a select list or dropdown list or combobox or radio box requires
    public class Common
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }
}

Controller 看起来像:

using System;
using Microsoft.AspNetCore.Mvc;
using SampleMultiSelectListExample.Models;

namespace SampleMultiSelectListExample.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            //Here we get our items as required
            //UserAccessData useraccessdata = new UserAccessData();
            //If you are getting your data from a db, you can do something like this
            //useraccessdata.ContainerIdList = GetAllContainerId(null);
            //useraccessdata.RequestAccessIdList = GetAllRequestAccessId(null);
            //useraccessdata.AppPermissionIdList= GetAllAppPermissionIdList(null);

            //Now since I am hardcoding these values, I can directly send my model to the view to render

            return View(new UserAccessData());
        }

        //Just an example implementation of how this would look via a webservice:
        //private MultiSelectList GetAllContainerId(string[] selectedValues)
        //{
        //    //Just an example using HttpClient to call a webservice to get this data.
        //    var client = clientFactory.CreateClient(baseAPIUrl);
        //    var containerIdDTO = httpClient.GetAsync<UserDtoList>(new Uri(new Uri(baseAPIUrl), $"Master/getUserDto").AbsoluteUri).Result;
        //    //return containerIdDTO.data;
        //    List<Common> allContainerIds = new List<Common>();
        //    foreach (var item in containerIdDTO)
        //    {
        //        Common common = new Common();
        //        common.ID = item.id;
        //        common.Name = item.fullName;
        //        allContainerIds.Add(common);
        //    }

        //    return new MultiSelectList(allContainerIds, "ID", "Name", selectedValues);
        //}

        //Now process your selected data as required
        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult ProcessInformation(UserAccessData useraccessdata)
        {
            //Our main model which is untouched
            UserAccess user = new UserAccess();
            user.AppPermissionId = Convert.ToInt32(useraccessdata.appPermissionId);
            user.RequestAccessId = Convert.ToInt32(useraccessdata.requestAccessId);
            user.BusinessJustification = useraccessdata.BusinessJustification;

            //Now for every container list, do your processing
            foreach(var containerid in useraccessdata.containerIds)
            {
                //Insert in your DB here 
                //var insert = CallDBInsert(user);
            }
            return View();
        }
    }
}

View 看起来像:

@using SampleMultiSelectListExample.Models
@model UserAccessData
@{
    ViewData["Title"] = "Home Page";
}
<div class="panel-heading">
    <h2>Sample MultiSelectList Example</h2>
</div>

<div class="row">

    <br />
    <div id="newAccess">
        <div>
            <br />
            @using (Html.BeginForm("ProcessInformation", "Home", FormMethod.Post, new { @id = "form-submission-id", @class = "" }))
            {
                @Html.AntiForgeryToken()
                <div class="form-horizontal">
                    <div class="form-group">
                        <label class="col-md-3 text-left">User Type:</label>
                        @Html.DropDownListFor(m => m.requestAccessId, Model.RequestAccessIdList, new { @id= "UserTypeID", @class = "form-control", placeholder = "Select User Type", @required = "required", @autocomplete = "off" })
                    </div>

                    <div class="form-group">
                        <label class="col-md-3 text-left">Application/Business Group:</label>
                        @Html.ListBoxFor(m => m.containerIds, Model.ContainerIdList, new { @id = "ContainerID", @name = "choices-multiple-remove-button", @class = "form-control", placeholder = "Select Application/Business Group", @required = "required", @autocomplete = "off", @multiple = "multiple" })
                    </div>

                    <div class="form-group">
                        <label class="col-md-3 text-left">Requested Permissions:</label>
                        @Html.DropDownListFor(m => m.appPermissionId, Model.AppPermissionIdList, new { @id = "AppPermissionID", @class = "form-control", placeholder = "Select Requested Permission", @required = "required", @autocomplete = "off" })

                    </div>
                    <div class="form-group">
                        <label class="col-md-3 text-left">Business Justification:</label>
                        @Html.TextAreaFor(m => m.BusinessJustification, new { @id = "Description", @class = "form-control", placeholder = "Provide business justification", @cols="20",@rows="4",@resize="none", @required = "required", @autocomplete = "off" })

                    </div>

                </div>

                <div class="form-group">
                    <div class="col-md-5">
                        <br />
                        <button id="btn-submit-user" type="submit" class="btn btn-success">Submit</button>
                        <button id="btn-cancel-request" type="button" class=" btn btn-danger" onclick="location.href='@Url.Action("Index", "Home")'">Cancel</button>
                    </div>
                </div>
            }
        </div>
        <br />

    </div>
</div>

你可以在我的 GitHub repository.

上找到这个项目

我希望这对有类似需求的人有所帮助。