Search code examples
c#asp.net-mvcajax.beginform

Ajax.BeginForm sends null values to controller action ASP.NET MVC


I have a partial view that contains an ajax form in asp.net MVC and has a view model with two different models. One of the models is for fetching summary information and another is for submitting a form to an action.

when I try to submit my data to action from my ajax form, I face with null values.

Here is my action code in AccountController

    [Authorize]
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<JsonResult> ChangePassword(ChangePasswordViewModel model)
    {
        var CurrentUser = GetCurrentUser();
        if (ModelState.IsValid)
        {
            bool isOldPasswordTrue = await UserManager.CheckPasswordAsync(CurrentUser, model.CurrentPassword);
            if (!isOldPasswordTrue)
            {
                return Json(new { result = "error", message = "رمز فعلی صحیح نمی باشد." }, JsonRequestBehavior.AllowGet);
            }
            var Result = await UserManager.ChangePasswordAsync(CurrentUser.Id, model.CurrentPassword, model.NewPassword);
            if(Result != IdentityResult.Success)
            {
                return Json(new { result = "error", message = "خطا در تغییر رمز عبور." }, JsonRequestBehavior.AllowGet);
            }
            return Json(new { result = "success", message = "رمز عبور با موفقیت تغییر کرد. صفحه به صورت خودکار بارگذاری خواهد شد." }, JsonRequestBehavior.AllowGet);
        }
        return Json(model);
    }

here is my Partial View

@model iran_pcj.Models.UserInformationViewModel

<div class="myAccount-profile">
    <div class="row align-items-center">
        <div class="col-lg-4 col-md-5">
            <div class="profile-image">
                @if (Model.CurrentUser.ImagePath == null)
                {
                    if (Model.CurrentUser.Gender == Gender.Male || Model.CurrentUser.Gender == Gender.Other)
                    {
                        <img src="~/Content/img/user_images/default_male.jpg" alt="image">
                    }
                    else
                    {
                        <img src="~/Content/img/user_images/default_female.jpg" alt="image">
                    }
                }
                else
                {
                    <img src="~/Content/img/user_images/@Model.CurrentUser.ImagePath" alt="image">
                }
            </div>
        </div>

        <div class="col-lg-8 col-md-7">
            <div class="profile-content">
                <h3>@Model.CurrentUser.Firstname @Model.CurrentUser.LastName</h3>
                <p>@Model.CurrentUser.Title</p>

                <ul class="contact-info">
                    <li><i class='bx bx-envelope'></i> @Model.CurrentUser.Email</li>
                    <li><i class='bx bx-phone'></i> @Model.CurrentUser.PhoneNumber</li>
                    @if (Model.CurrentUser.Website != null)
                    {
                        <li><i class="bx bx-world"></i> <a href="@Model.CurrentUser.Website" target="_blank">@Model.CurrentUser.Website</a></li>
                    }
                </ul>
                <ul class="social">
                    @if (Model.CurrentUser.Facebook != null)
                    {
                        <li><a href="#" class="d-block" target="_blank"><i class='bx bxl-facebook'></i></a></li>
                    }
                    @if (Model.CurrentUser.Twitter != null)
                    {
                        <li><a href="#" class="d-block" target="_blank"><i class='bx bxl-twitter'></i></a></li>
                    }
                    @if (Model.CurrentUser.Instagram != null)
                    {
                        <li><a href="https://www.instagram.com/@Model.CurrentUser.Instagram" class="d-block" target="_blank"><i class='bx bxl-instagram'></i></a></li>
                    }
                    @if (Model.CurrentUser.Linkedin != null)
                    {
                        <li><a href="https://www.linkedin.com/in/@Model.CurrentUser.Linkedin" class="d-block" target="_blank"><i class='bx bxl-linkedin'></i></a></li>
                    }
                </ul>

                <a href="@Url.Action("ChangeAvatar", "Account")" class="btn btn-outline-primary"><i class="bx bx-image"></i> ویرایش تصویر</a>
                <a href="#" class="btn btn-outline-success" id="ChangePassword"><i class="bx bx-lock-open"></i> تفییر رمز</a>
                <a href="@Url.Action("Logout", "Account")" class="btn btn-outline-danger"><i class="bx bx-log-out"></i> خروج</a>
            </div>
        </div>
    </div>
