Search code examples
c#.netvalidationblazor-server-sideasp.net-core-6.0

Blazor Server App InputSelect Not Being Marked Invalid


Hope everyone is having a great day! I have been struggling with getting validation for an InputSelect component in a Blazor Server project using .NET Core 6.0

Provided is a screenshot taken from my browser, Chrome: enter image description here

Provided is my code for the validation that is being performed, I wrote my own custom validation attribute:

public class GuidSelectValidation : ValidationAttribute
{
    protected override ValidationResult? IsValid(object? value, ValidationContext? validationContext)
    {
        if (value != null)
        {
            if (value.Equals(new Guid()))
            {
                return new ValidationResult(ErrorMessage);
            }
            else
            {
                return ValidationResult.Success;
            }
        }
        else
        {
            return new ValidationResult(ErrorMessage);
        }
    }
}

This is the DTO I am utilizing to handle the data manipulation:

public class AddressData
{
    public Guid Id { get; set; }

    [Required(ErrorMessage = "The Primary Street Address is required.")]
    public string Address1 { get; set; } = string.Empty;

    public string Address2 { get; set; } = string.Empty;

    public string Address3 { get; set; } = string.Empty;

    [Required]
    public string City { get; set;} = string.Empty;

    [Required]
    public string State { get; set;} = string.Empty;

    [Required]
    public string Zip { get; set; } = string.Empty;

    [GuidSelectValidation(ErrorMessage = "You must select a county for the address.")]
    public Guid County { get; set; }

    public string Country { get; set; } = "US";

    [GuidSelectValidation(ErrorMessage = "You must select an address type for the address.")]
    public Guid AddressType { get; set; }
}

Provided is my markup on the page for this particular section:

<EditForm @ref="editForm" Model="@model">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <div class="row bottom-padding">
        <div class="col-lg-6 bottom-padding">
            <label class="form-label col-lg-5">Primary Street Address</label>
            <InputTextArea class="form-control" @bind-Value="model.Address1"></InputTextArea>
        </div>

        <div class="col-lg-6 bottom-padding">
            <label class="form-label col-lg-5">Secondary Street Address</label>
            <InputTextArea class="form-control" @bind-Value="model.Address2"></InputTextArea>
        </div>

        <div class="col-lg-6 bottom-padding">
            <label class="form-label col-lg-5">On Behalf Of</label>
            <InputTextArea class="form-control" @bind-Value="model.Address3"></InputTextArea>
        </div>

        <div class="col-lg-6 bottom-padding">
            <label class="form-label col-lg-3">City</label>
            <InputText class="form-control" @bind-Value="model.City"></InputText>
        </div>

        <div class="col-lg-6 bottom-padding">
            <label class="form-label col-lg-3">State</label>
            <InputText class="form-control" @bind-Value="model.State"></InputText>
        </div>

        <div class="col-lg-6 bottom-padding">
            <label class="form-label col-lg-3">Zip</label>
            <InputText class="form-control" @bind-Value="model.Zip"></InputText>
        </div>

        <div class="col-lg-6 bottom-padding">
            <label class="control-label">County</label>
            <InputSelect @bind-Value="model.County" class="form-control">
                @if (model.County == new Guid())
                {
                    <option value="@(new Guid())" selected>[Select County]</option>
                }
                else
                {
                    <option value="@(new Guid())">[Select County]</option>
                }
                @foreach (var county in counties)
                {
                    <option value="@county.Id">@county.CountyName</option>
                }
            </InputSelect>
        </div>

        <div class="col-lg-6 bottom-padding">
            <label class="control-label">Address Type</label>
            <InputSelect @bind-Value="model.AddressType" class="form-control">
                @if(model.AddressType == new Guid())
                {
                    <option value="@(new Guid())" selected>[Select Type]</option>
                }
                else
                {
                    <option value="@(new Guid())">[Select Type]</option>
                }
                @foreach (var type in addressTypes)
                {
                    <option value="@type.Id">@type.Name</option>
                }
            </InputSelect>
        </div>

        <button type="button" @onclick="() => OnDelete()" class="btn btn-danger">Delete Address</button>
    </div>
</EditForm>

@code {
    [Parameter]
    public AddressData model { get; set; }

    [Parameter]
    public List<RefCounty> counties { get; set; }

    [Parameter]
    public List<RefAddressType> addressTypes { get; set; }

    [Parameter]
    public EventCallback<AddressData> DeleteAddress { get; set; }

    [Parameter]
    public EventCallback<AddressData> modelChanged { get; set; }

    private async Task OnDelete()
    {
        await DeleteAddress.InvokeAsync(model);
    }

    private EditForm editForm;

    public bool CanSubmit()
    {
        return editForm.EditContext.Validate();
    }
}

Any clue on how I can get the InputSelect to be surrounded in red? Basically when inspecting the source it indicates that it is valid, but clearly it is not as I am throwing an error stating the information must be selected.

Any thoughts or suggestions would definitely be appreciated.

I have wrote my own validation method, but it still doesn't seem to be processing this correctly on the webpage or triggering that the input select is invalid within the EditForm.


Solution

  • You have to return the filed's name when it's invalid

    public class GuidSelectValidation : ValidationAttribute
    {
        protected override ValidationResult? IsValid(object? value, ValidationContext? validationContext)
        {
            if (value != null)
            {
                if (value.Equals(new Guid()))
                {
                    return new ValidationResult(ErrorMessage, new[] { validationContext.MemberName });
                }
                else
                {
                    return ValidationResult.Success;
                }
            }
            else
            {
                return new ValidationResult(ErrorMessage, new[] { validationContext.MemberName });
            }
        }
    }
    

    Now it works : enter image description here