Container.RegisterValidators no effect

q1:
1. container.RegisterValidators(typeof(UserValidator).Assembly); // no effect,AddressValidator not injected
2. container.Register<IAddressValidator>(new AddressValidator()); //this is ok, but no effect?

from “http://docs.servicestack.net/validation” there are two way RegisterValidators, but in my test
http://localhost:49018/api/users?age=-1&format=json will get {"Result":"Hello, !"} ,it is error?

q2:
“ServiceStack\src\ServiceStack\Platforms\PlatformNet.HostConfig.cs” line 157
private static string ExtractHandlerPathFromWebServerConfigurationXml(string rawXml)
{
return XDocument.Parse(rawXml).Root.Element(“handlers”)
.Descendants(“add”)
.Where(handler => EnsureHandlerTypeAttribute(handler).StartsWith(“ServiceStack”))
.Select(handler => handler.Attribute(“path”).Value)
.FirstOrDefault();
}
// this method will throw exceptions when meet below rawXml

  <system.webServer>
    <staticContent>
      <remove fileExtension=".woff2" />
      <mimeMap fileExtension=".woff2" mimeType="application/font-woff2" />
    </staticContent>
  </system.webServer>

Hi when you’re posting a question please provide enough context so we can see what’s happening, e.g. it’s not clear what “no effect, AddressValidator not injected” means, where’s your Service class that you’re trying to inject it into? how are you trying to use it? If something’s throwing an Exception please provide the full message and StackTrace.

You need to first register the ValidationFeature to be able to use it:

Plugins.Add(new ValidationFeature());

Then you can use the method below to register all validators in the assembly specified, e.g:

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

The validators are registered against their IValidator<T> interface which is what your properties need to be declared with in order for them get injected. If you have a validator registered against a Request DTO, e.g. IValidator<RequestDto> then it will automatically get executed against that Request DTO.

Any validators that are not for a Request DTO aren’t used by ServiceStack, presumably you’re going to use them manually in your custom validation logic. Make sure you’re trying to resolve the right type, e.g if your register manually with:

 container.Register<IAddressValidator>(new AddressValidator());

Then you need to retrieve it using the type it was registered against, e.g:

public IAddressValidator AddressValidator { get; set; }

If you’re just using RegisterValidators() to register your validator you need to resolve it using IValidator<T> interface, e.g:

public IValidator<Address> AddressValidator { get; set; }

For question 2, please provide the full Exception and StackTrace and Web.config you’re using as this fragment provided below isn’t a valid Web.config:

 <system.webServer>
    <staticContent>
      <remove fileExtension=".woff2" />
      <mimeMap fileExtension=".woff2" mimeType="application/font-woff2" />
    </staticContent>
  </system.webServer>

and without the Exception and StackTrace we have no chance to identify the issue you’re having.

    public override void Configure(Container container)
        {
            SetConfig(new HostConfig
            {
                HandlerFactoryPath = "api",
            });
            //Config examples
            //this.Plugins.Add(new PostmanFeature());
            //this.Plugins.Add(new CorsFeature());
            Plugins.Add(new ValidationFeature());
              container.RegisterValidators(typeof(UserValidator).Assembly);
            Plugins.Add(new AuthFeature(() => new AuthUserSession(),
      new IAuthProvider[] {
      
        new CredentialsAuthProvider(), //HTML Form post of UserName/Password credentials
      }) );
         
            //Set MVC to use the same Funq IOC as ServiceStack
            ControllerBuilder.Current.SetControllerFactory(new FunqControllerFactory(container));

    
        }
 public class MyServices : Service
    {
        public object Any(User request)
        {
            return new UserResponse { Result = "Hello, {0}!".Fmt(request.Name) };
        }
    }

    public interface IAddressValidator
    {
        bool ValidAddress(string address);
    }

    public class AddressValidator : IAddressValidator
    {
        public bool ValidAddress(string address)
        {
            return address != null
                && address.Length >= 20
                && address.Length <= 250;
        }
    }

    public class UserValidator : AbstractValidator<User>
    {
        public IAddressValidator AddressValidator { get; set; }

        public UserValidator()
        {
            //Validation rules for all requests
            RuleFor(r => r.Name).NotEmpty();
            RuleFor(r => r.Age).GreaterThan(0);
            RuleFor(x => x.Address).Must(x => AddressValidator.ValidAddress(x));

            //Validation rules for GET request
            RuleSet(ApplyTo.Get, () => {
                RuleFor(r => r.Count).GreaterThan(10);
            });

            //Validation rules for POST and PUT request
            RuleSet(ApplyTo.Post | ApplyTo.Put, () => {
                RuleFor(r => r.Company).NotEmpty();
            });
        }
    }
  [Route("/user")]
    [Route("/user/{Name}")]
    public class User : IReturn<UserResponse>
    {
        public string Name { get; set; }
        public string Company { get; set; }
        public int Age { get; set; }
        public int Count { get; set; }
        public string Address { get; set; }
    }

    public class UserResponse
    {
        public string Result { get; set; }
    }

