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 te开发者_如何学运维xtbox 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?
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:
- Render a hidden field (
Html.Hidden
/Html.HiddenFor
) containing the Id along with the text boxes - Accept the changes in your controller action (as parameters or an object)
- Hydrate the instance of the object represented by Id from your repository/database
- Apply the changes to the hydrated instance
- 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.
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 );
}
Although I agree with @RichardSzalay , one other way would be to mark unchanged properties as not modified.
Lets say you have a model with these properties: Id, Name, Email. And you don't want to change Email.
public ActionResult ChangeName([Bind(Include="Id,Name")] User model)
{
// ...
db.Entry(model).State = EntityState.Modified;
db.Entry(model).Property(m => m.Email).IsModified = false;
db.SaveChanges();
// ...
}
The downside is that you may run into validation problems because of the missing fields in the model.
精彩评论