Reputation: 9519
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.
Upvotes: 2
Views: 363
Reputation: 9519
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!
Upvotes: 2
Reputation: 9458
Have you considered registering validators in the AppHost.cs
?
// This method scans the assembly for validators
container.RegisterValidators(Assemblies);
Upvotes: 1