.NET MVC脚手架关联表创建提交时出现NullReferenceException异常
MVC CRUD实体关联提交时触发NullReferenceException异常
开发基于脚手架生成的MVC CRUD表格,配置Activo与Usuario、Procesador等实体关联后,Create页面下拉列表能正常显示关联数据,但点击Create提交时触发NullReferenceException(错误信息:Object reference not set to an instance of an object)。手动输入ID可正常提交,推测问题出在下拉列表值的获取或传递环节。
实体类代码
public class Activo { public int id { get; set; } [Required] [StringLength(100)] public string Marca { get; set; } [Required] [StringLength(100)] public string Modelo { get; set; } [Required] [StringLength(100)] public string Tarjeta_Video { get; set; } public int? ID_Usuario { get; set; } public int? ID_Procesador { get; set; } public int? ID_Memoria { get; set; } public int? ID_DiscoDuro { get; set; } // Navigation properties [ForeignKey("ID_Usuario")] public virtual Usuario Usuario { get; set; } [ForeignKey("ID_Procesador")] public virtual Procesador Procesador { get; set; } [ForeignKey("ID_Memoria")] public virtual Memoria Memoria { get; set; } [ForeignKey("ID_DiscoDuro")] public virtual DiscoDuro DiscoDuro { get; set; } }
Controller代码
// GET: Activos/Create public IActionResult Create() { ViewData["ID_DiscoDuro"] = new SelectList(_context.DiscoDuro, "id", "Marca"); ViewData["ID_Memoria"] = new SelectList(_context.Memoria, "id", "Marca"); ViewData["ID_Procesador"] = new SelectList(_context.Procesador, "id", "Marca"); ViewData["ID_Usuario"] = new SelectList(_context.Usuario, "id", "ApellidoMaterno"); return View(); } // POST: Activos/Create // To protect from overposting attacks, enable the specific properties you want to bind to. [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create([Bind("id,Marca,Modelo,Tarjeta_Video,ID_Usuario,ID_Procesador,ID_Memoria,ID_DiscoDuro")] Activo activo) { if (ModelState.IsValid) { _context.Add(activo); await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); } ViewData["ID_DiscoDuro"] = new SelectList(_context.DiscoDuro, "id", "Modelo", activo.ID_DiscoDuro); ViewData["ID_Memoria"] = new SelectList(_context.Memoria, "id", "Modelo", activo.ID_Memoria); ViewData["ID_Procesador"] = new SelectList(_context.Procesador, "id", "Modelo", activo.ID_Procesador); ViewData["ID_Usuario"] = new SelectList(_context.Usuario, "id", "ApellidoMaterno", activo.ID_Usuario); return View(activo); }
View代码
<form asp-action="Create"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <div class="form-group"> <label asp-for="Marca" class="control-label"></label> <input asp-for="Marca" class="form-control" /> <span asp-validation-for="Marca" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Modelo" class="control-label"></label> <input asp-for="Modelo" class="form-control" /> <span asp-validation-for="Modelo" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Tarjeta_Video" class="control-label"></label> <input asp-for="Tarjeta_Video" class="form-control" /> <span asp-validation-for="Tarjeta_Video" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="ID_Usuario" class="control-label"></label> <select asp-for="ID_Usuario" class ="form-control" asp-items="ViewBag.ID_Usuario"></select> </div> <div class="form-group"> <label asp-for="ID_Procesador" class="control-label"></label> <select asp-for="ID_Procesador" class ="form-control" asp-items="ViewBag.ID_Procesador"></select> </div> <div class="form-group"> <label asp-for="ID_Memoria" class="control-label"></label> <select asp-for="ID_Memoria" class ="form-control" asp-items="ViewBag.ID_Memoria"></select> </div> <div class="form-group"> <label asp-for="ID_DiscoDuro" class="control-label"></label> <select asp-for="ID_DiscoDuro" class ="form-control" asp-items="ViewBag.ID_DiscoDuro"></select> </div> <div class="form-group"> <input type="submit" value="Create" class="btn btn-primary" /> </div> </form>
错误信息
An unhandled exception occurred while processing the request. NullReferenceException: Object reference not set to an instance of an object. Microsoft.AspNetCore.Mvc.Rendering.MultiSelectList.GetListItemsWithValueField()
完整调用栈
Microsoft.AspNetCore.Mvc.Rendering.MultiSelectList.GetListItemsWithValueField() Microsoft.AspNetCore.Mvc.Rendering.MultiSelectList.GetEnumerator() System.Collections.Generic.List<T>..ctor(IEnumerable<T> collection) System.Linq.Enumerable.ToList<TSource>(IEnumerable<TSource> source) Microsoft.AspNetCore.Mvc.ViewFeatures.DefaultHtmlGenerator.GenerateGroupsAndOptions(string optionLabel, IEnumerable selectList, ICollection currentValues) Microsoft.AspNetCore.Mvc.ViewFeatures.DefaultHtmlGenerator.GenerateSelect(ViewContext viewContext, ModelExplorer modelExplorer, string optionLabel, string expression, IEnumerable selectList, ICollection currentValues, bool allowMultiple, object htmlAttributes) Microsoft.AspNetCore.Mvc.TagHelpers.SelectTagHelper.Process(TagHelperContext context, TagHelperOutput output) Microsoft.AspNetCore.Razor.TagHelpers.TagHelper.ProcessAsync(TagHelperContext context, TagHelperOutput output) Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner.RunAsync(TagHelperExecutionContext executionContext) AspNetCoreGeneratedDocument.Views_Activos_Create.b__19_0() Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext.GetChildContentAsync(bool useCachedResult, HtmlEncoder encoder) Microsoft.AspNetCore.Mvc.TagHelpers.RenderAtEndOfFormTagHelper.ProcessAsync(TagHelperContext context, TagHelperOutput output) Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner.g__Awaited|0_0(Task task, TagHelperExecutionContext executionContext, int i, int count) AspNetCoreGeneratedDocument.Views_Activos_Create.ExecuteAsync() Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context) Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, bool invokeViewStarts) Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context) Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable statusCode) Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable statusCode) Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ActionContext actionContext, IView view, ViewDataDictionary viewData, ITempDataDictionary tempData, string contentType, Nullable statusCode) Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor.ExecuteAsync(ActionContext context, ViewResult result) Microsoft.AspNetCore.Mvc.ViewResult.ExecuteResultAsync(ActionContext context) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|22_0(ResourceInvoker invoker, IActionResult result) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|30_0<TFilter, TFilterAsync>(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext<TFilter, TFilterAsync>(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters() Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync() Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|17_1(ResourceInvoker invoker) Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|17_1(ResourceInvoker invoker) Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
解决方案
异常根源在MultiSelectList.GetListItemsWithValueField(),说明生成下拉选项时存在空引用,按以下步骤排查修复:
统一SelectList的Display字段
对比GET和POST方法的SelectList创建逻辑:- GET方法中用
"Marca"作为下拉选项的显示字段 - POST方法中却将
DiscoDuro、Memoria、Procesador的显示字段改成了"Modelo"
如果这些实体类中没有Modelo属性,或者该属性值为null,就会触发空引用异常。
修复:将POST方法中的显示字段统一改为"Marca",或确认实体类中Modelo属性存在且有值:
ViewData["ID_DiscoDuro"] = new SelectList(_context.DiscoDuro, "id", "Marca", activo.ID_DiscoDuro); ViewData["ID_Memoria"] = new SelectList(_context.Memoria, "id", "Marca", activo.ID_Memoria); ViewData["ID_Procesador"] = new SelectList(_context.Procesador, "id", "Marca", activo.ID_Procesador);- GET方法中用
确保关联表数据源不为空
如果_context.DiscoDuro等查询返回null或空集合,创建SelectList时会引发异常。添加空值判断:ViewData["ID_DiscoDuro"] = _context.DiscoDuro?.Any() == true ? new SelectList(_context.DiscoDuro, "id", "Marca", activo.ID_DiscoDuro) : new SelectList(Enumerable.Empty<DiscoDuro>(), "id", "Marca");优化下拉列表的空选项处理
在View的下拉列表中添加默认空选项,避免用户未选择时提交null的潜在问题:<select asp-for="ID_Usuario" class="form-control" asp-items="ViewBag.ID_Usuario"> <option value="">-- 请选择用户 --</option> </select>
内容的提问来源于stack exchange,提问作者yzkael
相关产品推荐
相关产品推荐

