AJAX Post Request with Multiple Properties and Files ASP.NET Core - ajax

I am trying to pass an object with multiple properties including user selected files to ASP.NET Core Controller. The POST request passes all properties except the files. How to fix the request to include the files in object? See the code below.
ViewModel:
public class InquiryViewModel
{
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Display(Name = "Upload Documents")]
public IEnumerable<IFormFile> Files { get; set; }
}
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(InquiryViewModel model)
{
try
{
//if (model.Files != null)
//{
// foreach(var file in model.Files)
// await _uploadFileService.PostFileAsync(file, "", 1);
//}
return Json(new { success = true });
}
catch (Exception ex)
{
return Json(new { success = false, message = ex.Message });
}
}
View:
#model InquiryViewModel
#{
ViewData["Title"] = "New Inquiry";
var AllowedExtensions = new string[] { "jpeg", "txt", "jpg", "pdf", "docx", "doc", "csv", "xls", "xlsx", "zip", "png" };
}
<div class="text-center pt-5 bg-logo">
<form id="wizard" autocomplete="false">
#Html.AntiForgeryToken()
<div class="row">
<div class="col-md-12">
<div class="requiredNotice">* Required Field</div>
</div>
</div>
<div class="row">
<div class="form-group col-lg-12 col-md-12 col-sm-12">
<label asp-for="FirstName" class="form-label"></label>
<input asp-for="FirstName" class="form-control" />
</div>
<div class="form-group col-lg-12 col-md-12 col-sm-12">
<label asp-for="LastName" class="form-label"></label>
<input asp-for="LastName" class="form-control" />
</div>
</div>
<div class="row">
<div class="form-group col-lg-12 col-md-12 col-sm-12">
<label asp-for="Files" class="form-label"></label>
<kendo-upload drop-zone=".dropZoneElement" id="files" name="Files">
<async auto-upload="false" chunk-size="12582912" />
<validation allowed-extensions="#AllowedExtensions" max-file-size="12582912" />
</kendo-upload>
<div class="demo-hint">Maximum allowed file size is <strong>12MB</strong>.</div>
</div>
</div>
<input type="button" name="next" class="col-2 submit action-button" value="Submit" />
</form>
</div>
#section Scripts {
<script>
$('input.submit').on('click', function() {
var formData = $('#wizard').serializeArray();
// add files to form data
var upload = $("input[name=Files]").data("kendoUpload");
var files = upload.getFiles();
for (var i = 0; i < files.length; i++) {
formData.push({ name: "Files", value: files[i] });
}
$.ajax({
type: 'POST',
//cache: false,
//contentType: false,
//processData: false,
data: formData,
url: '/Home/Create',
success: function (result) {
if (result.success == true) {
// success
}
else if (result.success == false) {
console.log(result);
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(xhr);
console.log(ajaxOptions);
console.log(thrownError);
}
});
});
</script>
}
As is the form submits only the first and last names no files. If I remove the comment from the cache = false, contentType = false, processData = false, it will not hit the controller at all.

Here is what I changed to make it work.
In the controller I added the [FromForm]
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create([FromForm] InquiryViewModel model)
{
try
{
//if (model.Files != null)
//{
// foreach(var file in model.Files)
// await _uploadFileService.PostFileAsync(file, "", 1);
//}
return Json(new { success = true });
}
catch (Exception ex)
{
return Json(new { success = false, message = ex.Message });
}
}
In the View I replaced kendo uploader with the out of the box html file input with the attribute multiple. In the AJAX I ended up constructing the FormData from scratch. Lastly, I used the contentType: false and processData: false
View
#model InquiryViewModel
#{
ViewData["Title"] = "New Inquiry";
}
<div class="text-center pt-5 bg-logo">
<form id="wizard" autocomplete="false">
#Html.AntiForgeryToken()
<div class="row">
<div class="col-md-12">
<div class="requiredNotice">* Required Field</div>
</div>
</div>
<div class="row">
<div class="form-group col-lg-12 col-md-12 col-sm-12">
<label asp-for="FirstName" class="form-label"></label>
<input asp-for="FirstName" class="form-control" />
</div>
<div class="form-group col-lg-12 col-md-12 col-sm-12">
<label asp-for="LastName" class="form-label"></label>
<input asp-for="LastName" class="form-control" />
</div>
</div>
<div class="row">
<div class="form-group col-lg-12 col-md-12 col-sm-12">
<label asp-for="Files" class="form-label"></label>
<input type="file" name="Files" id="files" class="form-control" multiple maxlength="12582912" />
</div>
</div>
<input type="button" name="next" class="col-2 submit action-button" value="Submit" />
</form>
</div>
#section Scripts {
<script>
$('input.submit').on('click', function() {
var formdata = new FormData();
var files = $("#files").get(0).files;
for (var i = 0; i < files.length; i++) {
formdata.append("Files", files[i]);
}
var otherData = wizard.serializeArray();
$.each(otherData, function (key, input) {
formdata.append(input.name, input.value);
});
$.ajax({
url: '/Home/Create',
type: "POST",
data: formdata,
contentType: false,
processData: false,
success: function (result) {
if (result.success == true) {
// success
}
else if (result.success == false) {
console.log(result);
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(xhr);
console.log(ajaxOptions);
console.log(thrownError);
}
});
});
</script>
}

