49

I was trying to require a text input field in a form, which implies that there needs to be something in the form. However, adding a [Required] tag to my model wasn't working. Specifically, look at the User Name property:

public class ColumnWidthMetaData {
    [DisplayName("Column Name")]
    [Required]
    public string ColName { get; set; }

    [DisplayName("Primary Key")]
    public int pKey { get; set; }

    [DisplayName("User Name")]
    [Required]
    public string UserName { get; set; }

    [DisplayName("Column Width")]
    [Required]
    public int Width { get; set; }
}

This allows empty strings to get past model validation and eventually a database error is thrown when it attempts to insert a NULL value for User Name.

How can I change these attributes so they do what they seem like they should do?

DCShannon
  • 2,470
  • 4
  • 19
  • 32

3 Answers3

121

After a lot of Googling and looking on Stackoverflow, I had nothing.

I went to MSDN and looked at the System.ComponentModel.DataAnnotations Namespace.

There I looked more closely at the Required attribute, and noticed the AllowEmptyStrings property. Setting this to false tells the attribute not to allow any empty strings. In at least some versions this is the default behavior, which makes sense seeing as how the point of Required is to require that something be entered, and an empty string indicates that nothing was entered. You may not need to add this, if it's the default, but it doesn't hurt to be explicit.

This doesn't solve the problem though, as by default empty strings are coerced to null, which is not an empty string, and is therefore allowed. This seems absurd, as Required is supposed to test if something was entered, and null indicates nothing was entered. However, the AllowEmptyStrings page has a link to DisplayFormAttribute's Property ConvertEmptyStringsToNull. If you set this to false, then empty strings will remain empty strings, and then the required tag will not allow them.

So, here's the fix:

public class ColumnWidthMetaData {
    [DisplayName("Column Name")]
    [Required(AllowEmptyStrings=false)]
    [DisplayFormat(ConvertEmptyStringToNull=false)]
    public string ColName { get; set; }

    [DisplayName("Primary Key")]
    public int pKey { get; set; }

    [DisplayName("User Name")]
    [Required(AllowEmptyStrings=false)]
    [DisplayFormat(ConvertEmptyStringToNull=false)]
    public string UserName { get; set; }

    [DisplayName("Column Width")]
    [Required]
    public int Width { get; set; }
}    
DCShannon
  • 2,470
  • 4
  • 19
  • 32
  • 4
    I checking Assembly System.ComponentModel.DataAnnotations.dll, v4.0.0.0 and I see following comment: public bool AllowEmptyStrings { get; set; } // Returns: // true if an empty string is allowed; otherwise, false. The default value is false. - So where is a problem? Default value is false. – Tomas Kubes Sep 22 '17 at 15:05
  • @qub1n ditto Assembly System.ComponentModel.Annotations, Version=4.2.0.0 – ono2012 Nov 06 '17 at 17:44
  • 1
    Just to note that the default value of `AllowEmptyStrings` is `false` (in .NET Core 6 at least) so you don't need to specify it. – Appetere Jul 28 '23 at 08:08
  • This was a long time ago. I'm sure things have changed in nearly 10 years, with multiple updated versions. In any case, specifying AllowEmptyStrings as false may not be required but it doesn't hurt to be explicit. It's also not the main point of the answer. The important bit is ConvertEmptyStringToNull. – DCShannon Jul 28 '23 at 20:58
10

I'd implement a new validation attribute like this and apply it to my model.

public class RequiredNotEmptyAttribute : RequiredAttribute
{
    public override bool IsValid(object value)
    {
        if(value is string) return !String.IsNullOrEmpty((string)value);

        return base.IsValid(value);
    }
}

This will only work on the server side (client side will still only check for null).

Nathan A
  • 11,059
  • 4
  • 47
  • 63
6

You could use [MinLength(1)]. See msdn docs here.

firefox1986
  • 1,602
  • 11
  • 9