Regression after upgrading from ServiceStack 8.0 to 8.1.2

Just after upgrading, what is working before is not working anymore.
I tried removing ValidationFeature from configuration but the same error appears in another part.

I am using ServiceStack.NetFramework and .NET Framework 4.8

Server Error in '/' Application.
Le type utilisé dans l'expression TypeAs doit être de type référence ou Nullable, System.Boolean n'est aucun de ces deux types
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.ArgumentException: Le type utilisé dans l'expression TypeAs doit être de type référence ou Nullable, System.Boolean n'est aucun de ces deux types

Source Error:


Line 196:
Line 197:            // This method scans the assembly for validators
Line 198:            Container.RegisterValidators(typeof(CustomerService).Assembly);
Line 199:            Container.RegisterServices(ReuseScope.None);
Line 200:            

Source File: D:\Projects\gecko\src\gui\Ksm.Gecko.Gui.WebMvc\AppHost.cs    Line: 198

Stack Trace:


[ArgumentException: Le type utilisé dans l'expression TypeAs doit être de type référence ou Nullable, System.Boolean n'est aucun de ces deux types]
   System.Linq.Expressions.Expression.TypeAs(Expression expression, Type type) +2808899
   Funq.<>c__DisplayClass141_0.<CreateServiceCollectionFactory>b__1(ParameterInfo x) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack/Funq/Container.ServiceCollection.cs:62
   System.Linq.WhereSelectArrayIterator`2.MoveNext() +58
   System.Linq.Buffer`1..ctor(IEnumerable`1 source) +204
   System.Linq.Enumerable.ToArray(IEnumerable`1 source) +79
   Funq.Container.CreateServiceCollectionFactory(Type type) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack/Funq/Container.ServiceCollection.cs:60
   Funq.Container.CreateFactory(ServiceDescriptor item) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack/Funq/Container.ServiceCollection.cs:31
   Funq.Container.Add(ServiceDescriptor item) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack/Funq/Container.ServiceCollection.cs:120
   ServiceStack.ServiceCollectionExtensions.Add(IServiceCollection services, Type serviceType, Type implementationType, ServiceLifetime lifetime) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack/ServiceCollectionExtensions.cs:86
   ServiceStack.Validation.ValidationExtensions.RegisterValidator(IServiceCollection services, Type validator, ServiceLifetime lifetime) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack/Validation/ValidationFeature.cs:509
   ServiceStack.Validation.ValidationExtensions.RegisterValidators(IServiceCollection services, ReuseScope scope, Assembly[] assemblies) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack/Validation/ValidationFeature.cs:467
   ServiceStack.Validation.ValidationExtensions.RegisterValidators(IServiceCollection services, Assembly[] assemblies) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack/Validation/ValidationFeature.cs:457
   Ksm.Gecko.Gui.WebMvc.AppHost.Configure(Container container) in D:\Projects\gecko\src\gui\Ksm.Gecko.Gui.WebMvc\AppHost.cs:198
   ServiceStack.ServiceStackHost.Init() in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack/ServiceStackHost.cs:279
   Ksm.Gecko.Gui.WebMvc.MvcApplication.Application_Start() in D:\Projects\gecko\src\gui\Ksm.Gecko.Gui.WebMvc\Global.asax.cs:64

[HttpException (0x80004005): Le type utilisé dans l'expression TypeAs doit être de type référence ou Nullable, System.Boolean n'est aucun de ces deux types]
   System.Web.HttpApplicationFactory.EnsureAppStartCalledForIntegratedMode(HttpContext context, HttpApplication app) +10092311
   System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +123
   System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context) +181
   System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +228
   System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +314

[HttpException (0x80004005): Le type utilisé dans l'expression TypeAs doit être de type référence ou Nullable, System.Boolean n'est aucun de ces deux types]
   System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +10072228
   System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +99
   System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +263

Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.8.9191.0

Please provide steps to Repro.

The problem occurs inside this ServiceStack function

    public static void RegisterValidators(this IServiceCollection services, ReuseScope scope, params Assembly[] assemblies)
    {
        Init(assemblies);
        var validatorTypesSnapshot = ValidatorTypes.ToArray();
        var lifetime = scope.ToServiceLifetime();
        foreach (var validatorType in validatorTypesSnapshot)
        {
            services.RegisterValidator(validatorType, lifetime); // <-- HERE
        }
    }

The validators are registering correctly until I came across a Validator with a constructor having a boolean parameter.

i.e.:

    public sealed class CustomerProformaInvoiceItemValidator : CustomerDocumentItemBaseValidator<CustomerProformaInvoiceItem>
    {
        public CustomerProformaInvoiceItemValidator(bool isVaf)
        {
             RuleFor(p => p.Id).GreaterThan(0);
             RuleFor(p => p.ExpectedDeliveryDate).Null().When(p=> isVaf);
             RuleFor(p => p.ExpectedDeliveryDate).NotNull().When(p => !isVaf && !p.SerialNumberOrArticle.IsNullOrEmpty() && p.ArticleId.IsNullOrEmpty());
        }
    }

When removing the boolean parameter of the constructor, the RegisterValidators does not throw an Exception anymore.
With ServiceStack v.8.0 this code was working.

It’s trying to Register an AutoWired Validator which needs to create with the only constructor available which it can’t resolve because there’s bool dependency registered (nor should there be) so it will never be able to be registered as an AutoWired dependency.

You can try adding a parameterless constructor which it’s able to use instead:

public sealed class CustomerProformaInvoiceItemValidator : CustomerDocumentItemBaseValidator<CustomerProformaInvoiceItem>
{
    public CustomerProformaInvoiceItemValidator() : this(false) {}
    public CustomerProformaInvoiceItemValidator(bool isVaf)
    {
         RuleFor(p => p.Id).GreaterThan(0);
         RuleFor(p => p.ExpectedDeliveryDate).Null().When(p=> isVaf);
         RuleFor(p => p.ExpectedDeliveryDate).NotNull().When(p => !isVaf && !p.SerialNumberOrArticle.IsNullOrEmpty() && p.ArticleId.IsNullOrEmpty());
    }
}

I’m assuming this was never autowired, how was it being used?

The latest v8.1.3+ release wont try to auto register a validator that’s been manually registered, I’ve also added a [IgnoreServices] attribute to ignore auth registering dependencies discovered through assembly scanning.

[IgnoreServices]
public sealed class CustomerProformaInvoiceItemValidator {}

Also I’m not sure how this was registered before but I’ve added an overload to manually register a validator, e.g:

services.RegisterValidator(c => new TestValidationValidator(true));

These changes are available from v8.1.3+ that’s now available in pre-release packages.

1 Like

Thank you very much!

It was never autowired, it is called by another (parent) validator

1 Like