4
votes

I am trying to use fluent validation in ServiceStack. I've added the validation plugin and registered my validator.

    Plugins.Add(new ValidationFeature());
    container.RegisterValidators(typeof(CreateLeaveValidator).Assembly);

I have implemented a validator class for my service model:

public class CreateLeaveValidator : AbstractValidator<CreateLeave>
{
    public CreateLeaveValidator()
    {
        RuleFor(cl => cl.StudentId).NotEmpty();
        RuleFor(cl => cl.LeaveDepart).NotEmpty().GreaterThan(DateTime.Now).WithMessage("Leave must begin AFTER current time and date.");
        RuleFor(cl => cl.LeaveReturn).NotEmpty().GreaterThan(cl => cl.LeaveDepart).WithMessage("Leave must end AFTER it begins.");
        RuleFor(cl => cl.ApprovalStatus).Must( status => ( ("P".Equals(status)) || ("C".Equals(status)) || ("A".Equals(status)) || ("D".Equals(status)) ) );
    }
}

Service Model:

   [Route("/leaves", "POST")]
    public class CreateLeave : IReturn<LeaveResponse>, IUpdateApprovalStatus
    {
        public int StudentId { get; set; }
        public DateTime RequestDate { get; set; }
        public DateTime LeaveDepart { get; set; }
        public DateTime LeaveReturn { get; set; }
        public string Destination { get; set; }
        public string HostRelationship { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string Postal { get; set; }
        public string Hostphone { get; set; }
        public string Cellphone { get; set; }
        public string Transport { get; set; }
        public string Driver { get; set; }
        public string Companions { get; set; }
        public string Reason { get; set; }
        public string ApprovalStatus { get; set; }
        public DateTime ApprovalDate { get; set; }
        public string ApprovalComment { get; set; }
        public string ApprovalReason { get; set; }
        public int ApprovalUser { get; set; }
    }

But when I create a request with no StudentId or an invalid ApprovalStatus, the validator does not appear to fire and catch the invalid request.

How can I go about troubleshooting the cause of this?

UPDATE: Correction it appears validators are working with my actual service but not in my unit tests. I'm guessing I must not be configuring my apphost correctly in the unit test setup. Here's my test constructor:

public LeaveTests()
    {
        Licensing.RegisterLicense(@"[license key]");

        appHost = new BasicAppHost(typeof(ApiServices).Assembly).Init();
        ServiceStack.Text.JsConfig.DateHandler = ServiceStack.Text.DateHandler.ISO8601;
        appHost.Plugins.Add(new ValidationFeature());            
         appHost.Container.RegisterValidators(typeof(CreateLeaveValidator).Assembly);

    }
1

1 Answers

4
votes

ServiceStack Validation filters are executed in a Global Request Filter which require a full integration test to run, e.g:

public class MyIntegrationTests
{
    ServiceStackHost appHost;
    public MyIntegrationTests()
    {
        appHost = new AppHost()
            .Init()
            .Start("http://localhost:8000/");
    }

    [OneTimeTearDown] void OneTimeTearDown() => appHost.Dispose();

    [Test]
    public void Execute_validation_filters()
    {
        var client = new JsonServiceClient("http://localhost:8000/");

        try
        {
            var response = client.Post(new CreateLeave { ... });
        }
        catch(WebServiceException ex) 
        {
            //...
        }
    }
}