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">×</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
your form is posting back to server before onsubmit="sendAjax();" fires
so try this :
or :
further you can remove
from form
and change
to
for save button
and add
to save button
Firstly,try to remove
onsubmit="sendAjax();"
and change your button to:Then the ajax will be called.Since you use
[ValidateAntiForgeryToken]
in your action,you need to add Antiforgery token to your ajax like this: