11

model is

public partial class BilingualString 
{ 
    public string RuString { get; set; } 
    public string EnString { get; set; } 
} 

public partial class Member 
{  
   public Member() 
   { 
       this.DisplayName = new BilingualString(); 
   } 
   public BilingualString DisplayName { get; set; } 
} 

if user don't fill inputs the values of RuString and EnString is null. I need string.Empty instead of null.

Using CustomModelBinder like this:

public class EmptyStringModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
        bindingContext.ModelMetadata.ConvertEmptyStringToNull = false; 
        return base.BindModel(controllerContext, bindingContext); 
    } 
} 

don't help.

2 Answers 2

15

Use this:

    [DisplayFormat(ConvertEmptyStringToNull=false)]
    public string RuString { get; set; }

OR

    private string _RuString;
    public string RuString {
        get {
            return this._RuString ?? "";
        }
        set {
            this._RuString = value ?? "";
        }
    }
Sign up to request clarification or add additional context in comments.

4 Comments

What if we don't want to mark every string field as [DisplayFormat(ConvertEmptyStringToNull=false)] ?
The question is how to tell MVC 3 bind empty html input as string.Empty, not as null (like in MVC 1). The BilingualString is example to show that custom EmptyStringModelBinder don't do the do the trick.
I know what are you talking about. But I don't know any other way ): so sorry. If you find, put it here please. I'm following your Q. I think u have to use one of these 3 ways.
I didn't want to write this on each string property so went with @Mike's answer.
2

old question, but here's an answer anyway :)

The issue seems to be that the ConvertEmptyStringToNull is set on the model binding context, not the property binding context.

Inside the DefaultModelBinder, it calls BindProperty for each property of the model, and doesn't recurse simple objects like strings/decimals down to their own call of BindModel.

Luckily we can override the GetPropertyValue instead and set the option on the context there.

public class EmptyStringModelBinder : DefaultModelBinder
{
   protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)
   {
       bindingContext.ModelMetadata.ConvertEmptyStringToNull = false;
       return base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);
   }
} 

Worked for me :)

[edit] As pointed out in comments.. This model binder will only work if registered, so after adding class, be sure to call

ModelBinders.Binders.Add(typeof(string), new EmptyStringModelBinder());

in the Application_Start() method of Global.asax.cs

2 Comments

To make this work you also need to add ModelBinders.Binders.Add(typeof(string), new EmptyStringModelBinder()); in Application_Start(). After I added this line, it worked for me as well.
Sorry, my bad, I answered the OP's question on the assumption that they knew to do this given they'd already attempted a custom binder. didn't think about anyone else!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.