Я не могу получить данные на свой контроллер без срабатывания триггера дважды

Здравствуйте, я могу получить все данные, но я не могу получить ProductIds, это дает мне значение null в параметре запроса функций обработки. SelectedIds не равен нулю, я могу без проблем получить его в своем действии. Я надеюсь, что кто-то может помочь.

Обновлено:

После некоторой отладки я вижу, что мое действие запускается дважды из-за cshtml. Как вы можете видеть в

 <form class = "form card-pretify" id = "remaxForm" action = "@Url.Action("EmployeeSessionPost","Product")" method = "post" enctype = "multipart/form-data">

Я использую действие как EmployeeSessionPost. Из-за этого мое действие срабатывает дважды. Обычно раньше это было EmployeeSession. Но я вижу, что не могу получить InstructorId и CsvFile с контроллера.

При использовании EmployeeSessionPost в качестве параметра действия в этой строке он срабатывает дважды, в первом триггере он дает мне selectedIds, но не CsvFile и InstructorId. Во втором триггере он дает мне CsvFile и InstructorId, но не selectedIds.

Если я изменю параметр Url.Action с EmployeeSessionPost на EmployeeSession, он даст мне тот же результат, что и первый триггер.

РЕДАКТИРОВАТЬ2:

Я удалил действие формы и изменил тип кнопки на «кнопку». вот изменения, которые я сделал из комментариев. Это предотвращает двойной триггер, но я не могу получить CsvFile и InstructorId, я просто получаю selectedIds, подобные этому. Как я упоминал ранее

<!--begin::Container-->
<div class = "container-fluid">
    <form class = "form card-pretify" id = "remaxForm" method = "post" enctype = "multipart/form-data">


<!--end::Licence-->
                <div class = "card-footer">
                    <button type = "button" class = "btn btn-primary ml-3" id = "btnUpdate">Update</button>
                </div>

У меня все тот же блок сценария

[Authorize]
[HttpPost]
public async Task<IActionResult> EmployeeSessionPost(List<int> selectedIds)
{
    var csvFile = Request.Form.Files["CsvFile"];
    var instructorId = Convert.ToInt32(Request.Form["InstructorId"]);

    if (csvFile != null && csvFile.Length > 0)
    {
        using var stream = new MemoryStream();
        await csvFile.CopyToAsync(stream);
        await MediatrSend(new Services.Product.Queries.SetEmployeeSessionQuery
        {
            ProductIds = selectedIds,
            InstructorId = instructorId,
            CsvFile = csvFile,
        });
    }

    ModelState.AddModelError("CsvFile", "Please select a valid CSV file.");
    //return RedirectToAction("ParticipantList", "Product", new { culture = RouteData.Values["culture"].ToString(), selectedIds = selectedIds });

    return RedirectToAction("EmployeeSession", "Product", new { culture = RouteData.Values["culture"].ToString() });
}

Мой файл запроса

   public class SetEmployeeSessionQuery : IRequest<int>
    {
        public List<int> ProductIds { get; set; }
        public int ProductId { get; set; }
        public int ProductEmployeeId { get; set; }
        public int InstructorId { get; set; }
        public ClaimModel ClaimModel { get; set; }
        public IFormFile CsvFile { get; set; }

    }

    public class SetEmployeeSessionQueryHandler : IRequestHandler<SetEmployeeSessionQuery, int>
    {
        private readonly IProductEmployeeSessionRepository _productEmployeeSessionRepository;
        private readonly IProductEmployeeRepository _productEmployeeRepository;

        public SetEmployeeSessionQueryHandler(IProductEmployeeSessionRepository productEmployeeSessionRepository, IProductEmployeeRepository productEmployeeRepository)
        {
            _productEmployeeSessionRepository = productEmployeeSessionRepository;
            _productEmployeeRepository = productEmployeeRepository;
        }

        public async Task<int> Handle(SetEmployeeSessionQuery request, CancellationToken cancellationToken)
        {
          .
          ..
          ...
          .... goes on

вот мой cshtml

@model Remax.Services.DTOs.EmployeeSessionDTO;
@{
    ViewData["Title"] = "EmployeeSession";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class = "content d-flex flex-column flex-column-fluid" id = "kt_content">
    <!--begin::Entry-->
    <div class = "d-flex flex-column-fluid">
        <!--begin::Container-->
        <div class = "container-fluid">
            <form class = "form card-pretify" id = "remaxForm" action = "@Url.Action("EmployeeSession","Product")" method = "post" enctype = "multipart/form-data">
                <!--begin::Licence-->
                <div class = "card card-custom" data-card = "true" data-card-tooltips = "false">
                    <div class = "card-header">
                        <div class = "card-header-inner" data-card-tool = "toggle">
                            <div class = "card-title">
                                <h3 class = "card-label">@Html.Raw(Localizer["Form"])</h3>
                            </div>
                            <div class = "card-toolbar">
                                <a href = "#" class = "btn btn-icon btn-sm btn-primary mr-1" data-toggle = "tooltip" data-placement = "top" title = "@Localizer["OpenClose"]">
                                    <i class = "ki ki-arrow-down icon-nm"></i>
                                </a>
                            </div>
                        </div>
                    </div>
                    <div class = "card-body">
                        <div class = "form-group row">
                            <div class = "col-lg-4">
                                <label>@Html.Raw(Localizer["Instructor"]) *:</label>
                                <select class = "form-control kt-selectpicker mr-1" data-actions-box = "true" data-live-search = "true" id = "InstructorId" name = "InstructorId">
                                    <option value = "">@Html.Raw(Localizer["Select"])</option>
                                    @foreach (var o in Model.Instructors)
                                    {
                                        <option value = "@(o.InstructorId)">@Html.Raw(o.NameSurname)</option>
                                    }
                                </select>
                            </div>
                            <div class = "col-lg-4">
                                <label>@Html.Raw(Localizer["ZoomFile"]) *:</label>
                                <div class = "custom-file">
                                    <input type = "file" class = "custom-file-input" id = "CsvFile" name = "CsvFile" accept = ".csv">
                                    <label class = "custom-file-label">@Html.Raw(Localizer["ZoomFile"])</label>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <!--begin::Card-->
                <div class = "card card-custom">
                    <div class = "card-header flex-wrap border-0 pt-6 pb-0">
                        <div class = "card-title">
                            <h3 class = "card-label">
                                @Html.Raw(Localizer["Products"])
                            </h3>
                        </div>
                        <div class = "card-toolbar">
                            <!--begin::Button-->
                            <a href = "javascript:;" class = "btn btn btn-light-primary mr-2 f-filter-btn">
                                <i class = "la la-filter"></i>@Html.Raw(Localizer["Filter"])
                            </a>
                            <!--end::Button-->
                        </div>
                    </div>
                    <div class = "card-body">
                        <!--begin::Search Form-->
                        <div class = "mb-7 f-filter-container" id = "searchForm">
                            <div class = "row align-items-center">
                                <div class = "col-lg-12">
                                    <div class = "row align-items-center mt-1">
                                        <div class = "col-md-4 form-group">
                                            <label class = "mr-3 mb-0 d-none d-md-block">@Html.Raw(Localizer["StartDate"]):</label>
                                            <div class = "input-group-prepend">
                                                <select data-filter = "1" class = "form-control kt-selectpicker" data-actions-box = "true" data-live-search = "true" data-selected-text-format = "count>1" id = "Month" name = "Month">
                                                    <option value = "">@Html.Raw(Localizer["Select"])</option>
                                                    @for (byte i = 1; i < 13; i++)
                                                    {
                                                        <option value = "@i">@(i.ToString().PadLeft(2, '0')) - @Html.Raw(Localizer[String.Format("Month{0}", i)])</option>
                                                    }
                                                </select>
                                                <input type = "number" id = "Year" name = "Year" placeholder = "@(Html.Raw(Localizer["Year"]))" class = "form-control ml-1" data-filter = "1" />
                                            </div>
                                        </div>
                                        <div class = "col-md-4 form-group">
                                            <label class = "mr-3 mb-0 d-none d-md-block">@Html.Raw(Localizer["Category"]):</label>
                                            <select data-filter = "1" class = "form-control kt-selectpicker" multiple = "multiple" data-actions-box = "true" data-live-search = "true" data-selected-text-format = "count>1" id = "ProductCategory" name = "ProductCategory">
                                                @for (byte i = 1; i <= 3; i++)
                                                {
                                                    <option selected value = "@i">@Html.Raw(Localizer[String.Format("ProductType{0}", i)])</option>
                                                }
                                            </select>
                                        </div>
                                        <div class = "col-md-4 form-group">
                                            <label class = "mr-3 mb-0 d-none d-md-block">@Html.Raw(Localizer["ProductName"]):</label>
                                            <input type = "text" class = "form-control" id = "ProductName" name = "ProductName" placeholder = "@Html.Raw(Localizer["ProductName"])" data-filter = "1" />
                                        </div>
                                    </div>
                                    <div class = "row justify-content-end mt-3">
                                        <div class = "col-md-4 form-group text-right">
                                            <label class = "mr-3 mb-0 d-none d-md-block">&nbsp;</label>
                                            <a href = "javascript:;" class = "btn btn-danger px-6 font-weight-bold" id = "ktSearch">
                                                <i class = "fa fa-search icon-nm"></i>
                                                <span>@Html.Raw(Localizer["Search"])</span>
                                            </a>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <!--end::Search Form-->
                        <!--begin: Datatable-->
                        <div class = "datatable datatable-bordered datatable-head-custom" id = "kt_datatable" data-url = "@Url.Action("EmployeeSessionList","Product",new { culture=Model.Language})"></div>
                        <!--end: Datatable-->
                    </div>
                </div>
                <!--end::Card-->
                <!--end::Licence-->
                <div class = "card-footer">
                    <button class = "btn btn-primary ml-3" id = "btnUpdate" name = "btnUpdate">@Html.Raw(Localizer["Update"])</button>
                </div>
            </form>
        </div>
        <!--end::Container-->
    </div>
    <!--begin::Entry-->
</div>

<script src = "https://code.jquery.com/jquery-3.6.0.min.js"></script>

@section scripts{
    <script src = "~/assets/js/pages/crud/ktdatatable/base/KtDatatable.js?v=@(AppSettings.Version)"></script>
    <script src = "~/assets/js/pages/crud/ktdatatable/base/KtDatatable_tr.js?v=@(AppSettings.Version)"></script>

    <script src = "~/assets/js/pages/crud/ktdatatable/base/KtDatatable_@(Model.Language.Substring(0,2)).js?v=@(AppSettings.Version)"></script>
    <script src = "~/assets/js/pages/forms/product/productlist.js?v=@(AppSettings.Version)"></script>

    <script src = "~/assets/js/pages/crud/ktdatatable/base/KtDatatable.min.js?v=@(AppSettings.Version)"></script>
    <script src = "~/assets/js/pages/crud/ktdatatable/base/KtDatatable_@(Model.Language.Substring(0,2)).min.js?v=@(AppSettings.Version)"></script>

    <script>
        var remaxTableScroll = true;
        $.checkboxSingleClick = function () { };
        var selectedIds = [];

        var datatableCols = [
            {
                selector: true,
                field: 'Id',
                title: '@Html.Raw(Localizer["Code"])',
                width: 35,
            },
            {
                field: 'ProductName',
                title: '@Html.Raw(Localizer["Product"])',
                width: 235,
            },
            {
                field: 'CategoryName',
                title: '@Html.Raw(Localizer["Category"])',
                width: 150,
            },
            {
                field: 'StartDateStr',
                title: '@Html.Raw(Localizer["StartDate"])',
                sortable: 'desc',
                width: 90,
            },
        ];
        $(document).ready(function () {
            datatable.on('datatable-on-check',
                function (e, args) {
                    $.each(args, function (i, a) {
                        if (selectedIds.indexOf(a) == -1)
                            selectedIds.push(a);
                    })
                    if (selectedIds.length > 0)
                        $('#setMultiple').show();
                    console.info(selectedIds);
                });
            datatable.on('datatable-on-uncheck',
                function (e, args) {
                    $.each(args, function (i, a) {
                        selectedIds.pop(a);
                    })
                    if (selectedIds.length == 0)
                        $('#setMultiple').hide();
                    console.info(selectedIds);
                });
            $('#btnUpdate').on('click', function () {
                $.ajax({
                    type: "POST",
                    dataType: 'json',
                    cache: false,
                    url: '@Url.Action("EmployeeSessionPost", "Product")',
                    cache: false,
                    data: {
                        selectedIds: selectedIds
                    },
                    success: function (data) {
                    }, async: true,
                });
            });
        });

    </script>
}

Вы отправляете форму с помощью jQuery, а также используете действие отправки формы. Вот почему вы видите две отправки. Измените свою кнопку на <button type=button" class = "btn btn-primary ml-3" id = "btnUpdate".... ИЛИ удалите обработчик события jQuery onClick. Постарайтесь сделать свой код настолько простым, насколько это возможно. Если бы это был я, я бы удалил код jQuery и сохранил действие отправки формы.

Rosdi Kasim 18.04.2023 16:20

Вот немного информации о типе кнопки: html.com/attributes/button-type

Rosdi Kasim 18.04.2023 16:24

Я понимаю, это выглядит хорошим использованием. Но если я удалю функцию кнопки jquery, я не смогу получить свои selectedIds. Это просто для получения selectedIds. Если я удалю этот блок кода, я смогу легко получить данные CsvFile и InstructorId, но не selectedIds. Я надеюсь, что вы также можете дать мне предложение по этому поводу

Onur Serbes 18.04.2023 16:30

Затем удалите действие формы и измените тип кнопки на «кнопку». Поэтому, когда вы нажимаете «Обновить», только jQuery будет отправлять форму.

Rosdi Kasim 18.04.2023 17:04

У меня все тот же ответ после того, как я это сделал, можете ли вы проверить РЕДАКТИРОВАТЬ 2

Onur Serbes 18.04.2023 17:28

Если это EDIT не реализовано правильно, можете ли вы изменить код cshtml и опубликовать его как ответ, пожалуйста? Мне лучше понять свою ошибку.

Onur Serbes 18.04.2023 17:36

Кажется, вы решили проблему двойной публикации. Для csv/structorId это связано с вашим javascript. Упростите свой js до самого базового уровня, чтобы воспроизвести проблему. Вот как вы учитесь программировать.

Rosdi Kasim 18.04.2023 17:55

Спасибо за ваши комментарии, я исправил проблему и поделился решением в разделе ответов. Вы можете проверить это отсюда

Onur Serbes 19.04.2023 12:17
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
8
58
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Спасибо за все комментарии, вот мое решение. Вместо того, чтобы публиковать отдельно (как форму, так и ajax), я хотел собрать все данные в форме и получить данные из одного и того же FormData через ajax. Вот измененный код

контроллер/действие

[Authorize]
        [HttpPost]
        public async Task<IActionResult> EmployeeSessionPost()
        {

            var csvFile = Request.Form.Files.GetFile("CsvFile");
            var instructorId = int.Parse(Request.Form["InstructorId"]);
            var selectedIds = Request.Form["SelectedIds"].ToString().Split(',').Select(int.Parse).ToList();

            if (csvFile != null && csvFile.Length > 0)
            {
                using var stream = new MemoryStream();
                await csvFile.CopyToAsync(stream);
                await MediatrSend(new Services.Product.Queries.SetEmployeeSessionQuery
                {
                    ProductIds = selectedIds,
                    InstructorId = instructorId,
                    CsvFile = csvFile,
                });
            }

            ModelState.AddModelError("CsvFile", "Please select a valid CSV file.");
            //return RedirectToAction("ParticipantList", "Product", new { culture = RouteData.Values["culture"].ToString(), selectedIds = selectedIds });
            return RedirectToAction("EmployeeSession", "Product", new { culture = RouteData.Values["culture"].ToString()});
        }

cshtml

<form class = "form card-pretify" id = "remaxForm" action = "@Url.Action("EmployeeSessionPost","Product")" method = "post" enctype = "multipart/form-data">


 <div class = "card-footer">
                    <button type = "button" class = "btn btn-primary ml-3" id = "btnUpdate" name = "btnUpdate">@Html.Raw(Localizer["Update"])</button>
                </div>


<script>
        var remaxTableScroll = true;
        $.checkboxSingleClick = function () { };

        var selectedIds = [];
        var formdata = new FormData();

        $(document).ready(function () {
            datatable.on('datatable-on-check',
                function (e, args) {
                    $.each(args, function (i, a) {
                        if (selectedIds.indexOf(a) == -1)
                            selectedIds.push(a);
                    })
                    if (selectedIds.length > 0)
                        $('#setMultiple').show();
                    console.info(selectedIds);
                });
            datatable.on('datatable-on-uncheck',
                function (e, args) {
                    $.each(args, function (i, a) {
                        selectedIds.splice(selectedIds.indexOf(a), 1);
                    })
                    if (selectedIds.length == 0)
                        $('#setMultiple').hide();
                    console.info(selectedIds);
                });

            $('#btnUpdate').on('click', function () {

                var csvFile = $('#CsvFile').prop('files')[0];
                var instructorId = $('#InstructorId').val();

                formdata.append('CsvFile', csvFile);
                formdata.append('InstructorId', instructorId);
                formdata.append('SelectedIds', selectedIds)

                $.ajax({
                    type: "POST",
                    dataType: 'json',
                    cache: false,
                    url: '@Url.Action("EmployeeSessionPost", "Product")',
                    data: formdata,
                    processData: false,
                    contentType: false,
                    success: function (data) {
                        console.info(data);
                    },
                    error: function (xhr, status, error) {
                        console.info(xhr.responseText);
                    }
                });
            });
        });
    </script>

Если у вас есть лучшее решение, чтобы исправить это, или какие-либо советы по улучшению этой реализации, пожалуйста, поделитесь со мной в комментариях.

Onur Serbes 19.04.2023 12:18

Другие вопросы по теме