Asp.Net 核心 通过 Ajax 提交表单时获得 500 状态。没有 Ajax 也能完美运行

Asp.Net Core Getting a 500 status when submitting a form through Ajax. Works perfectly without Ajax

我有一个非常简单的表单 - 只有三个字段,其中只有两个由用户通过下拉菜单填写。第三个自动标记为 DateTime.Now。我使用了一些我已经为其他表单准备好的脚手架中的表单提交代码。当我将该代码放入 Home 控制器(显然是在更改了一些代码之后)并构建了表单时,一切都很好。所以我知道我的关系和路径都很好。

但是,提交后,它刷新了整个页面。我不能那样。它只需要刷新页面上的特定 div。所以,我必须运行它通过Ajax。这是我头发掉了一半的地方...

当我记录通过 Ajax 传递的值时,正在获取正确的值,但随后我收到“Home/CreateBreak”的 500 错误,这正是它所在的位置在控制器中。这是控制台在 Chrome 中的所有代码和屏幕截图。提前感谢您的帮助。

Home Controller:(创建条目时只填写TimeEntered、EmployeeId和EmpPosition)

     //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");
        }
    });
});

表格:

@model Seating.ViewModels.ListsVM

<form id="ajax_submit" class="DthdropdownGroup ml-3">
    <div class="btn-group" style="margin-left:-1rem">
        <select class="form-group dropdownStyling btn-sm dropdown-toggle d-inline-block btn-outline-light" style="width: 7.4em;" id="EmpId">
            <option disabled selected>Dispatcher</option>
            @foreach (var item in Model.Employees)
            {
                <option class="dropdown-item pr-1 form-control" value="@item.Id">@item.DisplayName</option>
            }
        </select>
    </div>

    <div class="btn-group">
        <select class="form-group dropdownStyling btn-sm dropdown-toggle d-inline-block btn-outline-light" style="width: 7.3em" id="EmployeePosition">
            <option disabled selected>Position</option>
            @foreach (var item in Model.Positions)
            {
                <option class="dropdown-item pr-1" value="@item.Id">@item.PositionName</option>
            }
        </select>
    </div>
    <button type="button" class="btn btn-sm btn-block dropdownStyling" id="break_submit" style="margin-left: -1rem; width:15rem;">Submit</button>
</form>

填充下拉列表的 VM(适用于所有表单 - 不仅仅是这个):

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; }
    }
}

还有,截图。您可以看到日志显示 Employee Id 3 和 Position 3 - 这很完美。但随后它会感到困惑,无法弄清楚从那里去哪里 - 即使我告诉它确切去哪里。

再次感谢

来自 ASP.NET 的 500 可能意味着在处理请求时在某个时刻抛出了未处理的异常。 我建议您将调试器附加到网络服务器进程 如果您也 double-checked 认为 URL 是正确的,那将会有所帮助。

你有一个错误,因为你的动作输入参数是空的。从 ajax

中删除 JSON.stringify(模型)
$.ajax({
        type: "Post",
        url: "/Home/CreateBreak",
        dataType: 'json',
        data: model,
        success: function (data) {
         .....

或者如果你想使用 json 然后添加 contentType: application/json

$.ajax({
        type: "Post",
        url: "/Home/CreateBreak",
        dataType: 'json',
        contentType: 'application/json; charset=utf-8',
        data: JSON.stringify(model),
        success: function (data) {
        ...

并将 [FromBody] 添加到动作中

public async Task<IActionResult> CreateBreak([FromBody] Break newBreak)

恕我直言,您使用 Model 结构不必要地使 Controller 方法复杂化。由于您只需要将 EmployeeIdEmpPosition 变量发送到 Controller 方法,您可以这样做:

//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");
        }
    });
});

您的 Controller 方法将如下所示:

 //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 });   
    }             
}