POST 上的 SelectList 始终为 null 导致模型状态无效
SelectList always null on POST causes Model State to be Invalid
我知道 SelectListItems 的目的是不 return 支持 post 上的项目并且可能为空,但正因为如此,我的 ModelState.IsValid 条件始终为假,研究包含列表的字段是具有无效属性的字段。我尝试了不同的方法并坚持解决这个问题
查看
<label asp-for="Studies" class="form-label"></label>
<select asp-for="SelectedStudyGuid" asp-items="@Model.Studies" class="form-control" autocomplete="off">
<option value="">Select Study</option>
</select>
<span asp-validation-for="SelectedStudyGuid" class="text-danger"></span>
ViewModel
public class AddStudyViewModel
{
public string ParticipantGuid { get; set; }
public IEnumerable<SelectListItem> Studies { get; set; }
public string SelectedStudyGuid { get; set; }
[DataType(DataType.Date)]
public DateTime? StartDate { get; set; }
[DataType(DataType.Date)]
public DateTime? EndDate { get; set; }
}
控制器
private List<SelectListItem> GetStudyCatalog()
{
return _repo.GetStudyCatalog().Select(s => new SelectListItem
{
Text = s.Name,
Value = s.Guid
}).ToList();
}
[HttpGet]
public IActionResult AddStudy(string participantGuid)
{
var model = new AddStudyViewModel
{
Studies = GetStudyCatalog(),
ParticipantGuid = participantGuid
};
return PartialView("_AddStudyModal", model);
}
[HttpPost]
public IActionResult AddStudy(AddStudyViewModel model)
{
if (ModelState.IsValid)
{
var response= _repo.AddStudy(model.SelectedStudyGuid, model.ParticipantGuid, model.StartDate, model.EndDate);
if (response.Success)
{
TempData["Message"] = response.Message;
return RedirectToAction("EditParticipant", new {id = response.NewGuid});
}
}
model.Studies = GetStudyCatalog();
return PartialView("_AddStudyModal", model);
}
问题出在您单击按钮将表单数据提交回控制器时。
此时客户端代码发送表单上存在的输入字段,而您没有包含 SelectListItem 的输入字段。 SelectedStudyGuid select 列表是针对该领域的,而不是针对整个研究。
在 post 操作中接收到的 AddStudyViewModel 实例使用客户端发送的数据在服务器端重建,因此研究 属性.
通常 post 操作不需要 SelectListItem 数据,只有在 get 操作中才需要,您可以使用一些临时存储(如 ViewBag
)简单地传递它
所以你可以用
修复
型号
public class AddStudyViewModel
{
public string ParticipantGuid { get; set; }
public string SelectedStudyGuid { get; set; }
[DataType(DataType.Date)]
public DateTime? StartDate { get; set; }
[DataType(DataType.Date)]
public DateTime? EndDate { get; set; }
}
控制器
[HttpGet]
public IActionResult AddStudy(string participantGuid)
{
var model = new AddStudyViewModel
{
ParticipantGuid = participantGuid
};
ViewBag.Studies = GetStudyCatalog(),
return PartialView("_AddStudyModal", model);
}
VIEW
<label asp-for="Studies" class="form-label"></label>
<select asp-for="SelectedStudyGuid" asp-items="@ViewBag.Studies" class="form-control" autocomplete="off">
<option value="">Select Study</option>
</select>
<span asp-validation-for="SelectedStudyGuid" class="text-danger"></span>
只有在使用 net 6 时才会发生这种情况。要修复它,只需将 Studies 设置为 nullable
public List<SelectListItem>? Studies { get; set; }
或者聪明的开发人员在做什么,他们只是从项目中删除可为空值
<TargetFramework>net6.0</TargetFramework>
<!--<Nullable>enable</Nullable>-->
用 ViewBag 代替 ViewModel 很不专业
我知道 SelectListItems 的目的是不 return 支持 post 上的项目并且可能为空,但正因为如此,我的 ModelState.IsValid 条件始终为假,研究包含列表的字段是具有无效属性的字段。我尝试了不同的方法并坚持解决这个问题
查看
<label asp-for="Studies" class="form-label"></label>
<select asp-for="SelectedStudyGuid" asp-items="@Model.Studies" class="form-control" autocomplete="off">
<option value="">Select Study</option>
</select>
<span asp-validation-for="SelectedStudyGuid" class="text-danger"></span>
ViewModel
public class AddStudyViewModel
{
public string ParticipantGuid { get; set; }
public IEnumerable<SelectListItem> Studies { get; set; }
public string SelectedStudyGuid { get; set; }
[DataType(DataType.Date)]
public DateTime? StartDate { get; set; }
[DataType(DataType.Date)]
public DateTime? EndDate { get; set; }
}
控制器
private List<SelectListItem> GetStudyCatalog()
{
return _repo.GetStudyCatalog().Select(s => new SelectListItem
{
Text = s.Name,
Value = s.Guid
}).ToList();
}
[HttpGet]
public IActionResult AddStudy(string participantGuid)
{
var model = new AddStudyViewModel
{
Studies = GetStudyCatalog(),
ParticipantGuid = participantGuid
};
return PartialView("_AddStudyModal", model);
}
[HttpPost]
public IActionResult AddStudy(AddStudyViewModel model)
{
if (ModelState.IsValid)
{
var response= _repo.AddStudy(model.SelectedStudyGuid, model.ParticipantGuid, model.StartDate, model.EndDate);
if (response.Success)
{
TempData["Message"] = response.Message;
return RedirectToAction("EditParticipant", new {id = response.NewGuid});
}
}
model.Studies = GetStudyCatalog();
return PartialView("_AddStudyModal", model);
}
问题出在您单击按钮将表单数据提交回控制器时。
此时客户端代码发送表单上存在的输入字段,而您没有包含 SelectListItem 的输入字段。 SelectedStudyGuid select 列表是针对该领域的,而不是针对整个研究。
在 post 操作中接收到的 AddStudyViewModel 实例使用客户端发送的数据在服务器端重建,因此研究 属性.
通常 post 操作不需要 SelectListItem 数据,只有在 get 操作中才需要,您可以使用一些临时存储(如 ViewBag
)简单地传递它所以你可以用
修复型号
public class AddStudyViewModel
{
public string ParticipantGuid { get; set; }
public string SelectedStudyGuid { get; set; }
[DataType(DataType.Date)]
public DateTime? StartDate { get; set; }
[DataType(DataType.Date)]
public DateTime? EndDate { get; set; }
}
控制器
[HttpGet]
public IActionResult AddStudy(string participantGuid)
{
var model = new AddStudyViewModel
{
ParticipantGuid = participantGuid
};
ViewBag.Studies = GetStudyCatalog(),
return PartialView("_AddStudyModal", model);
}
VIEW
<label asp-for="Studies" class="form-label"></label>
<select asp-for="SelectedStudyGuid" asp-items="@ViewBag.Studies" class="form-control" autocomplete="off">
<option value="">Select Study</option>
</select>
<span asp-validation-for="SelectedStudyGuid" class="text-danger"></span>
只有在使用 net 6 时才会发生这种情况。要修复它,只需将 Studies 设置为 nullable
public List<SelectListItem>? Studies { get; set; }
或者聪明的开发人员在做什么,他们只是从项目中删除可为空值
<TargetFramework>net6.0</TargetFramework>
<!--<Nullable>enable</Nullable>-->
用 ViewBag 代替 ViewModel 很不专业