Related

Asp.Net Core: Send object and parameter to mvc controller using ajax?

I want to send the form data $('#SearchProduct').serialize() with a parameter to the controller...
But whatever I do, only one parameter is sent!!!
Jquery :
const MainProducts = new Products();
MainProducts.LoadProducts(null, 1);
Search_Btn.click(function () {
const Form_Data = SearchProduct.serialize();
MainProducts.LoadProducts(Form_Data, 1);
});
Ajax :
LoadProducts(ObjSearch, page) {
console.log(page);
$.ajax({
url: GetUrlAdmin.Product.AllShowProducts,
type: "Get",
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val());
},
data: { ObjSearch, page },
dataType: 'json',
contentType: 'application/json;charset=utf-8',
success: function (result) {
})
Controller :
public async Task<JsonResult> GetAllShowProducts(ProductSearchViewModel model, int page)
{
var Products = await _admin.GetAllShowProducts(model, page);
return Json(new { data = Products });
}
I also tested the following code, but it was not sent again?
JSON.stringify(ObjSearch, page)
I want to send the form data $('#SearchProduct').serialize() with a
parameter to the controller... But whatever I do, only one parameter
is sent!!!
The issue might be relating to the form elements, when binding the form element and property, we need to bind it via the page model. You can refer to the following sample code (using VS 2022 and Asp.net 6 MVC) and then compare with your code.
Model:
public class Product
{
public int Id { get; set; }
public string Title { get; set; }
public string UrlImage { get; set; }
public string Detail { get; set; }
public decimal Price { get; set; }
}
Home controller:
public IActionResult ProductCreate()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult ProductCreate(Product product)
{
return View();
}
ProductCreate.cshtml:
#model MVCWebApp.Models.Product
#{
ViewData["Title"] = "ProductCreate";
}
<h1>ProductCreate</h1>
<h4>Product</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form id="formprodcreate" asp-action="ProductCreate">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Id" class="control-label"></label>
<input asp-for="Id" class="form-control" />
<span asp-validation-for="Id" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="UrlImage" class="control-label"></label>
<input asp-for="UrlImage" class="form-control" />
<span asp-validation-for="UrlImage" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Detail" class="control-label"></label>
<input asp-for="Detail" class="form-control" />
<span asp-validation-for="Detail" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Price" class="control-label"></label>
<input asp-for="Price" class="form-control" />
<span asp-validation-for="Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
<input type="button" class="btn btn-primary" id="btnFormSubmit" value="Form Ajax Submit"/>
<input type="button" class="btn btn-primary" id="btnSubmit" value="Ajax Submit"/>
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
Js code: [Note] In the Ajax function, there is no need to set the datatype and contenttype.
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script type="text/javascript">
$(function(){
//use the serialize method to serialize the form.
$("#btnFormSubmit").click(function(){
$.ajax({
url: "/Home/ProductCreate",
type: "Post",
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val());
},
data: $('#formprodcreate').serialize(),
success: function (result) {
}
});
});
//create a JS object and get the entered value, then transfer the object to the controller.
$("#btnSubmit").click(function(){
var product = {};
product.Id = $("input[name='Id']").val();
product.Title = $("input[name='Title']").val();
product.UrlImage = $("input[name='UrlImage']").val();
product.Detail = $("input[name='Detail']").val();
product.Price = $("input[name='Price']").val();
$.ajax({
url: "/Home/ProductCreate",
type: "Post",
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val());
},
data: product,
success: function (result) {
}
});
});
});
</script>
}
The output is like this:

