m.Opis, "", new { @class = "control-label text-danger" }) Model prop" /> m.Opis, "", new { @class = "control-label text-danger" }) Model prop" /> m.Opis, "", new { @class = "control-label text-danger" }) Model prop"/>

How to add validated field length to @Html.ValidationMessageFor client validation message?

378 views Asked by At

I have a "Description" TextArea field on my form.

@Html.ValidationMessageFor(m => m.Opis, "", new { @class = "control-label text-danger" })

Model property has following attributes:

[Display(Name = nameof(Global.Opis), ResourceType = typeof(Global))]
[Required]
[MaxLength(500)]
public string Opis { get; set; }

It renders as the following html:

<textarea class="form-control input-validation-error" cols="20" data-val="true" data-val-length="Pole Opis musi być ciągiem o maksymalnej długości 500." data-val-length-max="500" data-val-required="[Opis]: Pole musi być wypełnione." id="Opis" name="Opis" rows="5" aria-describedby="Opis-error" aria-invalid="true"></textarea>
<span class="control-label text-danger field-validation-error" data-valmsg-for="Opis" data-valmsg-replace="true"><span id="Opis-error" class="">[Opis]: Pole musi być wypełnione.</span></span>

It validates fine however I want to change the client-side message template for it to show also the current length of the Description field. Something like:

Maximum length of Description field is 500. You've entered 510 characters.

I've tried to add a custom attribute derived from MaxLengthAttribute however it seems like this solution is only for server-side validation as the debugger doesn't hit the IsValid method.

public class MaxLengthWithLengthMessageAttribute : MaxLengthAttribute
    {
        public MaxLengthWithLengthMessageAttribute(int maximumLength) : base(maximumLength)
        {
        }

        public override bool IsValid(object value)
        {
            string input = Convert.ToString(value);

            if (input.Length > base.Length)
                base.ErrorMessage =
                    $"Pole może zawierać maksymalny ciąg {base.ErrorMessage} znaków. Wprowadzono {input.Length} znaków.";

            return base.IsValid(value);
        }
    }


    public class MaxLengthWithLengthMessageValidator : DataAnnotationsModelValidator
    {
        private string _errorMessage = "Pole może zawierać maksymalny ciąg #1 znaków. Wprowadzono #2 znaków.";
        private MaxLengthWithLengthMessageAttribute _attribute;

        public MaxLengthWithLengthMessageValidator(ModelMetadata metadata, ControllerContext context, MaxLengthWithLengthMessageAttribute attribute) : base(metadata, context, attribute)
        {
            _attribute = attribute;
        }

        public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
        {
            var rule = new ModelClientValidationRule
            {
                ErrorMessage = this._errorMessage,
                ValidationType = "maxlength"
            };
            rule.ValidationParameters.Add("max", _attribute.Length);
            yield return rule;
        }
    }

How do you go about it?

1

There are 1 answers

1
Nagib Mahfuz On

You can customize StringLengthAttribute Class like below

public class MyStringLengthAttribute : StringLengthAttribute
{
public MyStringLengthAttribute(int maximumLength)
    : base(maximumLength)
{
}

public override bool IsValid(object value)
{
    string val = Convert.ToString(value);
    
    if (val.Length > base.MaximumLength)
        base.ErrorMessage = String.Format("Maximum length of Description field is {0}. You've entered {1} characters.",base.MaximumLength,val.Length);
    return base.IsValid(value);
}
}