skip to Main Content

I want to add new item by send form Ajax to controller and then return json response
this is form to submit putting in partial view "_AddSubAccount"

@model EndSubAccountVM

@using Microsoft.AspNetCore.Mvc.Localization

@inject IViewLocalizer localizer

    <form method="post" onsubmit="sendAjax();">
        <!-- Modal -->
        <div class="modal fade rounded-lg shadow" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
            <div class="modal-dialog">
                <div class="modal-content ">
                    <div class="modal-header bg-info text-white d-flex">
                        <h5 class="modal-title font-weight-bold" id="exampleModalLabel"><i class="fas fa-plus-circle"></i>  @localizer["AddSubAccount"]</h5>
                        <button type="button" class="close align-self-start mx-1" data-dismiss="modal" aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                    </div>

                    <div class="modal-body container shadow">

                        <div class="form-inline mt-3">
                            <label class="font-weight-bold text-muted align-self-start mx-1 mb-2">@localizer["AccountNameAR"]</label>
                            <input type="text" asp-for="Name" id="nameAr"
                                   class="form-control w-100 shadow" />
                            <span class="text-danger" asp-validation-for="Name"></span>
                        </div>

                        <div class="form-inline my-3">
                            <label class="font-weight-bold text-muted align-self-start mx-1 mb-2">@localizer["AccountNameEN"]</label>
                            <input type="text" asp-for="NameEN" class="form-control w-100 shadow" id="nameEn" />
                            <span class="text-danger" asp-validation-for="NameEN"></span>
                        </div>
                        <input type="hidden" asp-for="AccountTreeId" value="@ViewBag.mainAccountID" id="mainAcc" />

                    </div>

                    <div class="modal-footer d-flex justify-content-end">
                        <button type="button" class="shadow btn btn-secondary mx-1" data-dismiss="modal"><i class="fas fa-cancel"></i>  @localizer["Cancel"]</button>
                        <button type="submit" class="shadow btn btn-primary mx-1"><i class="fas fa-save"></i>  @localizer["Save"]</button>
                    </div>
                </div>
            </div>
        </div>
    </form>

and this is View which i inject partial view in call "Add"

@model IEnumerable<EndSubAccount>

@using Microsoft.AspNetCore.Mvc.Localization
@using System.Globalization
@using NToastNotify;

@inject IViewLocalizer localizer
@inject IToastNotification toaster


<h3 class="jumbotron p-3 mb-0 bg-primary-cus text-center text-white font-weight-bold border-cus-3 w-75 container">
    <i class="fas fa-list-alt"></i>  @localizer["subAccountFor"]
    @(CultureInfo.CurrentCulture.Name.StartsWith("ar") ? ViewBag.mainAccountAR : ViewBag.mainAccountEN)
</h3>

<div class="w-75 container p-0 my-2">
    <!-- Button trigger modal -->
    <button type="button" class="btn btn-sm btn-primary btn-primary-cus addSubAccount" data-toggle="modal" data-target="#exampleModal">
        <i class="fas fa-plus-circle"></i>  @localizer["addSubAccount"]
    </button>
</div>


<table class="table table-sm table-striped table-hover container w-75 rounded-lg">
    <thead class="text-white font-weight-bold bg-primary-cus">
        <tr>
            <th>@localizer["AccountName"]</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model)
        {
            <tr>
                @if (CultureInfo.CurrentCulture.Name.StartsWith("ar"))
                {
                    <td>@item.Name</td>
                }
                else
                {
                    <td>@item.NameEN</td>
                }
                <td class="d-flex justify-content-end">
                    <a asp-rout-id="@item.Id" asp-action="Edit" class="btn btn-sm btn-outline-info mx-1"><i class="fas fa-pencil-alt"></i> @localizer["Edit"]</a>
                    <a asp-route-id="@item.Id" id="del-btn" class="btn btn-sm btn-danger mx-1"><i class="fas fa-trash-alt"></i> @localizer["Delete"]</a>
                </td>
            </tr>
        }
    </tbody>
</table>

<partial name="_AddSubAccount" model="new EndSubAccountVM()" />

<!--! Template To add row in Table  -->
<div class="d-none" id="template">
    <tr>
        @if (CultureInfo.CurrentCulture.Name.StartsWith("ar"))
        {
            <td>{nameAr}</td>
        }
        else
        {
            <td>{nameEn}</td>
        }
        <td class="d-flex justify-content-end">
            <a asp-rout-id="{id}" asp-action="Edit" class="btn btn-sm btn-outline-info mx-1"><i class="fas fa-pencil-alt"></i> @localizer["Edit"]</a>
            <a asp-route-id="{id}" id="del-btn" class="btn btn-sm btn-danger mx-1"><i class="fas fa-trash-alt"></i> @localizer["Delete"]</a>
        </td>
    </tr>