Boostrap Modal, browse for photo and submit via ajax to controller with [FromForm] IFormFile file

I want to create a reusable upload feature for images and have created a partialView for this. On click, the partial is loaded via ajax call and the user can browse for an image, the chosen image is displayed and on submit the file should be passed to the controller but the url for submission is always a 404.
Load the Bootstrap Modal
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-toggle="ajax-modal" data-target="#add-contact" data-url="#Url.Action("ShowModalUploadForm", new { Id= Model.Id })">
Add contact
</button>
var placeholderElement = $('#modal-placeholder');
$(document).on('click', 'button[data-toggle="ajax-modal"]', function (event) {
var url = $(this).data('url');
$.get(url).done(function (data) {
placeholderElement.html(data);
placeholderElement.find('.modal').modal('show');
});
});
This works...The issue is when I submit, the URL that is fored appears to not match what the controller is expecting
PartialView (omitted unnecessary portions)
<form id="UploadPhoto" asp-action="UploadPhoto" enctype="multipart/form-data" method="post">
<input name="VolunteerId" id="VolunteerId" type="hidden" value="#Model" />
<div class="col-md-12">
<div class="form-group">
<label>Upload Image</label>
<div class="input-group">
<span class="input-group-btn">
<span class="btn btn-default btn-file">
Browse… <input type="file" id="imgInp">
</span>
</span>
<input type="text" class="form-control" readonly>
</div>
<img id='img-upload' name='img-upload' />
</div>
</div>
</form>
$(document).on('click', '#btnSubmitUpload', function (event) {
event.preventDefault();
var form = $(this).parents('.modal').find('form');
var dataToSend = new FormData(form.get(0));
$.ajax({
url: '#Url.Action("UploadPhoto", "Volunteer", new { Area = "Admin" })',
method: 'post',
data: dataToSend,
processData: false,
contentType: false
}).done(function (data) {
//Do stuff here
}
});
});
$(document).on('change', '.btn-file :file', function () {
var input = $(this),
label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
input.trigger('fileselect', [label]);
});
$(document).on('fileselect', '.btn-file :file', function (event, label) {
var input = $(this).parents('.input-group').find(':text'),
log = label;
if (input.length) {
input.val(log);
} else {
if (log) alert(log);
}
});
$(document).on('change', '#imgInp', function () {
readURL(this);
});
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#img-upload').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
VolunteerController
[HttpPost]
private async void UploadPhoto([FromForm] IFormFile file)
{
//await _storage.SaveBlobAsync("volunteers", file, BlobType.Image);
}
Open the F12 developer tools, where is your misalignment? Or we can also use the FormData object.
View:
#model ImageFileUpload.Models.Human
#{
ViewBag.Title = "SaveData";
}
<h2>SaveData</h2>
<div>
Create New
<br /><br />
<table class="table table-responsive">
<thead>
<tr style="background-color:#333;color:white;">
<th>Human Name</th>
<th>Human Image</th>
<th>Human Phone</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody id="SetHumanList">
<tr id="LoadingStatus"></tr>
</tbody>
</table>
</div>
#using (Html.BeginForm("SaveData", "Human", FormMethod.Post, new { id = "form", enctype = "multipart/form-data" }))
{
<div class="modal fade" id="MyModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
×
<h4 id="ModalTitle"></h4>
</div>
<div class="modal-body">
<fieldset id="SubmitForm">
#Html.HiddenFor(a => a.HumanId, new { #id = "HumId" })
<div class="form-group">
#Html.TextBoxFor(a => a.HumanName, new { #id = "HumName", #class = "form-control", #placeholder = "Name" })
</div>
<div class="form-group">
<input type="file" id="UploadFile" name="Upload" class="form-control w" />
</div>
<div class="form-group">
#Html.TextBoxFor(a => a.HumanPhone, new { #id = "HumPhone", #class = "form-control", #placeholder = "Phone" })
</div>
<div class="form-group">
<button id="SaveRecord" type="button" class="btn btn-warning">Create</button>
</div>
</fieldset>
</div>
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
<script src="~/Scripts/jquery.form.min.js"></script>
#Scripts.Render("~/bundles/jqueryval")
<script>
function AddNewHuman() {
$("#MyModal").modal("show")
}
$("#SaveRecord").click(function () {
var formData = new FormData();
formData.append("Upload", $('#UploadFile')[0].files[0]); //append the image file
var other_data = $('form').serializeArray();
$.each(other_data, function (key, input) { //append other input value
formData.append(input.name, input.value);
});
$.ajax({
type: "POST",
url: "/Human/SaveData",
data: formData,
contentType: false, // Not to set any content header
processData: false, // Not to process data
success: function (result) {
alert("Success");
window.location.href = "/Human/index";
//$("#MyModal").modal("hide"); //this line is unnecessary because the user has been redirect
}
})
});
</script>
}
Result

