Reputation: 2813
My Sql Server database has some nullable nvarchar fields, and no nvarchar fields containing empty strings. I want to keep it this way, but the default MVC model binder seems to turn null strings into empty strings.
When a controller retrieves a null nvarchar database field, the null field turns into null string inside the controller, and from there the view renders them, say as blank text boxes. When the page is posted, the default model binder uses these blank text boxes to update the model, and the formerly null strings are changed to empty strings. When the data is updated back to the database, nulls are overwritten with empty strings.
What is the easiest way to get model binding to leave these nulls unchanged?
Upvotes: 1
Views: 2879
Reputation: 2813
I'm posting this answer to follow through on this question. After working with it for a while I came to see this problem as part of the general concern of model integrity. For a while I had implemented a solution inside my update stored procedures to catch empty strings and turn them to nulls, along the lines of mikerennick's answer above. Later I wanted also to make sure fields were trimmed and I happened to move the application to NHibernate (and most of the stored procedures went away). In the end I embedded some POCO logic to trim and check for empty strings (from whatever source) in the setters as so:
public MyClass { private string _name; public string Name { get { return _name; } set { _name = value.TrimToNullIfEmpty(); } } } public static class StringExtensions { public static string TrimToNullIfEmpty(this string s) { string temp = (s ?? "").Trim(); return temp.Length == 0 ? null : temp; } }
Upvotes: 0
Reputation: 18237
The right answer might be to override the default Model binder to add this functionality yourself.
Maybe you could have a NullValueAttribute that you could apply to string properties to identify the null value. Then make empty string a null value.
I am experiencing the same problem at the moment and will probably resort to this
Upvotes: 0
Reputation: 3374
Here's a hack I used a few months ago before I found the eden of stackoverflow. :) It's a pain, and doesn't scale well, but it works:
Basically, you override the binding inside of a partial linq object. If there's a value you know should always be null (but never legitimately empty) you can do the following. I used this for a string-based user id (SID).
partial void OnSubProcess_Owner_UserChanged()
{
if (string.IsNullOrEmpty(this.SubProcess_Owner_User))
this._SubProcess_Owner_User = null;
}
James
Upvotes: 0
Reputation: 395
I know you are probably looking for something more sophisticated, but the default behavior of the ModelBinder is to convert empty form field values into the default value for the datatype of your model object property. String properties become empty, int properties become 0, etc.
You can obviously create a validation scheme that will check for string.empty and convert to null prior to updating the DB. For int form fields you will need to check for 0, and then convert to null.
Upvotes: 1