Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Razor MVC model is losing data on Save action

I have 1 textbox using TextBoxFor which contains the data.

I have an Id for the Model and some other basic data but displayed as labels directly into the View.

When I submit the form only the textbox field has data on the model, everything else is null including the Id. This means it won't save into the database.

What would cause all the fields to be null apart from the textbox?

like image 288
jaffa Avatar asked Mar 25 '11 17:03

jaffa


2 Answers

This is the way the web works, only form elements are submitted with the form and labels are not form elements.

What commonly happens here is that you:

  1. Render a hidden field (Html.Hidden / Html.HiddenFor) containing the Id along with the text boxes
  2. Accept the changes in your controller action (as parameters or an object)
  3. Hydrate the instance of the object represented by Id from your repository/database
  4. Apply the changes to the hydrated instance
  5. Validate the state of the object and update your repository/database (or whatever you were planning on doing with it)

As the posted data class is often "invalid" due to its missing properties (those marked as [Required] for example), its very common to make a new class that has only the properties being changed (called a "command model"). This class can have its own validation properties and thus not muck with your form validation.

like image 189
Richard Szalay Avatar answered Sep 24 '22 02:09

Richard Szalay


Only inputs are posted back to the server. If you want the model populated based on the data on the page, they must be in inputs (or part of the url). Data in label elements will not be posted to the server with the form (this is standard HTML form behavior). Typically you'd use hidden fields to post back non-editable model data or simply reference the model id and repopulate from the database, updating the editable properties (as below).

Example:

 @(using Html.BeginForm( new { id = Model.ID } ))
 {
       <p>
           <label>Fixed Property:</label>
           @Model.SomeFixedProperty
       </p>
       <p>
          @Html.LabelFor( m => m.EditableProperty )
          @Html.TextBoxFor( m => m.EditableProperty )
       </p>
}

Controller

[HttpPost]
public ActionResult Foo( int id, string editableProperty )
{
    var model = repo.GetById( id );
    model.EditableProperty = editableProperty;
    repo.Save();
    return View( model );
}
like image 35
tvanfosson Avatar answered Sep 24 '22 02:09

tvanfosson