this is my code , when I visit http://localhost:49018/api/user?Name=World&format=json it will get NullReferenceException due to AddressValidator is null in UserValidator
MySS.ServiceInterface.dll!MySS.ServiceInterface.UserValidator..ctor.AnonymousMethod__4_0 行 43 ServiceStack.dll!ServiceStack.FluentValidation.DefaultValidatorExtensions.Must.AnonymousMethod__0 行 175 ServiceStack.dll!ServiceStack.FluentValidation.DefaultValidatorExtensions.Must.AnonymousMethod__0 行 192 ServiceStack.dll!ServiceStack.FluentValidation.DefaultValidatorExtensions.Must.AnonymousMethod__0 行 209 ServiceStack.dll!ServiceStack.FluentValidation.Validators.PredicateValidator.IsValid 行 38 ServiceStack.dll!ServiceStack.FluentValidation.Validators.PropertyValidator.Validate 行 78 ServiceStack.dll!ServiceStack.FluentValidation.Internal.PropertyRule.InvokePropertyValidator 行 221 ServiceStack.dll!ServiceStack.FluentValidation.Internal.PropertyRule.Validate 行 193

for q2:

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=301880
  -->
<configuration>
  
  
    <appSettings>
        <add key="webpages:Version" value="3.0.0.0"/>
        <add key="webpages:Enabled" value="false"/>
        <add key="ClientValidationEnabled" value="true"/>
        <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
    </appSettings>

    <system.web>
        <compilation debug="true" targetFramework="4.5"/>
        <httpRuntime targetFramework="4.5"/>
    </system.web>

  <system.webServer>
    <staticContent>
      <remove fileExtension=".woff2" />
      <mimeMap fileExtension=".woff2" mimeType="application/font-woff2" />
    </staticContent>
  </system.webServer>
  
 
  
    <location path="api">
        <system.web>
            <httpHandlers>
                <add path="*" type="ServiceStack.HttpHandlerFactory, ServiceStack" verb="*"/>
            </httpHandlers>
        </system.web>

        <system.webServer>
            <modules runAllManagedModulesForAllRequests="true"/>
            <validation validateIntegratedModeConfiguration="false" />
            <urlCompression doStaticCompression="true" doDynamicCompression="false" />
            <handlers>
                <add path="*" name="ServiceStack.Factory"
                     type="ServiceStack.HttpHandlerFactory, ServiceStack" verb="*"
                     preCondition="integratedMode"
                     resourceType="Unspecified" allowPathInfo="true" />
            </handlers>
        </system.webServer>
    </location>
    
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0"/>
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect oldVersion="1.0.0.0-1.5.2.14234" newVersion="1.5.2.14234"/>
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect oldVersion="1.0.0.0-5.1.0.0" newVersion="5.1.0.0"/>
            </dependentAssembly>
        </assemblyBinding>
    </runtime>
</configuration>

ServiceStack.dll!ServiceStack.Platforms.PlatformNet.ExtractHandlerPathFromWebServerConfigurationXml(string rawXml) 行 159 ServiceStack.dll!ServiceStack.Platforms.PlatformNet.SetPathsFromConfiguration(ServiceStack.HostConfig config, System.Configuration.Configuration webConfig, string locationPath) 行 141 ServiceStack.dll!ServiceStack.Platforms.PlatformNet.InferHttpHandlerPath(ServiceStack.HostConfig config) 行 92 ServiceStack.dll!ServiceStack.Platforms.PlatformNet.InitHostConifg(ServiceStack.HostConfig config) 行 24 ServiceStack.dll!ServiceStack.HostConfig.NewInstance() 行 143 ServiceStack.dll!ServiceStack.HostConfig.ResetInstance() 行 27 ServiceStack.dll!ServiceStack.ServiceStackHost.Init() 行 176
I saw ExtractHandlerPathFromWebServerConfigurationXml throw exception in output window and I am not sure it will lead to anyproblem, so I ask for your help.

sorry for my poor english , thank you very much

So as I explained above, if you’re just using RegisterValidators to register your validators, e.g:

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

Then it needs to be resolved with IValidator<T>, e.g:

public IValidator<Address> AddressValidator { get; set; }

For the 2nd Exception it shouldn’t have any impact as it’s only used to inferring the HandlerFactoryPath which you’re setting manually to “api” anyway. But I’ve wrapped it behind a try/catch to prevent it bubbling in this commit available on next release but you shouldn’t need it since you’re setting it explicitly.

thank you for your patience , I add container.Register(new AddressValidator()); in AppHost.Configure and ResponseStatus prop in UserResponse , now it works

1 Like