ASP.NET Core 更新工单状态时报未将对象引用设置到对象的实例错误
空引用错误排查与修复方案
错误触发的核心根源
你以为status为null导致了报错,实际上触发Object reference not set to an instance of an object.的位置是这行代码:
ticket.Status = status;
这里的ticket是null——因为从视图发出来的请求根本没有携带正确的ticketId参数,控制器调用_unitOfwork.Ticket.Get(ticketId)时拿到的ticketId是默认值0,查不到任何对应工单,返回了null对象,后续直接访问null对象的Status属性就会抛出空引用异常。
具体的代码错误点
- 下拉选择框绑定逻辑错误:当前代码写的是
asp-for="@Model.Ticket",把整个Ticket实体绑定到了状态选择下拉框上,既没有指向Ticket的Status属性,生成的select控件也完全无法匹配控制器需要的status参数名,就算提交也拿不到选中的状态值。 - 提交方式完全不符合规范:用来触发更新的是普通
<a>链接,既没有包裹在表单结构里携带select的选中值,也没有通过标签助手传入ticketId参数,点击链接发出的请求是完全无参的GET请求,根本无法为控制器的两个方法参数赋值。 - 控制器缺少边界防护:
- 没有对从数据库查询到的
ticket对象做空值判断,一旦查询不到对应工单就会直接触发空引用 - 调用了
Update方法但没有执行保存操作,就算不报错,工单状态的改动也不会写入数据库 - 方法最后直接
return View(),但没有给视图传入所需的模型对象,就算修改流程走完,返回页面时也会再次触发空引用错误
- 没有对从数据库查询到的
- 状态值没有合法性校验:当前方法直接把传入的
status字符串赋值给工单字段,没有校验值是否在预定义的TicketStatus枚举范围内,容易被传入恶意值污染数据库。
修复步骤
1. 修正视图层的状态修改区域代码
把管理员权限下的状态块替换为带表单结构的正确绑定逻辑:
@if (User.IsInRole(SD.Role_Admin)) { <form asp-area="Manager" asp-controller="Ticket" asp-action="UpdateStatus" method="post"> @* 隐藏域存储当前工单ID,确保提交时能传给控制器 *@ <input type="hidden" name="ticketId" value="@Model.Ticket.Id" /> <div class="form-group row"> <div class="col-2"> <label>Status Tiketa</label> </div> <div class="col-5"> @* 绑定到Ticket实体的Status字段,而非整个Ticket对象 *@ <select asp-for="Ticket.Status" asp-items="Html.GetEnumSelectList<VmSTicketing.Models.Enum.TicketStatus>()" class="form-control"></select> </div> </div> <div class="form-group"> <button type="submit" class="btn btn-primary">Update</button> </div> </form> }
2. 修正控制器的UpdateStatus方法
[HttpPost] [ValidateAntiForgeryToken] public IActionResult UpdateStatus(int ticketId, string status) { // 基础参数校验 if (ticketId <= 0 || string.IsNullOrWhiteSpace(status)) { return NotFound(); } // 校验状态值合法性 if (!Enum.TryParse<TicketStatus>(status, out _)) { return RedirectToAction(nameof(Details), new { id = ticketId }); } // 查工单,做非空校验避免空引用 var ticket = _unitOfwork.Ticket.Get(ticketId); if (ticket == null) { return NotFound(); } ticket.Status = status; _unitOfwork.Ticket.Update(ticket); // 提交保存到数据库 _unitOfwork.Save(); // 跳转回详情页,避免返回空视图触发错误 return RedirectToAction(nameof(Details), new { id = ticketId }); }
内容的提问来源于stack exchange,提问作者UnKnowUser
相关产品推荐
相关产品推荐