How to show Validation Summary in a modal form with ajax post method?

I'm beginner in ASP.NET Core MVC. I have a problem in my website code.
My model is User that has some fields, and I wrote a view model based on these fields.
I've written the following code:
My view model: RegisterViewModel:
public class RegisterViewModel
{
[Display(Name = "Username")]
[Required(ErrorMessage = "Enter {0} value please.")]
[MaxLength(20, ErrorMessage = "{0} Shouldn't have more than {1} Characters")]
public string Username { get; set; }
[Display(Name = "Password")]
[Required(ErrorMessage = "Enter {0} value please.")]
[MaxLength(50, ErrorMessage = "{0} Shouldn't have more than {1} Characters")]
public string Password { get; set; }
}
My controller: AccountController:
public class AccountController : Controller
{
private IUser _iuser;
public AccountController(IUser iuser)
{
_iuser = iuser;
}
public IActionResult Register()
{
return View();
}
[HttpPost]
public IActionResult Register(RegisterViewModel register)
{
if (ModelState.IsValid)
{
if (_iuser.isUsernameExist(register.Username))
{
ModelState.AddModelError("UserName", "This User Exists!");
return PartialView(register);
}
else
{
User user = new User()
{
Username = register.Username,
Password = HashGenerators.EncodingPassWithMD5(register.Password),
RoleId = 2,
};
_iuser.AddUser(user);
string TabName = "UserTab";
return Json(new { redirectToUrl = Url.Action("Index", "Profile", new {TabName}) });
}
}
else
{
return PartialView(register);
}
}
}
Register action has a view that has displayed as a modal.
View Register.cshtml:
<div class="row">
<div class="col-md-8 col-md-offset-2">
<hr />
<form asp-action="Register">
<div asp-validation-summary="ModelOnly" class="text-danger text-right"></div>
<div class="form-group">
<input asp-for="Username" class="form-control" , placeholder="username" id="txtUsername"/>
<span asp-validation-for="Username" class="text-danger" id="ValidationSummery"></span>
</div>
<div class="form-group">
<input asp-for="Password" class="form-control" , placeholder="password" id="txtPassword"/>
<span asp-validation-for="Password" class="text-danger text-right" id="ValidationSummery"></span>
</div>
<div class="form-group">
<input type="button" value="Create" onclick='AddUser()' class="btn-red pull-left" />
<button href="#" type="button" onclick='ClearForm()' class="btn-red pull-right"> Clear Form </button>
</div>
</form>
</div>
</div>
Modal code (at the end of above code):
<div id="myModal" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div id="bodyModal" class="modal-body">
</div>
</div>
</div>
</div>
and at the end of view, I have these Ajax scripts:
<script>
function ClearForm() {
$.ajax({
url: "/Account/Register/",
type: "Get",
data: {}
}).done(function (result) {
$('#myModal').modal('show');
$('#bodyModal').html(result);
});
$('#myModal').modal('dispose'); }
</script>
<script>
function AddUser() {
$.ajax({
url: "/Account/Register/",
type: "Post",
data: {
Username: $("#txtUsername").val(),
Password: $("#txtPassword").val(),
},
success: function (response) {
window.location.href = response.redirectToUrl;
}
}).done(function (result) {
$('#myModal').modal('show');
$('#bodyModal').html(result);
});}
</script>
When program is running, the ClearForm button works well, the Create button works well when modelstate is valid. But when modelstate is not valid, it goes to an error page (Hello world!), I see validation errors for 1 second but browser opens an wrong page and doesn't stay on modal for showing validation error.
NOTE: When I delete: ( window.location.href = response.redirectToUrl;) from ajax AddUser function at success part, modal stays open and validation errors displays. But if modelstate is valid, modal stays open but it was empty and destination page(Index/Profile#UserTab) doesn't display.
Please help me, how can I change above code to solve this problem?
I think you can have a new partial view to show the validation message.
Add a hidden input field to the partial view:
<input name="IsValid" type="hidden" value="#ViewData.ModelState.IsValid.ToString()" />
Then in ajax success function determine whether to show the modal or redirect by judging the value of IsValid
A simple demo based on your codes.
Register.cshtml:
#model RegisterViewModel
#{
ViewData["Title"] = "Register";
}
<h1>Register</h1>
<div class="row">
<div class="col-md-8 col-md-offset-2">
<hr />
<form asp-action="Register">
<div asp-validation-summary="ModelOnly" class="text-danger text-right"></div>
<div class="form-group">
<input asp-for="Username" class="form-control" , placeholder="username" id="txtUsername" />
<span asp-validation-for="Username" class="text-danger" id="ValidationSummery"></span>
</div>
<div class="form-group">
<input asp-for="Password" class="form-control" , placeholder="password" id="txtPassword" />
<span asp-validation-for="Password" class="text-danger text-right" id="ValidationSummery"></span>
</div>
<div class="form-group">
<input type="button" value="Create" onclick='AddUser()' class="btn-red pull-left" />
<button href="#" type="button" onclick='ClearForm()' class="btn-red pull-right"> Clear Form </button>
</div>
</form>
</div>
</div>
<div id="myModal" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div id="bodyModal" class="modal-body">
</div>
</div>
</div>
</div>
#section scripts{
<script>
function AddUser() {
$.ajax({
url: "/Account/Register/",
type: "Post",
data: {
Username: $("#txtUsername").val(),
Password: $("#txtPassword").val(),
},
success: function (response) {
$('#bodyModal').html(response);
var isValid = $('body').find('[name="IsValid"]').val() == 'True';
if (!isValid) {
$('#myModal').modal('show');
} else {
window.location.href = "#Url.Action("Index", "Profile")";
}
}
});
}
</script>
}
_Register.cshtml(Partial View):
#model RegisterViewModel
<form asp-action="Register">
<input name="IsValid" type="hidden" value="#ViewData.ModelState.IsValid.ToString()" />
<div asp-validation-summary="ModelOnly" class="text-danger text-right"></div>
<div class="form-group">
<input asp-for="Username" class="form-control" , placeholder="username" id="txtUsername" readonly />
<span asp-validation-for="Username" class="text-danger" id="ValidationSummery"></span>
</div>
<div class="form-group">
<input asp-for="Password" class="form-control" , placeholder="password" id="txtPassword" readonly />
<span asp-validation-for="Password" class="text-danger text-right" id="ValidationSummery"></span>
</div>
</form>
Controller:
public class AccountController : Controller
{
public IActionResult Register()
{
return View();
}
[HttpPost]
public IActionResult Register(RegisterViewModel register)
{
if (ModelState.IsValid)
{
// do some stuff
}
return PartialView("_Register",register);
}
}
Result:
With inspiring help of https://stackoverflow.com/users/11965297/mj1313, I Changed my code like following and my problem is solved entirely...
In controller, I send a parameter(Valid) by ViewBag to my view, to specify ModelState validity status.
[HttpPost]
public IActionResult Register(RegisterViewModel register)
{
if (ModelState.IsValid)
{
if (_iuser.isUsernameExist(register.Username))
{
ViewBag.Valid= "1"; // It's part of my change
ModelState.AddModelError("UserName", "This User Exists!");
return PartialView(register);
}
else
{
User user = new User()
{
Username = register.Username,
Password = HashGenerators.EncodingPassWithMD5(register.Password),
RoleId = 2,
};
_iuser.AddUser(user);
ViewBag.Valid= "0"; // It's part of my change
string TabName = "UserTab";
return Json(new { redirectToUrl = Url.Action("Index", "Profile", new {TabName}) });
}
}
else
{
ViewBag.Valid= "1"; // It's part of my change
return PartialView(register);
}
}
And in My view, I use a hidden input for save ViewBag.
<form asp-action="Register">
<input name="IsValid" type="hidden" value="#ViewBag.Valid" /> #*It's part of my change*#
<div asp-validation-summary="ModelOnly" class="text-danger text-right"></div>
<div class="form-group">
<input asp-for="Username" class="form-control" , placeholder="username"
</div>
.....
</form>
At the end, I change Ajax function, success part:
function AddUser() {
$.ajax({
url: "/Account/Register/",
type: "Post",
data: {
Username: $("#txtUsername").val(),
Password: $("#txtPassword").val(),
},
success: function (response) {
$('#bodyModal').html(response);
var isValid = $('body').find('[name="IsValid"]').val();
if (isValid) {
$('#myModal').modal('show');
} else {
window.location.href = response.redirectToUrl;
}
}
}).done(function (result) {
$('#myModal').modal('show');
$('#bodyModal').html(result);
});}