</div>
<div class="modal fade" id="AppModal" tabindex="-1" role="dialog" aria-labelledby="AppModallabel" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="AppModallabel"><i class="bx bx-lock-open"></i> تغییر رمز عبور</h5>
            </div>
            <div class="modal-body" id="modal-container">
                <div id="changepass">
                    @using (Ajax.BeginForm("ChangePassword", "Account", new { CurrentPassword = Model.ChangePassword.CurrentPassword, NewPassword = Model.ChangePassword.NewPassword, NewPasswordConfirmation = Model.ChangePassword.NewPasswordConfirmation }, new AjaxOptions
                    {
                        HttpMethod = "POST",
                        OnSuccess = "ChangePasswordSuccess",
                        OnFailure = "ChangePasswordFailure"
                    }, new { @id = "changePassForm" }))
                    {
                        @Html.AntiForgeryToken()

                        <div class="form-horizontal">
                            <div class="form-group">
                                @Html.LabelFor(model => model.ChangePassword.CurrentPassword, htmlAttributes: new { @class = "control-label col-md-12" })
                                <div class="col-md-12">
                                    @Html.EditorFor(model => model.ChangePassword.CurrentPassword, new { htmlAttributes = new { @class = "form-control" } })
                                    @Html.ValidationMessageFor(model => model.ChangePassword.CurrentPassword, "", new { @class = "text-danger" })
                                </div>
                            </div>

                            <div class="form-group">
                                @Html.LabelFor(model => model.ChangePassword.NewPassword, htmlAttributes: new { @class = "control-label col-md-12" })
                                <div class="col-md-12">
                                    @Html.EditorFor(model => model.ChangePassword.NewPassword, new { htmlAttributes = new { @class = "form-control" } })
                                    @Html.ValidationMessageFor(model => model.ChangePassword.NewPassword, "", new { @class = "text-danger" })
                                </div>
                            </div>

                            <div class="form-group">
                                @Html.LabelFor(model => model.ChangePassword.NewPasswordConfirmation, htmlAttributes: new { @class = "control-label col-md-12" })
                                <div class="col-md-12">
                                    @Html.EditorFor(model => model.ChangePassword.NewPasswordConfirmation, new { htmlAttributes = new { @class = "form-control" } })
                                    @Html.ValidationMessageFor(model => model.ChangePassword.NewPasswordConfirmation, "", new { @class = "text-danger" })
                                </div>
                            </div>
                        </div>
                    }
                </div>
                <div class="progress" style="height: 1px;visibility:hidden">
                    <div class="progress-bar" role="progressbar" style="width: 0%;" aria-valuemin="0" aria-valuemax="100"></div>
                </div>
            </div>
            <div class="modal-footer">
                <button type="submit" id="ChangPassSubmit" class="btn btn-outline-primary"><i class="bx bx-send"></i> ارسال</button>
                <button type="button" class="btn btn-outline-danger" data-dismiss="modal" id="recoveryCancel"><i class="bx bx-x"></i> انصراف</button>
            </div>
        </div>
    </div>
</div>

and here is my view models

UserInformationViewModel

public class UserInformationViewModel
    {
        public AppUser CurrentUser { get; set; }
        public ChangePasswordViewModel ChangePassword { get; set; }
    }

ChangePasswordViewModel

public class ChangePasswordViewModel
    {
        [Required(ErrorMessage = "{0} نمی تواند خالی باشد")]
        [DataType(DataType.Password)]
        [Display(Name = "کلمه عبور فعلی")]
        public string CurrentPassword { get; set; }

        [Required(ErrorMessage = "{0} نمی تواند خالی باشد")]
        [DataType(DataType.Password)]
        [Display(Name = "کلمه عبور جدید")]
        public string NewPassword { get; set; }

        [Required(ErrorMessage = "{0} نمی تواند خالی باشد")]
        [DataType(DataType.Password)]
        [Display(Name = "تکرار کلمه عبور")]
        [System.ComponentModel.DataAnnotations.Compare("NewPassword", ErrorMessage = "رمز عبور با تکرارش همخوانی ندارد.")]
        public string NewPasswordConfirmation { get; set; }
    }

I don't see anything wrong in my code. Maybe it causes from tiredness and I hope you to help me. Tnx


Solution

  • I found this question issue.

    As I use view model that contains two view models so I should rename my inputs.

    In this case when I used the above code data sent to server like this

    __RequestVerificationToken: VLBnD4tC7ih5q9FAtVM9b-4-7lLbDSVhgeKh8Z-eJGfOoXOT96kiwd24SMAkzuRF70OH-5fr4NWeXl1hA6xKfO81llCUOTcIwZtP_bDbCutt4VM9RfPteMmRj9JlitMgLhxk3S_PmMH2YkfxOECRJA2
    ChangePassword.CurrentPassword: 123456789
    ChangePassword.NewPassword: 123456
    ChangePassword.NewPasswordConfirmation: 123456
    X-Requested-With: XMLHttpRequest
    

    but ChangePassword action accepts CurrentPassword, NewPassword, NewPasswordConfirmation so I change EditFor to PasswordFor and then add Name html attribute to my code as below:

    @Html.PasswordFor(model => model.ChangePassword.CurrentPassword, new { @class = "form-control", Name = "CurrentPassword" })
    

    the other field are repeated like above.

    hope this useful for all