3

I have a Visual Studio 2013 MVC Razor project that I am studying by walking through one of the examples on w3schools.com.

In the chapter on ASP.NET MVC Security, you will see the default file AccountModels.cs in the Models class with the following text for each of the Password fields:

    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "New password")]
    public string NewPassword { get; set; }

I am familiar with String.Format, where the parameters must start from 0 and increment up.

The 2nd parameter above, however, jumps to 2, and it does not appear to have enough parameters being passed to the string.

When learning a project, I do what I can to customize features (like string responses) to better enforce my learning.

What is going on here?

pictures rock

  • 1
    http://referencesource.microsoft.com/#System.ComponentModel.DataAnnotations/DataAnnotations/StringLengthAttribute.cs,76 – SLaks Jan 12 '15 at 21:09
  • 2
    w3schools isn't the best resource for accurate information. They've cleaned up much of the html and javascript tutorials, but I'm not sure about ASP.NET. I would recommend sticking with http://www.asp.net/mvc – jrummell Jan 12 '15 at 21:10

2 Answers2

3

After a little more investigating, I found an answer posted on the ASP.NET Forum by CodeHobo:

You can find the full documentation here

http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.stringlengthattribute.aspx

[StringLength(100, ErrorMessage = "The password must be at least {0} characters", MinimumLength = 6)]

In this case error message is just a string template that is applied when rendered. Think of a string.Format. So it is equivalent to

string.Format("The {0} must be at least {2} characters long.",DisplayName,MaximumLength,MinimumLength);

The 0 index is the display name of the property, 1 is the maximum length, 2 is the minimum length

For your example, this would show the display name instead of the minimum length. You need to change {0} to {2}

[StringLength(100, ErrorMessage = "The password must be at least {0} characters", MinimumLength = 6)]

Yes, I could have simply deleted my question, but SO is my primary source of programming information.

If I don't find a programming answer here, I feel it needs it.

I don't quite yet understand the answer 100%, so if anyone has a better answer, I would gladly accept it.

Community
  • 1
  • 1
  • This was somewhat discussed here: http://stackoverflow.com/questions/9540314/modify-default-errormessage-for-stringlength-validation, but you're correct in that the structure of the format string is not really covered in the MSDN. – Tieson T. Jan 12 '15 at 21:26
  • This confused me also. Thank you very much for answering your own question and not deleting it. I found your question and answer by doing a Google search. – webworm Nov 18 '15 at 18:19
3

StringLengthAttribute class constructor

We are basically calling a constructor of a class:

The StringLengthAttribute is a class, and its constructor has one int parameter called maximumLength

It also has some Properties:

  • ErrorMessage of type string
    • in our case it's the string: "The {0} must be at least {2} characters long."
  • ErrorMessageResourceName of type string
    • in our case we don't give it any value
  • ErrorMessageResourceType of type System.Type
    • in our case we don't give it any value
  • MinimumLength of type int
    • in our case we give it the value 6

the ErrorMessageResourceName string has nothing to do (yet) with the other properties, so it is nothing like this:

String.Format("some variable {0} and some other {1}...", 100, 6)

so the number 100 and the property MinimumLength = 6 are not at all (yet) parameters sent to be formatted with the string "The {0} must be at least {2} characters long.".

The class StringLengthAttribute also has some methods, one of them is called FormatErrorMessage

This method is called internally to format the message, and it internally formats the string using String.Format, and here is when the parameters are passed to the string to be correctly formatted.

  • {0} is bound to DisplayName
  • {1} is bound to MaximumLength
  • {2} is bound to MinimumLength

this is the method that is called internally (if you want to know how it internally does it):

/// <summary>
    /// Override of <see cref="ValidationAttribute.FormatErrorMessage"/>
    /// </summary>
    /// <param name="name">The name to include in the formatted string</param>
    /// <returns>A localized string to describe the maximum acceptable length</returns>
    /// <exception cref="InvalidOperationException"> is thrown if the current attribute is ill-formed.</exception>
    public override string FormatErrorMessage(string name) {
        this.EnsureLegalLengths();

        bool useErrorMessageWithMinimum = this.MinimumLength != 0 && !this.CustomErrorMessageSet;

        string errorMessage = useErrorMessageWithMinimum ?
            DataAnnotationsResources.StringLengthAttribute_ValidationErrorIncludingMinimum : this.ErrorMessageString;

        // it's ok to pass in the minLength even for the error message without a {2} param since String.Format will just
        // ignore extra arguments
        return String.Format(CultureInfo.CurrentCulture, errorMessage, name, this.MaximumLength, this.MinimumLength);
    }

References:

  • Microsoft Reference Source here
  • A similar question on Stackoverflow: "What parameters does the stringlength attribute errormessage take?" here
  • The almost useless msdn documentation for StringLengthAttribute Class here
Community
  • 1
  • 1
Juan Castano
  • 959
  • 7
  • 10
  • Your answer says about the same thing as mine, but answer awarded because it is much more detailed. Thanks, Mr. Castano. –  Feb 19 '16 at 11:30