I have this form on my page. It's for adding some project to DB. Project requires director for itself, so i pass SelectList of workers to this form.
<form asp-controller="Project" asp-action="Edit" method="post">
...some other fields...
@if (ViewBag.workers != null)
{
<div>
<label asp-for="director">Director</label>
<select asp-for="director" [email protected]>
</select>
<span asp-validation-for="director"></span>
</div>
}
...
</form>
Select tag working, there are my workers. But when i'm trying to submit, i have error "The director field is required."
I've checked form with js and it has data from select option, but my post handler don't.
There is code of hadler
[HttpPost]
public IActionResult Edit(Project model)
{
// here model hasn't director field
if (ModelState.IsValid)
{
dataManager.project.SaveProject(model);
return RedirectToAction(nameof(HomeController.Index), nameof(HomeController).Replace("Controller", ""));
}
ViewBag.workers = new SelectList(dataManager.worker.GetAllWorkers(), nameof(Worker.id), nameof(Worker.name));
return View(model);
}
And Project class code
public class Project
{
[Required] public Guid id { set; get; }
[Required] public string name { set; get; }
public string customer { set; get; }
public string executor { set; get; }
public Worker director { set; get; }
public DateTime start { set; get; }
public DateTime end { set; get; }
public uint priority { set; get; }
}
CodePudding user response:
Post the solution mentioned in the comment as the answer post as the reference for the future reader.
Issue & Concern
From this line:
ViewBag.workers = new SelectList(dataManager.worker.GetAllWorkers(), nameof(Worker.id), nameof(Worker.name));
You are setting the value of the drop-down list option as id
. Unsure what is the id
type, (possibly it is an int
, Guid
type) but I am sure that it is not a Worker
(object) type.
While in the Project
model, you specify director
as Worker
type.
public class Project
{
...
public Worker director { set; get; }
}
Since an int
/Guid
type is unmatched with the Worker
type, the API action is unable to bind the value that you passed from the View to the model. Thus, you will get Project
as null
in the API action.
Solution
- Would suggest that modify the property type in
Project
model asint
/Guid
(depending on your Worker ID type in the database) rather than using theWorker
(object) type. And remove theWorker
property as it is no longer needed and avoid the error inModelState
due to the value is not provided.
Note: If this Project
model is the entity model that was generated (scaffolded) by Entity Framework, would suggest creating another class that acts as the DTO (Data Transfer Object). Then map the received DTO to entity model.
public class Project
{
...
public Worker directorId { set; get; }
}
- In the View, bind the drop-down list with
asp-for="workerId"
to pass the selected value asworkerId
.
<select asp-for="directorId" [email protected]></select>
Back-end side
3.1. Key point: Query the
Worker
object with the receivedproject.workerId
. Then bind theWorker
object to the entity model before inserting.3.2. (If implementing the DTO as mentioned in 1) You need to implement the logic (or look for mapping library such as AutoMapper) to map from DTO to the entity model.