Question

I am implementing my own user registration service based on the built in RegistrationService, so I have copied most of it including the first few lines below...

        if (EndpointHost.RequestFilters == null
            || !EndpointHost.RequestFilters.Contains(ValidationFilters.RequestFilter)) //Already gets run
            RegistrationValidator.ValidateAndThrow(request, ApplyTo.Post);


        // Above line does not get hit as there is the ValidationFilters.RequestFilter
        //...but then the code should have previously run validation and failed?
        //...Adding the following line causes the validation to run and fail when expected
       //...but I should not required it as that is the point of the global ValidationFilters.RequestFilter??
        RegistrationValidator.ValidateAndThrow(request, ApplyTo.Post);

From what I understand the ValidationFilters.RequestFilter should have been hit earlier and my validation exception thrown.

N.B: I have put this line at the very end of my apphost configuration.

Plugins.Add(new ValidationFeature());

And I am successfully registering my validator, with this:

container.Register<AbstractValidator<UserRegistration>>(new UserRegistrationValidator());

...I have now narrowed it down to the following lines of ServiceStack source code in ValidatorCache.cs

public class ValidatorCache<T>
{
    public static IValidator GetValidator(IHttpRequest httpReq)
    {
        return httpReq.TryResolve<IValidator<T>>();
    }
}

...The TryResolve is not finding the validator.

Was it helpful?

Solution

I figured out that the validators were not resolving from the IOC container...rather than delve into this I took a step back and instead found out why the automatic registration method did not work for me previously.

The reason was I originally had this...

public interface IUserRegistrationValidator : IValidator<UserRegistration>
{
}

public class UserRegistrationValidator : AbstractValidator<UserRegistration>, IUserRegistrationValidator
{ //..etc

And ServiceStack code was tripping up on line shown below for obvious reasons (suggest friendly exception):

    public static void RegisterValidator(this Container container, Type validator, ReuseScope scope=ReuseScope.None)
    {
        var baseType = validator.BaseType;
        while (!baseType.IsGenericType) // WOULD FAIL ON THIS LINE HERE
        {
            baseType = baseType.BaseType;
        }

        var dtoType = baseType.GetGenericArguments()[0];
        var validatorType = typeof(IValidator<>).MakeGenericType(dtoType);

        container.RegisterAutoWiredType(validator, validatorType, scope);
    }

After getting rid of the pointless interfaces I was playing around with I can use the automatic method of registering validators...such as:

container.RegisterValidators(typeof(UserRegistrationValidator).Assembly);

Which resolves my issues, I am not 100% sure how I would manually register the UserValidator from https://github.com/ServiceStack/ServiceStack/wiki/Validation and have it work as I am still somewhat under impression that the following would not work properly.

container.Register<AbstractValidator<User>>(new UserValidator());

...I am likely wrong of course!

OTHER TIPS

Have you considered registering validators in the AppHost.cs?

// This method scans the assembly for validators
container.RegisterValidators(Assemblies);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top