Отправка модели представления с помощью ajax на контроллер - как это действительно работает? - PullRequest
0 голосов
/ 03 октября 2019

Я не могу понять почему, иногда отправка объекта с помощью ajax работает, а иногда нет. У меня есть пример - все происходит в 1 представлении, где у меня есть 2 компонента вида

1-й - вид компонента вида

@model ShippingViewModel

    <input type="hidden" name="step" value="@ShoppingCartHelper.TokenShipping" />
    <input type="hidden" asp-for="CustomerId" />
    <div class="form-group">
        <label asp-for="FirstName" class="m-1"></label>
        <div><span asp-validation-for="FirstName" class="text-danger"></span></div>
        <input asp-for="FirstName" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="LastName" class="m-1"></label>
        <div><span asp-validation-for="LastName" class="text-danger"></span></div>
        <input asp-for="LastName" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="Email" class="m-1"></label>
        <div><span asp-validation-for="Email" class="text-danger"></span></div>
        <input asp-for="Email" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="Address" class="m-1"></label>
        <div><span asp-validation-for="Address" class="text-danger"></span></div>
        <input asp-for="Address" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="AddressNumber" class="m-1"></label>
        <div><span asp-validation-for="AddressNumber" class="text-danger"></span></div>
        <input asp-for="AddressNumber" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="City" class="m-1"></label>
        <div><span asp-validation-for="City" class="text-danger"></span></div>
        <input asp-for="City" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="ZipCode" class="m-1"></label>
        <div><span asp-validation-for="ZipCode" class="text-danger"></span></div>
        <input asp-for="ZipCode" class="form-control" />
    </div>
    <div class="form-group form-check">
        <input type="checkbox" class="form-check-input" id="isTheSame">
        <label class="form-check-label" for="isTheSame">Czy dane płatnika mają być takie same jak dane wysyłki?</label>
    </div>
    <button class="btn" id="save-shipping">Dalej&nbsp;&nbsp;&nbsp;<i class="fa fa-level-down" aria-hidden="true"></i></button>

    <script type="text/javascript">
    $(document).ready(function () {
        $('#save-shipping').on('click', function () {
            var ShippingViewModel = {
                CustomerId: $('input[name="CustomerId"]').val(),
                FirstName: $('input[name="FirstName"]').val(),
                LastName: $('input[name="LastName"]').val(),
                Email: $('input[name="Email"]').val(),
                Address: $('input[name="Address"]').val(),
                AddressNumber: $('input[name="AddressNumber"]').val(),
                City: $('input[name="City"]').val(),
                ZipCode: $('input[name="ZipCode"]').val(),
                IsTheSame: $('input[id="isTheSame"]').is(':checked'),
            };
            $.ajax({
                type: "POST",
                url: '/koszyk/cs',
                data: JSON.stringify(ShippingViewModel),
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                beforeSend: function (xhr) {
                    xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val());
                },
                error: function (xhr) {
                    if (xhr.status != 200) window.location.href = "/home/error/" + xhr.status;
                },
                complete: function (xhr) {
                    if (xhr.responseText.includes('@ShoppingCartHelper.TokenShipping')) {
                        $('#ShoppingCartCustomerShipping').html(xhr.responseText);
                    } else if (xhr.responseText.includes('@ShoppingCartHelper.TokenBilling')) {
                        $('#ShoppingCartCustomerShipping').hide();
                        $('#ShoppingCartCustomerBilling').html(xhr.responseText);
                    }
                }
            });
        });
    });
    </script>

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

[HttpPost]
[ValidateAntiForgeryToken]
[Route(RouteUrl.ShoppingCart + "/cs")]
public IActionResult Shippping([FromBody] ShippingViewModel svm)

и выше, код работает отлично - я получаю ShippingViewModel

и затем на том же виде у меня есть 2-й компонент вида

2-й - вид компонента вида / тот же подход

