简体   繁体   中英

Why is my model populating but the text box isn't?

I am searching the database by two values:

public class SearchProjectModel : ISearchProject
    {
        public int ProjectID { get; set; }
        [Display(Name = "Project Number")]
        public string JobNumber { get; set; }
        [Display(Name = "Project Name")]
        public string JobName { get; set; }
    }

Index View:

@model SearchProjectModel

@using (@Html.BeginForm("ManipulateProject", "Project", FormMethod.Post))
{

    <div>
        @Html.HiddenFor(x => x.ProjectID)
        <div class="col-md-3">
            @Html.LabelFor(x => x.JobNumber)
            @Html.TextBoxFor(x => x.JobNumber, new { @class = "form-control", id = "jobNumber" })
            @Html.ValidationMessageFor(x => x.JobNumber)
        </div>
        <div class="col-md-6">
            @Html.LabelFor(x => x.JobName)
            @Html.TextBoxFor(x => x.JobName, new { @class = "form-control " })
            @Html.ValidationMessageFor(x => x.JobName)
        </div>
    </div>

    <div class="col-md-12 text-center" style="margin-top: 1%">
        <button type="submit" class="btn btn-primary">Submit</button>
    </div>
}

On the controller I am then creating a new model based off what was found:

public ActionResult ManipulateProject(SearchProjectRequest request)
{
    var project = _projectService.GetBy(request);
    if (project != null)
    {
        //When this method is complete the data is in the new model!!!!
        return View("Project", Assemble(project));
    }
    return View("Project", Assemble(new ManipulateProjectModel()));
}

Model:

 public class ManipulateProjectModel : IProject
{
    public int ProjectID { get; set; }
    [Display(Name = "Project Number"), Required(ErrorMessage = "Required!")]
    public string JobNumber { get; set; }
    [Display(Name = "Project Name"), Required(ErrorMessage = "Required!")]
    public string JobName { get; set; }
    //Lots of stuff that is being populated
}

Project View:

@model ManipulateProjectModel

<div>
@using (@Html.BeginForm("Save", "Project", FormMethod.Post))
{
    @Html.HiddenFor(x => x.ProjectID)
    <div class="col-md-12" style="border: 1px dotted black; padding: 1%; margin-top: 1%">
        <h3 class="col-md-12 text-center">Project Info</h3>
        <div class="col-md-3">
            @Html.LabelFor(x => x.JobNumber)
            @Html.TextBoxFor(x => x.JobNumber, new { @class = "form-control", id = "jobNumber"})
            @Html.ValidationMessageFor(x => x.JobNumber)
        </div>
        <div class="col-md-6">
            @Html.LabelFor(x => x.JobName)
            @Html.TextBoxFor(x => x.JobName, new { @class = "form-control "})
            @Html.ValidationMessageFor(x => x.JobName)
        </div>

        //stuff that is populated just fine
    </div>
}
</div>

When the project is found and Assemble is called, The new Model is populated with ALL THE DATA!!! But if I only searched for one of two parameters then the box that I didn't fill in is populated on the model but the textbox does not display the data.

Why is the model populated but the view doesn't populate the textbox. It should not know or care if the previous view was populated.

This is because the html helpers uses the values from ModelState , not the values from your model. When you post to public ActionResult ManipulateProject(SearchProjectModel request) (note I assume its really SearchProjectModel , not SearchProjectRequest ), an instance of SearchProjectModel is created and its properties are bound. The values are also added to ModelState .

When you return the view with an instance of ManipulateProjectModel , your @Html.TextBoxFor(x => x.JobName ) sets the value by first looking for a ModelState value. Because the value in the first form was (say) null , then the textbox will display an empty string after the post because the ModelState value for JobName is null , despite what you Assemble() method may have set it to. The reason for this behavior is explained in this answer .

One option is to give your SearchProjectModel properties different names that the properties in ManipulateProjectModel . The other option is to clear ModelState before reassigning the new values and returning the view

ModelState.Clear(); // clears all values
// or clear one property
if (ModelState.ContainsKey("JobName"))
{
  ModelState["JobName"].Errors.Clear();
}

Note clearing model state also removes validation errors, so use with caution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM