In my MVC 5 EF Database First project I have been using UpdateModel method in my controller action successfully, but after including some additional fields (previously unused by application) I find that the new fields simply refuse to get values from the UpdateModel method call. The only thing of any significance I can identify is that the fields share part of their name.
Consider this class as an example:
public class Record
{
public int ID {get;set;}
public string Details {get;set;}
public string DetailsFile {get;set;}
...
}
The property/field DetailsFile
was previously unused, but now is an optional field on the web form. It is stored in a <input type="hidden" name="DetailsFile" id="DetailsFile />
and is successfully posted to the controller action with the correct value (or empty string).
Within the controller action I handle the update like this:
[HttpPost]
public async Task<ActionResult> Edit(Record_EditView model, FormCollection collection)
{
if (ModelState.IsValid)
{
try
{
var record = await db.Record.FindAsync(model.ID);
UpdateModel(record, collection);
db.Entry(record).State = EntityState.Modified;
await db.SaveChangesAsync();
}
catch(Exception ex)
{
throw ex;
}
}
// do more stuff here
...
}
Which has been working fine, but with the additional field all fields except the DetailsFile
get updated from the FormCollection that is passed in. I have inspected both the model
and the collection
and they have the correct value, but the record
never gets the values until I do a second post of the same data. Then the values get pushed in to the fields as expected.
I don't get any errors thrown and am at a bit of a loss as to what is going on. For the time being I have resorted to modifying my controller action to this:
[HttpPost]
public async Task<ActionResult> Edit(Record_EditView model, FormCollection collection)
{
if (ModelState.IsValid)
{
try
{
var record = await db.Record.FindAsync(model.ID);
UpdateModel(record, collection);
record.DetailsFile = collection["DetailsFile"]; // <-- Manually insert DetailsFile value
db.Entry(record).State = EntityState.Modified;
await db.SaveChangesAsync();
}
catch(Exception ex)
{
throw ex;
}
}
// do more stuff here
...
}
And this works OK, however I'm sure that I shouldn't have to do this, and hope that someone out there can explain what I am overlooking!
Finally found the problem, it is not likely to benefit many people but just in case here is the answer.
More Information
In my project I started using a jquery plugin for styling file input elements in a more bootstrap fashion, namely Jasny Bootstrap.
The plugin works great, however as part of it's internal workings it takes steps to maintain state of existing data and avoid post conflict by using hidden input and renaming the file input like this:
The Problem
Which ends up with element(s) that have an attribute
name=""
and that caused the page to post the element and theFormCollection
to include an empty/"" item(s).Despite the fact that no errors were thrown, nonetheless it seems to break the call to
The Solution
To fix this and avoid posting the selected file (my project doesn't actually want the file to be posted, just the file path) I just intercept the form submit to remove the unwanted form elements prior to posting: