I understand that the SelectListItems are meant to not return back the items on post and perhaps be null, but because of this my ModelState.IsValid condition is always false and the Studies field which contains the list is the one with the invalid attribute. I tried different methods and am stuck on resolving this
View
<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; }
}
Controller
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);
}
2
Answers
The problem is originated when you click your button to submit the form data back to the controller.
At this point the client side code sends the input fields present on the form and you don’t have an input field that contains the SelectListItem. The SelectedStudyGuid select list is for that field, not for the whole Studies.
The AddStudyViewModel instance received in the post action is rebuilt on the server side using the data sent by the client side and thus you have a null for the Studies property.
Usually the SelectListItem data is not needed on the post action but only in the get action and you can simply pass it using some temporary storage like the ViewBag
So you can fix with
MODEL
CONTROLLER
VIEW
This can happen only if you use net 6. To fix it simply make Studies nullable
or what is the smart developers do , they just remove nullables from the projests
to use a ViewBag instead of a ViewModel is very unprofessional