To leverage the max length value on a custom validation message for the MaxLengthAttribute, you need to use the {1} placeholder. This will then be replaced at runtime by the validator itself with the actual number.
For example:
$"The 'Vehicle Number' is limited to {1} characters."
Note that you can also use replacement {0} to automatically grab the name of the property being validated, so you could actually replace your custom message with a more general template:
$"The '{0}' is limited to {1} characters."
Of course, you don't get the space between the words this way, as it will use the name of your property as is without doing any transformations on it.
Here is a simple way to see how these values are passed into the format string:
https://referencesource.microsoft.com/#System.ComponentModel.DataAnnotations/DataAnnotations/MaxLengthAttribute.cs,84
/// <summary>
/// Applies formatting to a specified error message. (Overrides <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>
public override string FormatErrorMessage(string name) {
// An error occurred, so we know the value is greater than the maximum if it was specified
return string.Format(CultureInfo.CurrentCulture, ErrorMessageString, name, Length);
}
In particular, notice the position of the name and Length values there, which coincide with indexes 0 and 1 in the format string.