Search code examples
c#ajaxrazor-pagesasp.net-core-2.2form-serialize

Asp.Net Core Razor Page PUT Handler model binder not binding the serialized form from java script on ajax put


I'm trying to serialize the form and put it to server and for some reason the model binding fails to bind the model.

Here is my javascript button click,

$.when(ajaxFormPutAsync(window.userUrls.update, $('#formUserEdit').serialize(), true)).done((response) => {

       });

ajaxFormPutAsync method:

function ajaxFormPutAsync(requestUrl, putData, global) {
    try {
        return $.ajax({
            type: "PUT",
            url: requestUrl,
            async: true,
            global: global,
            headers: {
                "XSRF-TOKEN": $('input[name="__RequestVerificationToken"]').val()
            },
            data: putData,
            error: function (jqXhr, textStatus, errorThrown) {
                console.log(jqXhr);
            }
        });
    } catch (q) {
        ajaxIndicatorStop();
    }

    return false;
};

Here is my form,

<form id="formUserEdit" method="put">
    <div class="form-row">
        <div class="form-group col-md-6">
            <label asp-for="FirstName"></label>
            <input asp-for="FirstName" class="form-control form-control-sm">
            <span asp-validation-for="FirstName" class="text-danger"></span>
        </div>
        <div class="form-group col-md-6">
            <label asp-for="LastName"></label>
            <input asp-for="LastName" class="form-control form-control-sm">
            <span asp-validation-for="LastName" class="text-danger"></span>
        </div>
    </div>
    <div class="form-row">
        <div class="form-group col-md-6">
            <label asp-for="Designation"></label>
            <input asp-for="Designation" class="form-control form-control-sm">
            <span asp-validation-for="Designation" class="text-danger"></span>
        </div>
        <div class="form-group col-md-6">
            <label asp-for="IdentityNumber"></label>
            <input asp-for="IdentityNumber" class="form-control form-control-sm">
            <span asp-validation-for="IdentityNumber" class="text-danger"></span>
        </div>
    </div>
    <input type="hidden" asp-for="Id" />
</form>

Here is my RazorPageHandler,

public async Task<IActionResult> OnPutAsync(
    [FromBody] UserViewModel userViewModel,
    CancellationToken ct)
{
...

Here is my UserViewModel,

    public class UserViewModel
    {
        public Guid Id { get; set; }

        [Required]
        [Display(Name = "First Name")]
        public string FirstName { get; set; }

        [Required]
        [Display(Name = "Last Name")]
        public string LastName { get; set; }

        [Required]
        public string Designation { get; set; }

        [Required]
        [Display(Name = "Identity Number")]
        public string IdentityNumber { get; set; }
    }

the request is hitting my page handler but userViewModel is null always.

Any suggestion on where I'm wrong?

Please assist.


Solution

  • Parameter Binding is very specific in Asp.Net meaning that if you intend to POST data from your front-end, with either ajax or the form itself, you have to make sure that it is in the correct format that your controller action anticipates receiving the data.

    Therefore, since you are submitting your data like this $('#formUserEdit').serialize(), ajax will serialize it as FormData and your controller action should receive it in the same format.

    Solution

    Change controller action from [FromBody] to [FromForm] and that should work.