4

I'm using MVC 3 and attempting to get fields left blank to be sent to the database as zero-length strings, instead of nulls. Is this possible to do with data annotation attributes?

If not, what is the most appropriate place to convert from nulls? Is it during model validation?

Chris
  • 43
  • 1
  • 4

3 Answers3

12

While not ideal, this is the best way I know of: [DisplayFormat(ConvertEmptyStringToNull = false)] above the property. It keeps the logic in the model, which is good practice, and it directly addresses the issue. It's just a bummer that this is necessary.

private string _summary = "";
[Required]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public virtual string Summary
{
    get { return _summary; }
    set { _summary = value; }
}
Kyle Robson
  • 3,060
  • 24
  • 20
0

I wouldn't do this in a validator, but probably in model binding instead (or even in the model itself).

Often, in my model classes, I set my string properties to default to an empty string, and in their setters, I convert nulls to empty strings.

It's kindof a pain to write this repetitive stuff over and over, but it's so much nicer to not have to deal with nulls.

James Nail
  • 1,541
  • 1
  • 14
  • 23
  • I'm going with your solution but I'm dissapointed that modifying the model is required to address a view concern. I'm going to read more on model binding. – Chris Mar 22 '11 at 13:34
  • Chris, I think data annotation attributes are also a valid way to approach this. I personally opt for properties that default to empty strings because I hate dealing with nulls. – James Nail Mar 22 '11 at 17:57
  • I've spent some time thinking about this and must agree with you completely. – Chris Mar 23 '11 at 13:48
  • @Chris, I'm glad I could be helpful to you. Good luck! – James Nail Mar 23 '11 at 18:59
  • 2
    @Chris, check this answer out: http://stackoverflow.com/questions/3475273/how-to-convert-textboxes-with-null-values-to-empty-strings – James Nail Mar 29 '11 at 16:29
0

Set the property equal to string.empty in the constructor.

Or, though this is a little more costly you could make an extension method that does the following and just call it in the constructor:

 var stringPropertyInfos = GetType()
                  .GetProperties(BindingFlags.Instance|BindingFlags.Public)
                  .Where(p => p.PropertyType == typeof(string));
 foreach(var propertyInfo in stringPropertyInfos){
     propertyInfo.SetValue(this,string.Empty,null);
 }
smartcaveman
  • 41,281
  • 29
  • 127
  • 212
  • I'm not sure this is an appropriate approach. While clever, it's a bit much. – Chris Mar 22 '11 at 13:31
  • Sure. It's the easiest way. ModelMetadata already does the reflection, so it might make more sense to assign it there. You could always override the `DefaultModelBinder`, and have it assign strings to `string.Empty` instead of null by default. – smartcaveman Mar 22 '11 at 13:52
  • Basically you're suggesting that I iterate over all public, non-static string properties in a class. My comment is that this seems like an inappropriate thing to do no matter where or when you do it. While it's a clever solution, I'm wary of putting anything like that into production code, and especially code that others may have to maintain. In your comment you mention DefaultModelBinder. This didn't seem to be part of your original answer. Are you suggesting I've missed your point? – Chris Mar 22 '11 at 15:36
  • No, they were separate answers. The ModelBinder binds the ValueProviders' values to the Controller Action's parameters. This works if you are binding a form directly to a database call. I don't think this is good practice, because you are mixing concerns. I think that if its a data model, then you should initialize the properties with their intended default values in their constructor. Basically, you shouldn't be able to instantiate something invalid within the data layer of your application. That's why I suggested the reflection method as a short cut. – smartcaveman Mar 22 '11 at 17:40
  • However, if this model is a view model, then a better solution would be to use a model binder because you save the cost of an additional reflection. But, if this is a DAL object, then doing this in a ModelBinder causes a potentially larger problem of coupling your UI to your DAL. I still think the best place to do this is to manually set your properties in the constructor, and not allow them to be set to be invalid, but unless you are doing some codegen that takes considerably more work than the quick solution I provided you. – smartcaveman Mar 22 '11 at 17:43