I have a very simple form - just three fields and only two of them are filled in by the user via dropdowns. The third is automatically stamped with DateTime.Now. I used the form submit code from some scaffolding I already had in place for other forms. When I put that code into the Home controller (after changing some of the code, obviously) and built the form, everything submits great. So I know my connections and paths are all good.
However, after it submits, it refreshes the whole page. I can't have that. It needs to just refresh specific divs on the page. So, I have to run it through Ajax. Here's where I've lost half the hair on my head...
When I log the values being passed in through Ajax, the correct values are being obtained but then I'm getting a 500 error for "Home/CreateBreak", which is right where it is in the controller. Here's all the code and a screenshot of how the console looks in Chrome. Thank you in advance for any help.
Home Controller: (Only the TimeEntered, EmployeeId and EmpPosition are filled when the entry is created).
//Create//
[HttpPost]
public async Task<IActionResult> CreateBreak([Bind("Id,TimeEntered,TimeCleared,EmpSent,EmployeeId,EmpPosition,RlfPosition")] Break newBreak)
{
if (ModelState.IsValid)
{
newBreak.TimeEntered = DateTime.Now;
_context.Add(newBreak);
await _context.SaveChangesAsync();
return Json(new { success = true, });
}
else
{
return Json(new { success = false });
}
}
Ajax:
//Add Break
$(document).on("click", "#break_submit", function () {
var model = {};
model.EmployeeId = Number($("#EmpId").val());
model.EmpPosition = Number($("#EmployeePosition").val());
console.log("model", model);
$.ajax({
type: "Post",
url: "/Home/CreateBreak",
dataType: 'json',
data: JSON.stringify(model),
success: function (data) {
if (data.success)
{
$(" #headerRefresh ").load(window.location.href " #headerRefresh ");
$(" .dthRefresh ").load(window.location.href " .dthRefresh ");
}
else
alert("Error: Please enter your name AND position");
},
error: function () {
alert("Error: Please enter your name AND position");
}
});
});
Form:
@model Seating.ViewModels.ListsVM
<form id="ajax_submit" >
<div style="margin-left:-1rem">
<select style="width: 7.4em;" id="EmpId">
<option disabled selected>Dispatcher</option>
@foreach (var item in Model.Employees)
{
<option value="@item.Id">@item.DisplayName</option>
}
</select>
</div>
<div >
<select style="width: 7.3em" id="EmployeePosition">
<option disabled selected>Position</option>
@foreach (var item in Model.Positions)
{
<option value="@item.Id">@item.PositionName</option>
}
</select>
</div>
<button type="button" id="break_submit" style="margin-left: -1rem; width:15rem;">Submit</button>
</form>
VM that fills the dropdowns (for all the forms - not just this one):
namespace Seating.ViewModels
{
public class ListsVM
{
public ListsVM()
{
Employees = new List<Employee>();
Positions = new List<Position>();
}
public IEnumerable<Dth> Dths { get; set; }
public IEnumerable<Break> Breaks { get; set; }
public IEnumerable<Lunch> Lunches { get; set; }
public IEnumerable<Employee> Employees { get; set; }
public IEnumerable<Position> Positions { get; set; }
public int EmployeeId { get; set; }
public int EmpPosition { get; set; }
public bool EmpSent { get; set; }
public bool LunchTime { get; set; }
public bool LongerLunch { get; set; }
public bool DblLunch { get; set; }
}
}
And, the screenshot. You can see the logs are showing Employee Id 3 and Position 3 - which is perfect. But then it gets confused and can't figure out where to go from there - even though I told it exactly where to go.
Thanks again
CodePudding user response:
A 500 from ASP.NET probably means an unhandled exception was thrown at some point when serving the request. I suggest you attach a debugger to the webserver process It would help if you also double-checked that the URL is correct.
CodePudding user response:
you have an error, since your action input parameters are empty. Remove JSON.stringify(model) from ajax
$.ajax({
type: "Post",
url: "/Home/CreateBreak",
dataType: 'json',
data: model,
success: function (data) {
.....
or if you want to use json then add contentType: application/json
$.ajax({
type: "Post",
url: "/Home/CreateBreak",
dataType: 'json',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(model),
success: function (data) {
...
and add [FromBody] to an action
public async Task<IActionResult> CreateBreak([FromBody] Break newBreak)
CodePudding user response:
IMHO, you are unnecessarily complicating things on your Controller
method using a Model
structure. Since you only need to send your EmployeeId
and EmpPosition
variables to your Controller
method, you can do this:
//Add Break
$(document).on("click", "#break_submit", function () {
var EmployeeId = Number($("#EmpId").val());
var EmpPosition = Number($("#EmployeePosition").val());
var json = {
EmployeeId: EmployeeId,
EmpPosition: EmpPosition
};
console.log("Model", json);
$.ajax({
type: "post",
//url: "/Home/CreateBreak",
url: "@Url.Action("CreateBreak", "Home")",
dataType: "json",
data: {"json": JSON.stringify(json)},
success: function (data) {
if (data.success)
{
$(" #headerRefresh ").load(window.location.href " #headerRefresh ");
$(" .dthRefresh ").load(window.location.href " .dthRefresh ");
}
else
alert("Error: Please enter your name AND position");
},
error: function () {
alert("Error: Please enter your name AND position");
}
});
});
And your Controller
method will look like this:
//Create//
[HttpPost]
public async Task<IActionResult> CreateBreak(string json)
{
Break newBreak=new Break();
int EmployeeId=0;
int EmpPosition=0;
if(!string.IsNullOrEmpty(json))
{
var jsonData = JsonConvert.DeserializeObject<dynamic>(json);
EmployeeId = Convert.ToInt32(jsonData.EmployeeId);
EmpPosition = Convert.ToInt32(jsonData.EmpPosition);
newBreak.EmployeeId = EmployeeId;
newBreak.EmpPosition = EmpPosition;
if (ModelState.IsValid)
{
newBreak.TimeEntered = DateTime.Now;
_context.Add(newBreak);
await _context.SaveChangesAsync();
return Json(new { success = true, });
}
else
{
return Json(new { success = false });
}
}
else
{
return Json(new { success = false });
}
}