title: WCF webservice with custom certificate validation
body: <p>I am hosting a WCF webservice with custom certificate validation, but I am not able to configure it properly. When I try to get the WSDL of the WebService, I get a compilation error below. What am I doing wrong?</p>
  
  <p>Thanks</p>
  
  <h1>Edit:</h1>
  
  <p>I've looked into: <a href="https://stackoverflow.com/questions/1559915/custom-certificate-validation-in-wcf-service">Custom certificate validation in WCF service</a> and <a href="https://msdn.microsoft.com/en-us/library/aa347699(v=vs.110).aspx" rel="nofollow noreferrer">authentication of clientCertificate Element</a> and <a href="https://msdn.microsoft.com/en-us/library/ms733806(v=vs.110).aspx" rel="nofollow noreferrer">How to: Create a Service that Employs a Custom Certificate Validator</a> and <a href="https://msdn.microsoft.com/en-us/library/aa354512.aspx" rel="nofollow noreferrer">X.509 Certificate Validator</a> and none of those links describe an issue  I am having.</p>
  
  <h1>Compilation Error message:</h1>
  
  <pre><code>Could not load file or assembly 'service' or one of its dependencies. The system cannot find the file specified.
  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.IO.FileNotFoundException: Could not load file or assembly 'service' or one of its dependencies. The system cannot find the file specified.
  Source Error: 
  An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
  </code></pre>
  
  <h1>web.config:</h1>
  
  <pre><code>  &lt;system.serviceModel&gt;
      &lt;bindings&gt;
        &lt;basicHttpBinding&gt;
          &lt;binding name="TransportSecurity"&gt;
            &lt;security mode="Message"&gt;
              &lt;message clientCredentialType="Certificate" /&gt;
            &lt;/security&gt;
          &lt;/binding&gt;
        &lt;/basicHttpBinding&gt;
      &lt;/bindings&gt;
      &lt;behaviors&gt;
        &lt;serviceBehaviors&gt;
          &lt;behavior name="MyServiceBehavior"&gt;
            &lt;serviceMetadata httpsGetEnabled="true" httpsGetUrl="" /&gt;
            &lt;serviceDebug includeExceptionDetailInFaults ="true"/&gt;
            &lt;serviceCredentials&gt;
              &lt;clientCertificate&gt;
                &lt;authentication certificateValidationMode="Custom" customCertificateValidatorType = "MyProject.MyX509CertificateValidator, service"/&gt;
              &lt;/clientCertificate&gt;
              &lt;serviceCertificate findValue="hashvalue" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" /&gt;
            &lt;/serviceCredentials&gt;
          &lt;/behavior&gt;
        &lt;/serviceBehaviors&gt;
        &lt;endpointBehaviors&gt;
          &lt;behavior name="clientBehavior"&gt;
            &lt;clientCredentials&gt;
              &lt;serviceCertificate&gt;
                &lt;authentication certificateValidationMode="Custom"  customCertificateValidatorType="MyProject.MyX509CertificateValidator, client"/&gt;
              &lt;/serviceCertificate&gt;
            &lt;/clientCredentials&gt;
          &lt;/behavior&gt;
        &lt;/endpointBehaviors&gt;
      &lt;/behaviors&gt;
      &lt;services&gt;
        &lt;service name="MyProject.MyProjectWCF" behaviorConfiguration="MyServiceBehavior"&gt;
          &lt;endpoint address="" binding="basicHttpBinding" bindingConfiguration="TransportSecurity" contract="MyProject.IMyProjectWCF" /&gt;
          &lt;endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" /&gt;
        &lt;/service&gt;
      &lt;/services&gt;
    &lt;/system.serviceModel&gt;
  </code></pre>
  
  <h1>  WCF code:</h1>
  
  <pre><code>Imports System.ServiceModel
  Imports System.ServiceModel.Description
  Imports System.IdentityModel.Selectors
  Imports System.Security.Cryptography.X509Certificates
  Imports System.IdentityModel.Tokens
  Imports System.ServiceModel.Security
  
  Namespace MyProject
      ' NOTE: You can use the "Rename" command on the context menu to change the class name "MyProjectWCF" in code, svc and config file together.
      &lt;ServiceBehavior()&gt; _
      Public Class MyProjectWCF
          Implements IMyProjectWCF
  
          Public Function HelloWorld() As String Implements IMyProjectWCF.HelloWorld
              Return "nameSpace: [" + Me.GetType().Namespace + "]" + vbNewLine + "Normal response"
          End Function
  
          Sub New()
              Dim serviceHost As New ServiceHost(GetType(MyProjectWCF))
              Try
                  serviceHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.Custom
                  serviceHost.Credentials.ClientCertificate.Authentication.CustomCertificateValidator = New MyX509CertificateValidator("CN=MyCertificate")
                  serviceHost.Open()
                  'serviceHost.Close()
              Finally
                  'serviceHost.Close()
              End Try
          End Sub
      End Class
  
      Public Class MyX509CertificateValidator
          Inherits X509CertificateValidator
          Private allowedIssuerName As String
  
          Public Sub New(ByVal allowedIssuerName As String)
              If allowedIssuerName Is Nothing Then
                  Throw New ArgumentNullException("allowedIssuerName")
              End If
              Me.allowedIssuerName = allowedIssuerName
          End Sub
  
          Public Overrides Sub Validate(ByVal certificate As X509Certificate2)
              ' Check that there is a certificate.
              If certificate Is Nothing Then
                  Throw New ArgumentNullException("certificate")
              End If
              ' Check that the certificate issuer matches the configured issuer.
              If allowedIssuerName &lt;&gt; certificate.IssuerName.Name Then
                  Throw New SecurityTokenValidationException _
                    ("Certificate was not issued by a trusted issuer")
              End If
          End Sub
      End Class
  End Namespace
  </code></pre>
  
  <h1>Interface code:</h1>
  
  <pre><code>Imports System.ServiceModel
  Imports System.Security.Permissions
  
  Namespace MyProject
      ' NOTE: You can use the "Rename" command on the context menu to change the interface name "IMyProjectWCF" in both code and config file together.
      &lt;ServiceContract([Namespace]:="MyProject")&gt; _
      Public Interface IMyProjectWCF
          &lt;OperationContract()&gt; _
          Function HelloWorld() As String
      End Interface
  End Namespace
  </code></pre>
  
  <h1>  EDIT 2 (with fix):</h1>
  
  <p>Insert default constructor into the cert validator class:</p>
  
  <pre><code>    Public Sub New()
          Me.New("CN=yourCertificate here")
      End Sub
  </code></pre>
  
  <p>And then I had to figure out what the project name of my website is, which is App_Code, it gets compiled with a bunch of other pages into one DLL, which is APP_Code.dll. The final line in web.config looks like this:</p>
  
  <pre><code>&lt;authentication certificateValidationMode="Custom" customCertificateValidatorType="MyProject.MyX509CertificateValidator, App_Code"/&gt;
  </code></pre>
  
  <p>So now there are no compiled errors and I get my WSDL. Thank you for your help :)</p>