Blazored / FluentValidation

A library for using FluentValidation with Blazor
https://blazored.github.io/FluentValidation/
MIT License
587 stars 84 forks source link

System.TypeLoadException: Unable to locate a validator #16

Closed tjackadams closed 4 years ago

tjackadams commented 4 years ago

I'm just having a few problems with this library and nested types.

I have the following page

@page "/courses/create"
@namespace ContosoUniversity.Blazor.Courses.Pages

<h2>Create</h2>

<ContosoSpinLoader IsLoading="@(Departments == null)">
    <ContentTemplate>
        <h4>Course</h4>
        <hr />
        <div class="row">
            <div class="col-md-4">

                <EditForm Model="@Data" OnValidSubmit="HandleValidSubmit">
                    <FluentValidationValidator />
                    <ValidationSummary />

                    <div class="form-group">
                        <Label For="@(() => Data.Number)"></Label>
                        <InputNumber class="form-control" @bind-Value="@Data.Number" />
                    </div>

                    <div class="form-group">
                        <Label For="@(() => Data.Title)"></Label>
                        <InputText class="form-control" @bind-Value="@Data.Title" />
                    </div>

                    <div class="form-group">
                        <Label For="@(() => Data.Credits)"></Label>
                        <InputNumber class="form-control" @bind-Value="@Data.Credits" />
                    </div>

                    <div class="form-group">
                        <Label For="@(() => Data.Department)"></Label>
                        <ContosoInputSelect class="form-control" @bind-Value="@Data.Department.Id">
                            @foreach (var department in Departments)
                            {
                                <option value="@department.Id">@department.Name</option>
                            }
                        </ContosoInputSelect>
                    </div>

                    <div class="form-group">
                        <button type="submit" class="btn btn-primary">Create</button>
                    </div>
                </EditForm>
            </div>
        </div>

    </ContentTemplate>
</ContosoSpinLoader>

<div>
    <a href="courses">Back to List</a>
</div>

However, when i change the drop down list for the departments, i get the following exception (taken from the browser console)

blazor.server.js:15 [2020-02-06T17:39:01.855Z] Error: System.TypeLoadException: Unable to locate a validator of type FluentValidation.IValidator`1[[ContosoUniversity.Domain.UniversityAggregate.Department, ContosoUniversity.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] or FluentValidation.AbstractValidator`1[[ContosoUniversity.Domain.UniversityAggregate.Department, ContosoUniversity.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]
   at Blazored.FluentValidation.EditContextFluentValidationExtensions.GetValidatorForModel(IServiceProvider serviceProvider, Object model)
   at Blazored.FluentValidation.EditContextFluentValidationExtensions.ValidateField(EditContext editContext, ValidationMessageStore messages, FieldIdentifier fieldIdentifier, IServiceProvider serviceProvider, IValidator validator)
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__139_0(Object state)
   at Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext.ExecuteSynchronously(TaskCompletionSource`1 completion, SendOrPostCallback d, Object state)
   at Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext.<>c.<.cctor>b__23_0(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext.ExecuteBackground(WorkItem item)

And i can't seem to work out how to fix this issue. The validator for the form looks like this

        public class Validator : AbstractValidator<Command>
        {
            public Validator()
            {
                RuleFor(p => p.Number).NotEmpty();

                RuleFor(p => p.Title)
                    .SetValidator(new TitleValidator());

                RuleFor(p => p.Credits)
                    .SetValidator(new CreditsValidator());
            }
        }

Which means i don't want/need to validate on the department field. If i add a blank validator in for the department, its seems to work ok.

        public class Validator : AbstractValidator<Command>
        {
            public Validator()
            {
                RuleFor(p => p.Number).NotEmpty();

                RuleFor(p => p.Title)
                    .SetValidator(new TitleValidator());

                RuleFor(p => p.Credits)
                    .SetValidator(new CreditsValidator());

                RuleFor(p => p.Department)
                    .SetValidator(new DepartmentValidator());
            }
        }

        public class DepartmentValidator : AbstractValidator<Department>
        {
            public DepartmentValidator()
            {

            }
        }

Any ideas why this would be happening? I've tried debugging it but the debug tools for blazor are lacking a bit at the moment.

Cheers Tom

chrissainty commented 4 years ago

The short answer is, I'm not sure.

I'll try and have a look at this in the next week and get back to you.

NatanBagrov commented 4 years ago

@tjackadams It is similar to #8 - as you said, Department is another entity...