ajax with return Json return blank page

**Hi I have Login and Register Page in one view.Login controller does not have view. i want to show error message when user enter wrong email and password. but it return blank page with {"Fail"} with url Account/Login
$(document).ready(function () {
$("#alertmessage").hide()
$("#logbut").on("click",function () {
//collect the user data
var data = {};
data.Email = $("#Email").val();
data.Password = $("#Password").val();
var token = $('input[name="__RequestVerificationToken"]').val();
$.ajax({
contentType: "application/json; charset=utf-8",
url: "/Account/Login",
type: "POST",
dataType: "json",
data: {
model: data,
__RequestVerificationToken: token,
},
success: function () {
$("#alertmessage").show()
},
})
})
})
<div class="login-container">
<div class="row">
<div class=" col-md-12 col-sm-12 col-12 login-form-1">
<h2>Login </h2>
<p>Log into your account</p>
#using (Html.BeginForm("Login", "Account", FormMethod.Post))
{
<div id="alertmessage">
<div class=" alert alert-danger">
<span>
Email or Password is incorrect
</span>
</div>
</div>
#Html.AntiForgeryToken()
<div class="form-group col-md-12 col-sm-12 col-12">
<input id="Email" type="text" class="form-control" placeholder="Your Email *" value="" name="Emaillog" />
</div>
<div class="form-group col-md-12 col-sm-12 col-12 ">
<input id="Password" type="password" class="form-control" placeholder="Your Password *" value="" name="Passwordlog" />
</div>
<div class="form-group col-md-12 col-sm-12 col-12">
<input type="submit" class="btnSubmit" value="Login now" id="logbut" />
</div>
<div class="form-group col-md-6 col-sm-6 col-6">
Forget Password?
</div>
}
</div>
</div>
</div>
[HttpGet]
public ActionResult Login()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(string Emaillog,string Passwordlog)
{
string result = "Fail";
User appUser = _context.Users.FirstOrDefault(u => u.Email == Emaillog);
if (appUser != null)
{
if (appUser.Password ==Passwordlog)
{
Session["ActiveUser"] = appUser;
return RedirectToAction("MainAccount");
}
}
return Json(result, JsonRequestBehavior.AllowGet); }
I tried change to JsonResult action but still the same. I don't know where gone wrong. **
Your ajax call is not being called because your submit button is submitting the form and doing a redirect.
Add a event.preventDefault() button click event so that it won't do a normal synchronous POST.
// add e parameter, this is for the event
$("#logbut").on("click",function (e) {
// this is to avoid the form being submitted, and proceed with your script call
e.preventDefault();
// ...
})

