当我在 $ajax() 完成处理程序中触发表单提交时出现 400 错误

问题描述 投票:0回答:1

我在 ASP.NET Core Razor Pages 页面上有一个表单。如果我向表单添加提交按钮 (

type="submit"
),表单将按预期正常发布。

如果我将提交按钮更改为常规按钮 (

type="button"
) 并为该按钮添加一个调用
.trigger('submit')
的处理程序,它也会按预期正常发布。

$('#myButton').on('click', function () {
    $('#myForm').trigger('submit');
});

但是,如果我更改处理程序进行如下所示的

$ajax()
调用,并从
done
处理程序中触发表单提交,则会收到 400 错误。

$('#myButton').on('click', function () {
    var $form = $(this).closest('form');

    $.ajax({
        type: 'GET',
        url: '?handler=ValidateProductTransfer',
        contentType: 'application/json',
        dataType: 'json',
        data: { ... },
    })
    .done(function (response) {
        if (response.isSuccess)
            $form.trigger('submit'); // <----- FAILS w/400 error!
        else
            alert(response.error);
    })
    .fail(function (response) {
        alert(response.responseText);
    })
});

我可以通过延迟表单提交来解决上述问题。

.done(function (response) {
    if (response.isSuccess)
        setTimeout(function () {
            $form.trigger('submit'); // <----- OK
        }, 300);
    else
        alert(response.error);
})

显然,在

$ajax().done
处理程序中触发表单提交时存在问题。但我不明白为什么,或者为什么会导致 400 错误。

谁能解释一下这里发生了什么?以及如何解决这个问题而不施加延迟,如果延迟不够的话可能会失败?

更新

如果有帮助,这是我实际的 JavaScript 处理程序。

    $('#product-transfer-submit').on('click', function () {
        disablePopup(true);

        var $form = $(this).closest('form');
        var $modal = $('#transfer-product-modal');
        var $activeTab = $modal.find('a.nav-link.active');
        var targetType = $activeTab.data('type');
        var targetId = $modal.find($activeTab.attr('href') + ' :input').val();
        $modal.find('#TargetType').val(targetType);

        $.ajax({
            type: 'GET',
            url: '?handler=ValidateProductTransfer',
            contentType: 'application/json',
            dataType: 'json',
            data: {
                'sourceId': $modal.find('#SourceId').val(),
                'targetType': targetType,
                'targetId': targetId,
                'productId': $modal.find('#ProductId').val()
            },
        })
        .done(function (response) {
            if (response.isSuccess)
                //setTimeout(function () {
                    $form.trigger('submit');
                //}, 300);
            else
                alert(response.error);
        })
        .fail(function (response) {
            alert(response.responseText);
        })
        .always(function (response) {
            disablePopup(false);
        });
    });

    function disablePopup(disable) {
        $("#transfer-product-modal :input").prop("disabled", disable);
        $("#transfer-product-modal a").prop("disabled", disable);
    }

这是我在浏览器中呈现的完整表单。

<div id="transfer-product-modal" class="modal show" tabindex="-1" role="dialog" aria-modal="true" style="display: block;">
    <form method="post" action="/Transloading/Ships?handler=ProductTransfer" novalidate="novalidate">
        <input type="hidden" data-val="true" data-val-required="The SourceId field is required." id="SourceId" name="SourceId" value="2">
        <input type="hidden" data-val="true" data-val-required="The TargetType field is required." id="TargetType" name="TargetType" value="Ship">
        <div class="modal-dialog" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">Ship 2 : Transfer Product To</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>

                <div class="modal-body">
                    <ul class="nav nav-tabs">
                        <li class="nav-item">
                            <a href="#railcar-content" data-bs-toggle="tab" aria-expanded="false" class="nav-link" data-type="railcar">
                                <span class="d-block d-sm-none"><img src="/images/mdi/calendar.svg" title="Railcar"></span>
                                <span class="d-none d-sm-block">Railcar</span>
                            </a>
                        </li>
                            <li class="nav-item">
                                <a href="#storage-content" data-bs-toggle="tab" aria-expanded="false" class="nav-link" data-type="storage">
                                    <span class="d-block d-sm-none"><img src="/images/mdi/calendar.svg" title="Storage"></span>
                                    <span class="d-none d-sm-block">Storage</span>
                                </a>
                            </li>
                            <li class="nav-item">
                                <a href="#ship-content" data-bs-toggle="tab" aria-expanded="false" class="nav-link active" data-type="ship">
                                    <span class="d-block d-sm-none"><img src="/images/mdi/calendar.svg" title="Ships"></span>
                                    <span class="d-none d-sm-block">Ship</span>
                                </a>
                            </li>
                    </ul>

                    <div class="tab-content mt-3 mb-3">

                        <div id="railcar-content" class="tab-pane">
                            <div class="row">
                                <div class="col-md-12">
                                    <div class="form-group">
                                        <label class="control-label" for="RailcarId">Railcar</label>
                                        <select class="form-select" data-val="true" data-val-required="The Railcar field is required." id="RailcarId" name="RailcarId"><option value="36167">AOKX482582</option>
