0

Here's my custom validator:

public class CustomRuleFileTypeAttribute : ValidationAttribute
{
        protected override ValidationResult IsValid(object value,ValidationContext validationContext)
        {
            var pdfProperty = validationContext.ObjectType.GetProperty("Pdf");
            var stepProperty = validationContext.ObjectType.GetProperty("Step");
            var dwgProperty = validationContext.ObjectType.GetProperty("Dwg");
    
            bool isPdfSelected = pdfProperty != null && (bool?) pdfProperty.GetValue(validationContext.ObjectInstance) == true;
            bool isStepSelected = stepProperty != null &&
                                  (bool?) stepProperty.GetValue(validationContext.ObjectInstance) == true;
            bool isDwgSelected =
                dwgProperty != null && (bool?) dwgProperty.GetValue(validationContext.ObjectInstance) == true;
    
            if (!isPdfSelected && !isStepSelected && !isDwgSelected)
            {
                return new ValidationResult(ErrorMessage);
            }
    
            return ValidationResult.Success;
        }
    }

And here's the Ticket class:

public partial class Ticket
{
    [Required(ErrorMessage = "Dieses Feld ist erforderlich!")]
    public string? Kunde { get; set; }
    [CustomRuleFileType(ErrorMessage = "Bitte wählen Sie mindestens 1 Dateiformat aus")]
    public bool? Pdf { get; set; }
    [CustomRuleFileType(ErrorMessage = "Bitte wählen Sie mindestens 1 Dateiformat aus")]
    public bool? Step { get; set; }
    [CustomRuleFileType(ErrorMessage = "Bitte wählen Sie mindestens 1 Dateiformat aus")]
    public bool? Dwg { get; set; }
}

And here's part of my EditForm:

<EditForm Model="@Ticket" OnValidSubmit="@SendTicket" id="homeForm">
    <DataAnnotationsValidator/>
    <div class="sectionGeneral">
        <div>
            <label for="inputKunde">Kunde*</label><br/>
            <input type="text" id="inputKunde" @bind-value="Ticket.Kunde">
            <ValidationMessage For="@(() => Ticket.Kunde)"/>
        </div>
        <div>
            <label>Format*</label><br/>
            <label class="labelItem">
                <input type="checkbox" @bind="Ticket.Pdf" class="checkbox"/>
                <ValidationMessage For="@(() => Ticket.Pdf)" />
                <div class="option_inner">
                    <div class="name">PDF</div>
                </div>
            </label>
            <label class="labelItem">
                <input type="checkbox" @bind="Ticket.Step" class="checkbox"/>
                <ValidationMessage For="@(() => Ticket.Step)" />
                <div class="option_inner">
                    <div class="name">Step</div>
                </div>
            </label>
            <label class="labelItem">
                <input type="checkbox" @bind="Ticket.Dwg" class="checkbox"/>
                <ValidationMessage For="@(() => Ticket.Dwg)" />
                <div class="option_inner">
                    <div class="name">DWG</div>
                </div>
            </label>
        </div>
    </div>
    </div>

The ErrorMessage for e.g. Ticket.pdf (or the other types) isn't displayed, but the custom validation works. It get's displayed in the ValidationSummary though. The ValidationMessage for "Kunde" is displayed (not custom).

2
  • 2
    Add the dotnet version and especially the rendermode. Also, when is the summary updated? Commented Apr 23 at 15:11
  • .NET 8.0., rendermode=InteractiveServer OnValidSubmit="@SendTicket" In this method, that's where the validation takes place Commented Apr 23 at 15:15

1 Answer 1

0

You could try using the overload that specifies the field that the error applies to, for example:

rather than this:

            if (!isPdfSelected && !isStepSelected && !isDwgSelected)
            {
                return new ValidationResult(ErrorMessage);
            }

You could try this overload
https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.validationresult.-ctor?view=net-9.0#system-componentmodel-dataannotations-validationresult-ctor(system-string-system-collections-generic-ienumerable((system-string)))

i,.e.

     var errorFields = new List<string>();
     if (!isPdfSelected)
     {
         errorFields.Add(nameof(Ticket.Pdf)});
     }
     if (!isStepSelected)
     {
         errorFields.Add(nameof(Ticket.Step)});
     }            
     if (!isDwgSelected)
     {
         errorFields.Add(nameof(Ticket.Dwg)});
     }

     if(errorFields.Any())
     {
          return new ValidationResult(ErrorMessage, errorFields.ToArray();
     }

Although, as you are validating across a combination of fields, so it may be neater to implement IValidatableObject as per this answer here: https://stackoverflow.com/a/6075732/30012070 as that would then allow you to specify the error message once, but highlight the relevant fields with the above overload.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.