Every row is executed twice

I have found a bug - and I haven't found any solution to this.
I have a code in ASP.NET Core (using VSPro 2019 16.5.0):
public IActionResult CreateSubGroup(MyClass model, string returnUrl = null)
{
if (ModelState.CreateMyClassValidation())
{
if (!db.MyClass.Where(x => x.Title == model.Title).Any())
{
ViewData["ReturnUrl"] = returnUrl;
var code = new MyClass { Title = model.Title, IdGroup = model.IdGroup, GroupCode = model.GroupCode};
db.MyClass.Add(code);
var result = db.SaveChanges();
if (result > 0)//if there was no issue (at least one row was changed)
{
this.AddNotification(MessagesHandler.Success, $"Item\"{model.Title}\" was successfully created.");
}
else
{
this.AddNotification(MessagesHandler.Error, $"Item \"{model.Title}\" cannot be created.");
}
}
else
{
this.AddNotification(MessagesHandler.Error, $"Item \"{model.Title}\" already exists.");
}
}
else
{
this.AddNotification(MessagesHandler.Error, $"ErrorMessage.");
}
return RedirectToLocal(returnUrl);
}
Creating of new Item always crashes with unique code exception from DB - During debuging I have found, that every row is executed twice (and I don't know why??) - so also the row db.SaveChanges() is executed twice and that's why I got this exception.
Second bad thing is, that not even the first attempt to save database is not executed (= new Item is not created in DB).
Have you seen this error?
EDIT:
I have found, that it happens only when data are posted from view with JS/AJAX (from modal window)
Here is the code for sending data:
<div class="modal fade" id="ModalWindow" tabindex="-1" role="dialog" aria-labelledby="ModalForm" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<form id="ModalForm" action="" method="post" class="validator">
<div class="modal-body">
<div class="form-group">
<label asp-for="Id"></label>
<input class="form-control" asp-for="Id" value="" readonly data-val="false">
<div class="form-text text-muted small">ID cannot be changed!</div>
</div>
<div class="form-group">
<label asp-for="Title"></label>
<input class="form-control mlfb-create" asp-for="Title" placeholder="Title" value="" autofocus tabindex="#(++tabindex)">
<span class="text-danger small" asp-validation-for="Title"></span>
</div>
<div class="form-group">
<label asp-for="IdGroup"></label>
<select class="selectpicker form-control" asp-for="IdGroup" data-live-search="true" data-style="btn-info" tabindex="#(++tabindex)">
#if (data?.GroupData != null)
{
#foreach (var item in data?.GroupData)
{
<option value="#(item.Id)">#item.Title</option>
}
}
</select>
</div>
<div class="form-group">
<label asp-for="GroupCode"></label>
<input class="form-control mlfb-create" asp-for="GroupCode" placeholder="Title" value="" autofocus tabindex="#(++tabindex)">
<span class="text-danger small" asp-validation-for="GroupCode"></span>
</div>
</div>
<div class="text-center modal-footer">
<button type="submit" class="btn btn-success _modal-buttton-save" tabindex="#(++tabindex)"><i class="fas fa-check mr-2"></i><span>Save</span></button>
<button type="reset" class="btn btn-secondary" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
#section scripts {
<script>
$(function () {
"use strict";
$(document).on('click', '._createSubFormButton', function () {
$('#ModalWindow').modal('show');
$('.modal-title').text('Creating of subgroup');
$('.modal-buttton-save span').text('Create');
$('#ModalForm').attr('action', '/MyCode/CreateSubGroup/?returnurl=' + window.location.href);
});
// Edit form
$(document).on('click', 'tr ._editSubFormButton', function () {
$('#ModalWindow').modal('show');
var $tr = $(this).closest('tr');
var Id = $tr.find('._Id').text();
var Title = $tr.find('._Title').text();
var IdGroup = $tr.find('._IdGroup').text();
var GroupCode = $tr.find('._GroupCode').text();
$('.modal-title').text('Editing of subgroup');
$('#ModalForm').attr('action', '/MyCode/EditSubGroup/' + Id + '?returnurl=' + window.location.href);
$('#Id').val(Id);
$('#Title').val(Title);
$('#GroupCode').val(GroupCode);
});
// form validation reset during closing modal form
$('#ModalWindow').on('hidden.bs.modal', function () {
$(this).find('form').trigger('reset');
$('#IdGroup').load();
$('.form-group .is-invalid').each(function () { $(this).removeClass('is-invalid'); });
$('.form-group .is-valid').each(function () { $(this).removeClass('is-valid'); });
$('.form-text.text-danger').each(function () { $(this).removeClass('text-danger'); });
$('.form-text.text-success').each(function () { $(this).removeClass('text-success'); });
$('.invalid-feedback').each(function () { $(this).remove(); });
});
$(document).on('submit', '#ModalForm', function (e) {
var form = $('#ModalForm');
if (form.valid()) {
console.log(form.serializeArray());
$.ajax({
url: form.attr("action"),
type: form.attr("method"),
data: form.serializeArray()
}).done(function () {
console.log('done');
$tr.find('._Number').text();
var $tr = $(this).closest('tr');
})
.fail(function () {
console.log('fail');
});
$('#ModalWindow').modal('hide');
}
});
error I got:
Have you tried debugging this code? Debugging with setting breakpoints and stepping through the code would help you find what is wrong with this code.

Resources