<option value="36400">AOKX491641</option>
<option value="36399">AOKX497959</option>
<option value="36240">CBFX305181</option>
<option value="36245">TOPX311252</option>
<option value="36193">TOPX311288</option>
<option value="36244">TOPX311390</option>
</select>
                                        <span class="text-danger field-validation-valid" data-valmsg-for="RailcarId" data-valmsg-replace="true"></span>
                                    </div>
                                </div>
                            </div>
                        </div>

                            <div id="storage-content" class="tab-pane">
                                <div class="row">
                                    <div class="col-md-12">
                                        <div class="form-group">
                                            <label class="control-label" for="StorageId">Storage</label>
                                            <select class="form-select" data-val="true" data-val-required="The Storage field is required." id="StorageId" name="StorageId"><option value="15">Test Storage (100 Mesh)</option>
</select>
                                            <span class="text-danger field-validation-valid" data-valmsg-for="StorageId" data-valmsg-replace="true"></span>
                                        </div>
                                    </div>
                                </div>
                            </div>

                            <div id="ship-content" class="tab-pane active">
                                <div class="row">
                                    <div class="col-md-12">
                                        <div class="form-group">
                                            <label class="control-label" for="ShipId">Ship</label>
                                            <select class="form-select" data-val="true" data-val-required="The Ship field is required." id="ShipId" name="ShipId"><option value="1">Ship 1</option>
<option value="2">Ship 2</option>
</select>
                                        <span class="text-danger field-validation-valid" data-valmsg-for="ShipId" data-valmsg-replace="true"></span>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="row">
                        <div class="col-md-12">
                            <div class="mb-3">
                                <label class="control-label" for="ProductId">Product</label>
                                <select class="form-select" data-val="true" data-val-required="The Product field is required." id="ProductId" name="ProductId"><option value="1">100 Mesh</option><option value="18">Butane</option><option value="19">Diesel</option><option value="40">Propane</option></select>
                                <span class="text-danger field-validation-valid" data-valmsg-for="ProductId" data-valmsg-replace="true"></span>
                            </div>
                        </div>
                    </div>
                    <div class="row">
                        <div class="col-md-6">
                            <div class="form-group mb-3">
                                <label class="control-label" for="Quantity">Quantity</label>
                                <input class="form-control" type="text" data-val="true" data-val-number="The field Quantity must be a number." data-val-range="Quantity must be a positive number" data-val-range-max="1000000000" data-val-range-min="0.1" data-val-required="The Quantity field is required." id="Quantity" name="Quantity" value="0">
                                <span class="text-danger field-validation-valid" data-valmsg-for="Quantity" data-valmsg-replace="true"></span>
                            </div>
                        </div>
                        <div class="col-md-6">
                            <div class="form-group mb-3">
                                <label class="control-label" for="Timestamp">Timestamp</label>
                                <input class="form-control" type="datetime-local" data-val="true" data-val-required="The Timestamp field is required." id="Timestamp" name="Timestamp" value="0001-01-01T00:00"><input name="__Invariant" type="hidden" value="Timestamp">
                                <span class="text-danger field-validation-valid" data-valmsg-for="Timestamp" data-valmsg-replace="true"></span>
                            </div>
                        </div>
                    </div>
                    <div class="row">
                        <div class="col-md-12">
                            <div class="form-check form-switch mb-3">
                                <input class="form-check-input" type="checkbox" data-val="true" data-val-required="The Mark source as empty field is required." id="MarkAsEmpty" name="MarkAsEmpty" value="true">
                                <label class=" form-check-label" for="MarkAsEmpty">Mark source as empty</label>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" id="product-transfer-submit" class="btn btn-success">Transfer</button>
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
                </div>
            </div>
        </div>
        <input name="__RequestVerificationToken" type="hidden" value="CfDJ8BlcV1FRqxZOunKbIAf54ZLanzQR8IEs7WCpxJ-3rTLTtnUwgcrJW0eL-Tl3Z_3exdKwVNmoPzo3m644U1W1i1nwO3iJDvZVW6EXTKkrdGHZJPh_QkKWU_6k5wGPNDpDzPwVOAK8p7CmxDE2QzacCwz3rUcnjpXhyrhWhup0xq7e6n50j0vA3TBlBKR2bxfOzA"><input name="MarkAsEmpty" type="hidden" value="false">
    </form>
</div>
javascript jquery ajax
1个回答
0
投票

问题是您的

disablePopup()
函数禁用了表单中的所有输入。

禁用的输入不包含在提交的数据中。超时起作用的原因是它为您的

.always()
回调提供了重新启用输入的机会。

您可以更改延迟回调的顺序,以确保在处理成功或失败之前重新启用输入...

$.ajax({
  url: "",
  method: "GET",
  data: {
    targetType,
    targetId,
    handler: "ValidateProductTransfer",
    sourceId: $modal.find("#SourceId").val(),
    productId: $modal.find("#ProductId").val(),
  },
  dataType: "json",
})
  .always(() => { // 👈 register "always" first
    disablePopup(false);
  })
  .done(({ isSuccess, error }) => {
    if (isSuccess) {
      $form.trigger("submit");
    } else {
      alert(error);
    }
  })
  .fail(({ responseText }) => {
    alert(responseText);
  });

注意一些细微的变化:

  • GET 请求没有内容类型,因为没有内容;数据在查询字符串中发送
  • 为了方便起见,我将文字查询字符串与数据对象组合在一起,并确保所有属性都正确编码
© www.soinside.com 2019 - 2024. All rights reserved.