I am trying to save a ViewModel object from a partial view in a modal, and I get a 404 error when I try to post it. The url is being called, but the ViewModel data isn't being sent. I have been reading similar questions on here and on MSN for hours and nothing I've tried fixes the problem. I took out the repetitive days of the week code for brevity, but I can add them back in if anyone wants a complete working example. Here is the code
EmployeeViewModel
public class EmployeeViewModel
{
public bool Monday { get; set; } = false;
//...bool properties for Tuesday through Sunday
public Employee Employee { get; set; }
}
Employee/ _AddEmployeeModalPartial
@model JSarad_C868_Capstone.ViewModels.EmployeeViewModel
@Html.AntiForgeryToken()
<div id="addEmployee">
<div >
<div >
<div >
<h4 id="addEmpoyeeLabel">Add Employee</h4>
<button type=button data-bs-dismiss="modal">
<span>x</span>
</button>
</div>
<div >
<form action="Add">
<div >
<input asp-for="Employee.Id" />
<input asp-for="Employee.Availability" />
<label asp-for="Employee.Role"></label>
<select asp-for="Employee.Role" >
<option value="Bartender">Bartender</option>
<option value="Server">Server</option>
</select>
<span asp-validation-for="Employee.Role" ></span>
</div>
@*<div >*@
<div >
<label asp-for="Employee.Name"></label>
<input asp-for="Employee.Name" />
<span asp-validation-for="Employee.Name" ></span>
</div>
@* <div >*@
<div >
<label asp-for="Employee.Phone"></label>
<input asp-for="Employee.Phone" />
<span asp-validation-for="Employee.Phone" >
</span>
</div>
@*<div >*@
<div >
<label asp-for="Employee.Email"></label>
<input asp-for="Employee.Email" />
<span asp-validation-for="Employee.Email" >
</span>
</div>
@*<div >*@
<div >
<label asp-for="Employee.Address"></label>
<input asp-for="Employee.Address" />
<span asp-validation-for="Employee.Address" >
</span>
</div>
@* <div >*@
<div >
<label>Availabiliy</label>
</div>
<div >
<div >
<div >
<input asp-for="Monday"
type="checkbox" />
<label asp-for="Monday" ></label>
</div>
<!--...//form check boxes for Tuesday trough Sunday -->
</div>
</div>
</form>
</div>
<div >
<button type="button"
data-bs-dismiss="modal">Cancel</button>
<button type="button"
data-bs-save="modal">Save</button>
</div>
</div>
</div>
</div>
EmployeeController.cs
[HttpGet]
public IActionResult Add()
{
EmployeeViewModel viewModel = new EmployeeViewModel();
return PartialView("_AddEmployeeModalPartial", viewModel); ;
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Add(EmployeeViewModel viewModel) //code never reaches this Action
{
viewModel.Employee.Availability = ConvertDaysToChar(viewModel.Employee.Availability)
if (ModelState.IsValid)
{
_db.Employees.Add(viewModel.Employee);
_db.SaveChanges();
return RedirectToAction("Index");
}
else
{
return PartialView("_AddEmployeeModelPartial", viewModel);
}
}
site.js
$(function () {
var PlaceHolderElement = $('#PlaceHolderHere');
$('button[data-bs-toggle="ajax-modal"]').click(function (event) {
/* event.preventDefault();*/
var url = $(this).data('url');
console.log(url)
$.get(url).done(function (data) {
PlaceHolderElement.html(data);
PlaceHolderElement.find('.modal').modal('show');
})
})
PlaceHolderElement.on('click', '[data-bs-save="modal"]', function (event) {
event.preventDefault();
var form = $(this).parents('.modal').find('form');
var actionUrl = form.attr('action');
console.log(actionUrl);
var sendViewModel = form.serialize();
console.log(sendViewModel);
//$.post(actionUrl, sendViewModel).done(function (data) {
// PlaceHolderElement.find('.modal').modal('hide');
/*above is the code from a tutorial for modals. It also doesn't send the object to
post action*/
$.ajax({
type: 'POST',
url: actionUrl,
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify(sendViewModel),
success: function (result) {
console.log('Data received: ');
console.log(result);
}
})
})
})
When I click the save button on the model, the console.log(sendViewModel) returns the correct Serialization with all of the properties and their correct names. And the properties change correctly when there is input.
Employee.Id=&Employee.Availability=&Employee.Role=Bartender&Employee.Name=&Employee.Phone=&Employee.Email=&Employee.Address=&Monday=false&Tuesday=false&Wednesday=false&Thursday=false&Friday=false&Saturday=false&Sunday=false
But I get an error "Failed to load resource: the server responded with a status of 404 ()" and when I check it the page says "No webpage was found for the web address: https://localhost:44313/Add HTTP ERROR 404" as if it's trying to get a post. It is also missing the controller, but if I change my form action to "Employee/Add" in the _Partial view it still doesn't send the data along with the url, which is causing an entirely different problem. I would greatly appreciate any help or guess or input of any kind. I'm about five seconds away from throwing my laptop out the window on this one. Thanks.
CodePudding user response:
Alright, thanks for the responses everyone. I feel really bad because I had the same exact issue not even a month ago, but I'm going to post the answer here anyway, incase it's helpful. First, I had to change the form action from "Add" to "Employee/Add". Second I had to remove the antiforgery token from my post action. The first code that is commented out actually works fine otherwise. In my defense I did remove the antiforgery token when I had the wrong url, but I forgot to retest that when I had the correct one.
CodePudding user response:
1.Remove the @Html.AntiForgeryToken()
inside your form,like below:
<form action="Add" >
@Html.AntiForgeryToken()
....
Then after you serialize the form you can get the AntiForgeryToken, like below:
Because when you don't add @Html.AntiForgeryToken()
inside form, after you serialize the form you don't get the AntiForgeryToken, like below:
Besides, if you use <form asp-action="Add" >
In ASP.Net Core anti forgery token is automatically added to forms, so you don't need to add @Html.AntiForgeryToken()
,you can find in the below :
2.change your ajax like below:
$.ajax({
type: 'POST',
url:'/Employee/Add',
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
data: sendViewModel,
success: function (result) {
console.log('Data received: ');
console.log(result);
}
})
result: