ASP.NET Core 6表单提交时ContactViewModel传值为null的解决咨询
问题
在ASP.NET Core 6项目中,我创建了带验证特性的ContactViewModel类,又定义了包含该类及IEnumerable<Category>的MenuViewModel。在Index视图中以MenuViewModel为模型构建表单后,提交时控制器的MenuViewModel参数里的ContactViewModel属性始终为null,无法获取前端输入内容,该如何解决?
相关代码
ContactViewModel代码
public class ContactViewModel { [Required(ErrorMessage = "请输入您的姓名。")] public string Name { get; set; } [Required(ErrorMessage = "请输入您的邮箱。")] public string Email { get; set; } [Required(ErrorMessage = "请输入您的留言。")] public string Message { get; set; } }
MenuViewModel代码
public class MenuViewModel { public ContactViewModel ContactViewModel { get; set; } public IEnumerable<Category> Category { get; set; } }
视图表单代码
@model project.Models.ViewModels.MenuViewModel <form method="post" asp-action="ContactMe" asp-controller="Contact" id="contact-form"> <div class="form-group col-md-6"> <label>姓名</label> <input asp-for="ContactViewModel.Name" type="text" class="form-control" id="name"> <span asp-validation-for="ContactViewModel.Name" class="text-danger"></span> </div> <div class="form-group col-md-6"> <label>邮箱</label> <input asp-for="ContactViewModel.Email" type="text" class="form-control" id="Email"> <span asp-validation-for="ContactViewModel.Email" class="text-danger"></span> </div> <div class="form-group col-md-6"> <label>留言</label> <input asp-for="ContactViewModel.Message" type="text" class="form-control" id="Message"> <span asp-validation-for="ContactViewModel.Message" class="text-danger"></span> </div> <input type="submit" id="submit" class="btn btn-primary px-5 py-2" value="发送"> </form>
控制器代码
[HttpPost] public async Task<IActionResult> ContactMe(MenuViewModel menu) { if(!ModelState.IsValid) { return NotFound(); } // 写入数据库逻辑 }
解决方案
问题核心是模型绑定器无法为未初始化的引用类型属性赋值:MenuViewModel中的ContactViewModel是引用类型,默认值为null,绑定器无法直接给null对象的属性赋值。可通过以下两种方式解决:
方式一:在MenuViewModel中初始化ContactViewModel
修改MenuViewModel代码,直接在属性声明时实例化ContactViewModel:
public class MenuViewModel { // 初始化嵌套的ContactViewModel实例 public ContactViewModel ContactViewModel { get; set; } = new ContactViewModel(); public IEnumerable<Category> Category { get; set; } }
方式二:在控制器GET方法中实例化MenuViewModel
如果表单是通过GET方法返回的视图,需要在GET方法中创建MenuViewModel实例并初始化ContactViewModel:
[HttpGet] public IActionResult Index() { var menuViewModel = new MenuViewModel { ContactViewModel = new ContactViewModel(), // 按需初始化Category数据 Category = _categoryService.GetAllCategories() }; return View(menuViewModel); }
额外优化点
- 移除表单中手动添加的
name属性:asp-for标签助手会自动生成正确的name值(如ContactViewModel.Name),手动添加可能引发冲突,建议删除。 - 修正控制器错误返回逻辑:原代码返回
NotFound()会丢失用户输入,应改为return View(menu),保留用户输入并显示验证错误信息。
内容的提问来源于stack exchange,提问作者Jeff
相关产品推荐
相关产品推荐