@model BillingViewModel

    @if ((Model.BillingSteps != (int)CustomerModel.StepEnum.None) && (Model.BillingSteps == (int)CustomerModel.StepEnum.Shipping))
    {
        @Html.Raw("<div style=\"display:block;\">")
    }
    else
    {
        @Html.Raw("<div style=\"display:none;\">")
    }
    <input type="hidden" value="@ShoppingCartHelper.TokenBilling" />
    <input type="hidden" asp-for="BillingCustomerId" />
    <div class="form-group">
        <label asp-for="BillingFirstName" class="m-1"></label>
        <div><span asp-validation-for="BillingFirstName" class="text-danger"></span></div>
        <input asp-for="BillingFirstName" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="BillingLastName" class="m-1"></label>
        <div><span asp-validation-for="BillingLastName" class="text-danger"></span></div>
        <input asp-for="BillingLastName" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="BillingEmail" class="m-1"></label>
        <div><span asp-validation-for="BillingEmail" class="text-danger"></span></div>
        <input asp-for="BillingEmail" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="BillingAddress" class="m-1"></label>
        <div><span asp-validation-for="BillingAddress" class="text-danger"></span></div>
        <input asp-for="BillingAddress" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="BillingAddressNumber" class="m-1"></label>
        <div><span asp-validation-for="BillingAddressNumber" class="text-danger"></span></div>
        <input asp-for="BillingAddressNumber" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="BillingCity" class="m-1"></label>
        <div><span asp-validation-for="BillingCity" class="text-danger"></span></div>
        <input asp-for="BillingCity" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="BillingZipCode" class="m-1"></label>
        <div><span asp-validation-for="BillingZipCode" class="text-danger"></span></div>
        <input asp-for="BillingZipCode" class="form-control" />
    </div>

    <button class="btn" id="save-billing">Dalej&nbsp;&nbsp;&nbsp;<i class="fa fa-level-down" aria-hidden="true"></i></button>

    <script type="text/javascript">
        $(document).ready(function () {
            $('#save-billing').on('click', function () {
                var BillingViewModel = {
                    BillingCustomerId: $('input[name="BillingCustomerId"]').val(),
                    BillingFirstName: $('input[name="BillingFirstName"]').val(),
                    BillingLastName: $('input[name="BillingLastName"]').val(),
                    BillingEmail: $('input[name="BillingEmail"]').val(),
                    BillingAddress: $('input[name="BillingAddress"]').val(),
                    BillingAddressNumber: $('input[name="BillingAddressNumber"]').val(),
                    BillingCity: $('input[name="BillingCity"]').val(),
                    BillingZipCode: $('input[name="BillingZipCode"]').val(),
                };
                console.log(BillingViewModel);
                $.ajax({
                    type: "POST",
                    url: '/koszyk/cb',
                    data: JSON.stringify(BillingViewModel),
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    beforeSend: function (xhr) {
                        xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val());
                    },
                    error: function (xhr) {
                        if (xhr.status != 200) window.location.href = "/home/error/" + xhr.status;
                    },
                    complete: function (xhr) {
                        if (xhr.responseText.includes('@ShoppingCartHelper.TokenBilling')) {
                            $('#ShoppingCartCustomerBilling').html(xhr.responseText);
                        } else if (xhr.responseText.includes('@ShoppingCartHelper.TokenPayment')) {
                            $('#ShoppingCartCustomerBilling').hide();
                            $('#ShoppingCartCustomerPayment').html(xhr.responseText);
                        }
                    }
                });
            });
        });
    </script>
    @Html.Raw("</div>")

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

[HttpPost]
[ValidateAntiForgeryToken]
[Route(RouteUrl.ShoppingCart + "/cb")]
public IActionResult Billing([FromBody] BillingViewModel bvm)

и вот - яполучение BillingViewModel - null

и я не понимаю WHY первый вызов ajax, отправляющий модель, и второе отправление

Я нашел обходной путь - вставил [FromBody] BillingViewModel bvm я звонил [FromBody] object bvm

и тогда я звоню deserialized bvm - и он работает

Вопрос

Что именно я делаю не так? Оказывается, я не понимаю, как работает AJAX в ядре ASP. Я не вижу ошибок в своем коде.

РЕДАКТИРОВАТЬ: Модель

public int BillingCustomerId { get; set; }
public string BillingFirstName { get; set; }
public string BillingLastName { get; set; }
public string BillingAddress { get; set; }
public string BillingAddressNumber { get; set; }
public string BillingZipCode { get; set; }
public string BillingCity { get; set; }
public string BillingEmail { get; set; }
public int BillingSteps { get; set; }

отправка данных экран отправки данных

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...