简体   繁体   English

基于提交表单[ASP.NET Core]中的multiselect中的输入,多次调用控制器方法

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

Summary of issue: 问题摘要:

I have an existing asp.net core application that takes 3 inputs (single input allowed in each) from dropdown and based on those values first validates them and then adds a new record in a DB in say Table_Abc. 我有一个现有的asp.net核心应用程序,该应用程序从下拉列表中获取3个输入(每个输入中允许单个输入),并基于这些值首先对其进行验证,然后在表Table_Abc中的数据库中添加新记录。 Eg: 例如: 单输入示例 .

I am trying to modify this such that multiple inputs can be selected from the 2nd dropdown but in the backend the number of records it adds to Table_Abc= number of inputs I have selected such that all the values of the records remain same and the only difference are the different inputs from the 2nd dropdown. 我正在尝试对此进行修改,以便可以从第二个下拉列表中选择多个输入,但是在后端,它添加到Table_Abc =我选择的输入数量的记录数使得所有记录值都保持不变,唯一的区别是是第二个下拉列表中的不同输入。

Front end(VIEW): 前端(VIEW):

Existing code in View (eg: demoview.cshtml): 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>

In above, successfully changed the view to take multiple input in 2nd dropdown by changing the code from 在上面,通过更改代码, 成功更改了视图以在第二个下拉菜单中接受多个输入

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

to

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

Objective (help needed): 目标(需要帮助):

Call the method RequestAccessSubmit for each value selected in the app/business group dropdown while the values from other dropdowns remain the same. 为应用程序/业务组下拉列表中选择的每个值调用方法RequestAccessSubmit,而其他下拉列表中的值保持不变。

Current flow: 电流:

Javascript: 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);
            });
        });

Here getGroupsandApplications() is just used to fill the 2nd and 3rd dropdown based on the input in 1st dropdown so that can be safely ignored. 在这里,getGroupsandApplications()仅用于基于第一个下拉列表中的输入来填充第二个和第三个下拉列表,因此可以放心地忽略它。 As for the ValidatePermissions() javascript function, it calls ValidatePermissions() in controller using the current value of 2nd and 3rd dropdown to validate them(note that this code considers only one value in both of these dropdowns and hence needs to be modified ) - 至于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
                });
            }

        }

Controller: 控制器:

ValidatePermissions() method - 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
            });

}

Note that the sampleModel controls the values needed to insert a record in the Table_Abc in the database. 请注意,sampleModel控制在数据库的Table_Abc中插入记录所需的值。

RequestAccessSubmit() method - 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");


}

Model: 模型:

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
    }

Approach: 方法:

To modify above code such that both the above methods in the controller are called such that multiple records can be inserted for the different values of containerId 若要修改上述代码,以便调用控制器中的上述两种方法,以便可以为containerId的不同值插入多个记录

I finally worked out a successful solution. 我终于找到了一个成功的解决方案。 Optimizations to this are most welcome. 最欢迎对此进行优化。

Controller: Unchanged 控制器:不变

Model: Unchanged 型号:不变

View: Changes in form - 视图:表单更改-

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

to: 至:

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

to: 至:

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

to

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

In short, I removed the direct connection of the submit button to RequestAccessSubmit method of controller and removed the value of the 2nd dropdown to the column ContainerID. 简而言之,我删除了提交按钮与控制器的RequestAccessSubmit方法的直接连接,并删除了ContainerID列的第二个下拉菜单的值。

Javascript changes: JavaScript更改:

Added a new function to handle the execution of submit button: 添加了一个新功能来处理Submit按钮的执行:

$("#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
                    });
                }

            }
        });

Modified ValidatePermissions() script method to: 将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
                    });
                }
            }

        }

My approach towards this requirement is a strongly typed Model binding View . 我针对此要求的方法是强类型Model绑定View You can use inheritance in your Model classes if you want to keep your database context model the way it is. 如果要保持数据库上下文模型的原样,则可以在Model类中使用继承。 In this example, I have hard-coded values for my dropdown and listbox. 在此示例中,我的下拉列表和列表框具有硬编码的值。 You can tailor that requirement according to your implementation. 您可以根据自己的实现量身定制该要求。 So here I go: 所以我在这里:

The Model looks like: 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; }
    }
}

The Controller looks like: 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();
        }
    }
}

And the View looks like: 并且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>

You can find this project on my GitHub repository . 您可以在我的GitHub 存储库中找到该项目。

I hope this helps someone who is having a similar requirement. 希望这对有类似要求的人有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从视图中的asp.net中的控制器调用方法 - call method from controller in asp.net button from view Asp.net 视图不调用 controller 方法 - Asp.net view not call controller method 如何从 ASP.NET Core MVC 中的一个控制器调用或返回另一个控制器的视图 - How to call or return the view of another controller from one controller in ASP.NET Core MVC 为什么我的 AJAX 表单从我在 ASP.NET Core 的部分视图中发布多次? - Why is my AJAX form posting mutliple times from my partial view in ASP.NET Core? ASP.NET MVC - 如何从视图中调用 Controller 方法以重定向到多个其他视图? - ASP.NET MVC - How do I Call a Controller Method from within a View to Redirect to Multiple Other Views? ASP.NET Core MVC controller 接收 null 来自 Z2705A83A5A0659CCE34583972 调用的输入参数 - ASP.NET Core MVC controller receives null for input parameter from ajax call ASP.NET Core MVC-从表单到控制器操作的无效输入 - ASP.NET Core MVC - invalid input from form to controller action ASP.Net Core 3.1:控制器方法总是从 HttpPost 调用接收 NULL 参数 - ASP.Net Core 3.1: Controller method always recieves NULL parameter from HttpPost call ASP.NET MVC 4从另一个控制器调用一个控制器方法 - ASP.NET MVC 4 call a controller method from another controller ASP.NET Core Razor Pages多选输入和分页 - ASP.NET Core Razor Pages multiselect input and pagination
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM