82

I used to receive empty string when there was no value:

[HttpPost]
public ActionResult Add(string text)
{
    // text is "" when there's no value provided by user
}

But now I'm passing a model

[HttpPost]
public ActionResult Add(SomeModel Model)
{
    // model.Text is null when there's no value provided by user
}

So I have to use the ?? "" operator.

Why is this happening?

Erik Philips
  • 53,428
  • 11
  • 128
  • 150
Alex
  • 34,581
  • 26
  • 91
  • 135
  • An alternative solution to using attributes on each model property, as described below, is using a custom model binder, see http://stackoverflow.com/questions/12734083/string-empty-converted-to-null-when-passing-json-object-to-mvc-controller – Anders Jan 16 '13 at 15:14

3 Answers3

174

You can use the DisplayFormat attribute on the property of your model class:

[DisplayFormat(ConvertEmptyStringToNull = false)]
KyleMit
  • 30,350
  • 66
  • 462
  • 664
Michael Jubb
  • 1,756
  • 1
  • 11
  • 2
  • This helped me with implicit model binding before my action was executed. Used it along with MetadataTypeAttribute to mark auto-generated property of Entity Framework Model-First class – EvAlex May 13 '13 at 10:47
  • 1
    This is definitively a Should Know. – Serge Nov 28 '13 at 12:50
  • I am using: `public ActionResult Quotations(string projectName, string brandName, string modelName, string clientName) { var model = _dataAccess.Quotations_Select(projectName, brandName, modelName, clientName); return View(model); }` calling a stored procedure and supplying values, so, the attribute will not work for me. What should I do? – Talal Yousif Jan 17 '15 at 16:36
  • 3
    It's a long road, but also, in MVC6, if you (like me) for some reason don't want to set this via an attribute and want to store your metadata elsewhere, you can write your own metadata provider and register it in Startup.cs like: `AddMvc(o => ModelMetadataDetailsProviders.Add(new YourProvider()))`. There in `GetDisplayMetadata` you can do everying that attributes do. For this question it'll be `context.DisplayMetadata.ConvertEmptyStringToNull = false;` – evilkos Jan 13 '16 at 14:45
  • This conflicted with my other validation I had on the property. I ended up creating a property with a backing field where the get returns empty string if the backing field is null. – Peheje Oct 01 '18 at 06:39
9

The default model binding will create a new SomeModel for you. The default value for the string type is null since it's a reference type, so it's being set to null.

Is this a use case for the string.IsNullOrEmpty() method?

hackerhasid
  • 11,699
  • 10
  • 42
  • 60
  • 1
    Yeah, that's what I thought. I didn't realize that default value for the string type is null, not String.Empty though. No, it's not the case for the IsNullOrEmpty method, I have NOT NULL columns in my SQL table, so I get an exception when there'are null strings. So I guess I'll have to continue to use the ?? "" operator. Thanks! – Alex Sep 07 '10 at 09:24
  • You might also use a property with a backing store and return string.empty instead of null from the ViewModel, eg: – hackerhasid Sep 08 '10 at 14:38
  • 1
    woops! here's some psuedocode: private string _text; public string Text { get { return _text; } set { _text = value ?? string.empty; }} -- something like that – hackerhasid Sep 08 '10 at 14:39
2

I am trying this in Create and Edit (my object is called 'entity'):-

        if (ModelState.IsValid)
        {
            RemoveStringNull(entity);
            db.Entity.Add(entity);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(entity);
    }

Which calls this:-

    private void RemoveStringNull(object entity)
    {
        Type type = entity.GetType();
        FieldInfo[] fieldInfos = type.GetFields(BindingFlags.Instance | BindingFlags.GetField | BindingFlags.Public | BindingFlags.NonPublic);
        for (int j = 0; j < fieldInfos.Length; j++)
        {
            FieldInfo propertyInfo = fieldInfos[j];
            if (propertyInfo.FieldType.Name == "String" )
            {
                object obj = propertyInfo.GetValue(entity);
                if(obj==null)
                    propertyInfo.SetValue(entity, "");
            }
        }
    }

It will be useful if you use Database First and your Model attributes get wiped out each time, or other solutions fail.

user2284063
  • 321
  • 2
  • 5