I have a service which is hosted in IIS. It is configured by Web.config.
I have created a custom UserNamePassValidator which works if I I have the logic in the validate method. But I want the logic in another project and injected in using DI as below.
public class UserNamePassValidator : System.IdentityModel.Selectors.UserNamePasswordValidator
{
    private readonly ISystemAuthentication _systemAuthentication;
    public UserNamePassValidator(ISystemAuthentication systemAuthentication)
    {
        _systemAuthentication = systemAuthentication;
    }
    public override void Validate(string userName, string password)
    {
        _systemAuthentication.Validate(userName, password))
    }
}
I am using the Autofac WCF integration.
var builder = new ContainerBuilder();
builder.RegisterType<AuthenticationService>().As<IAuthenticationService>();
builder.Register(c => new SystemAuthentication()).As<ISystemAuthentication>();
builder.Register(c => new UserNamePassValidator(c.Resolve<ISystemAuthentication>()));
AutofacHostFactory.Container = builder.Build();
When I browse to the service i receive the following error:
[MissingMethodException: No parameterless constructor defined for this object.]
web.config behaviour;
 <userNameAuthentication
                 userNamePasswordValidationMode="Custom"
                 customUserNamePasswordValidatorType="MyNamespace.UserNamePassValidator, service" />
I have read the following related post but the example is a self hosted service: How to inject an object into a WCF validator class
EDIT
  <system.serviceModel>
    <services>
      <service behaviorConfiguration="Namespace.AuthenticationServiceBehaviour" name="Namespace.AuthenticationService" >
        <endpoint address="" binding="wsHttpBinding" contract="Namespace.IAuthenticationService" bindingConfiguration="SafeServiceConf">
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="Namespace.AuthenticationServiceBehaviour">
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceCredentials>
            <serviceCertificate findValue="AuthenticationService" 
              storeLocation="LocalMachine"
              storeName="My" 
              x509FindType="FindBySubjectName" />
            <userNameAuthentication
              userNamePasswordValidationMode="Custom"
              customUserNamePasswordValidatorType="Namespace.UserNamePassValidator, Service" />
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <wsHttpBinding>
        <binding name="SafeServiceConf" maxReceivedMessageSize="65536">
          <readerQuotas maxStringContentLength="65536" maxArrayLength="65536" maxBytesPerRead="65536" />
          <security mode="Message">
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
SystemAuthentication class
public class SystemAuthentication : ISystemAuthentication
{
   public bool Validate(string userName, string password)
   {
       // removed code for abbreviation
       return true;
   }
WCF Authentication Service
public class AuthenticationService : IAuthenticationService
    { 
        public bool Authenticate(string email, string password)
        {
            // removed for abbreviation
            return true;
        }
    }
                From the help of this post UserNamePasswordValidator: When DI and Framework collide
From the XML configuraiton i removed:
<userNameAuthentication
   userNamePasswordValidationMode="Custom"
   customUserNamePasswordValidatorType="MyNamespace.UserNamePassValidator, service" />
I added the behaviour to the AutoFacHostFactory service host
   IContainer container = builder.Build();
    AutofacHostFactory.Container = container;
    AutofacHostFactory.HostConfigurationAction = host =>
    {
        var auth = host.Credentials.UserNameAuthentication;
        auth.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
        auth.CustomUserNamePasswordValidator = container.Resolve<UserNamePassValidator>();
    };
This works perfectly, but it would have been nicer to be able to do it from the web.config. If anyone knows a better way please post :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With