</div>

@section Scripts{
    @{ await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script>
    function sendAjax() {

            let form = $('form').serialize();
            var row2Append = $('table tbody tr:last');
            var nameAr = $('#nameAr').val();
            var nameEn = $('#nameEn').val();

        $.ajax({
            url: @Url.Action("Add", "EndSubAccount"),
            type: 'post',
            data: form,
            dataType: 'json',
            success: function (response) {

                var accountName = CultureInfo.CurrentCulture.Name.StartsWith("ar") ? response.Name : response.NameEN;
                var data2Add = $('#template').html().replace('{nameAr}', response.Name)
                    .replace('{nameEn}', response.NameEN)
                    .replace('{id}', response.Id);
                row2Append.append(data2Add).fadeIn();
                toaster.success(localizer["accountSaved", ViewBag.AccountName]);
                },
                error: function () {
                    alert({@localizer["someThingError"]});
                }
            //end of Ajax
            });
    }

</script>
}

and this is post action to save item and retrun json

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Add(EndSubAccountVM accountVM)
        {
            var nameArExist = await _context.AccountsTrees.FirstOrDefaultAsync(x => x.Name == accountVM.Name);
            var nameEnExist = await _context.AccountsTrees.FirstOrDefaultAsync(x => x.NameEN == accountVM.NameEN);
            var AccountIdExist = await _context.AccountsTrees.FirstOrDefaultAsync(x => x.Id == accountVM.AccountTreeId);

            // validate Data
            if (nameArExist != null)
            {
                ModelState.AddModelError("Name", _localizer["nameExist"]);
            }
            if (nameEnExist != null)
            {
                ModelState.AddModelError("NameEN", _localizer["nameExist"]);
            }
            if (AccountIdExist == null)
            {
                ModelState.AddModelError("AccountId", _localizer["AccountIdExist"]);
            }
            var accountName = CultureInfo.CurrentCulture.Name.StartsWith("ar")? accountVM.Name : accountVM.NameEN;
            if (!ModelState.IsValid)
            {
                _notify.AddErrorToastMessage(_localizer["accountNotSave", accountName]);
                return new JsonResult(accountVM);
            }

            var account2Add = new EndSubAccount()
            {
                Name = accountVM.Name,
                NameEN = accountVM.NameEN,
                _lastUpdate = DateTime.Now,
                _UserId = Convert.ToInt32(User.FindFirst("UserId").Value),
                AccountTreeId = accountVM.AccountTreeId
            };

            var accountSaved =  CultureInfo.CurrentCulture.Name.StartsWith("ar") ? account2Add.Name : account2Add.NameEN;
            ViewBag.AccountName = accountName;
                    
            await _context.EndSubAccounts.AddAsync(account2Add);
            await _context.SaveChangesAsync();

            return new JsonResult(accountSaved);
        }

when i click on submit it go to action directly without call AJAX so action return response as json in view page not return to AJAX code

so why AJAX Not Work ?

2

Answers


  1. your form is posting back to server before onsubmit="sendAjax();" fires
    so try this :

    $("form").submit(function(e){
        return false;
    });
    

    or :

    $('form').on('submit', function(e){
          e.preventDefault();
      });
    

    further you can remove

    onsubmit="sendAjax();"
    

    from form
    and change

    type="submit"
    

    to

    type="button"
    

    for save button
    and add

    onclick="sendAjax();"
    

    to save button

    Login or Signup to reply.
  2. Firstly,try to remove onsubmit="sendAjax();" and change your button to:

    <button type="button" class="shadow btn btn-primary mx-1" onclick="sendAjax()"><i class="fas fa-save"></i>  @localizer["Save"]</button>
    

    Then the ajax will be called.Since you use [ValidateAntiForgeryToken] in your action,you need to add Antiforgery token to your ajax like this:

        function sendAjax() {
        
                    let form = $('form').serialize();
                    var row2Append = $('table tbody tr:last');
                    var nameAr = $('#nameAr').val();
                    var nameEn = $('#nameEn').val();
        
                $.ajax({
                    url: @Url.Action("Add", "EndSubAccount"),
                    type: 'post',
                    data: form,
                    headers: { "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val() },
                    dataType: 'json',
                    success: function (response) {
        
                        var accountName = CultureInfo.CurrentCulture.Name.StartsWith("ar") ? response.Name : response.NameEN;
                        var data2Add = $('#template').html().replace('{nameAr}', response.Name)
                            .replace('{nameEn}', response.NameEN)
                            .replace('{id}', response.Id);
                        row2Append.append(data2Add).fadeIn();
                        toaster.success(localizer["accountSaved", ViewBag.AccountName]);
                        },
                        error: function () {
                            alert({@localizer["someThingError"]});
                        }
                    //end of Ajax
                    });
    
    
    ----------
    
    
            }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search