Question

I tried to make a secure wcf with custom userNamePasswordValidationMode service but I confronted some problems(for three days). My setup environment is visual studio 2012, .net 4.0, IIS Express. My service model in host is:

<system.serviceModel>
    <bindings >
      <wsHttpBinding>
        <binding maxReceivedMessageSize="65536" name="WsHttpBinding_ISurveyService">
          <security mode="TransportWithMessageCredential">
            <message clientCredentialType="UserName"/>
          </security>
          <readerQuotas   maxArrayLength="65536"
                          maxBytesPerRead="65536"
                          maxStringContentLength="65536"/>
        </binding>
      </wsHttpBinding>
    </bindings>
    <services>
      <!--name= "namespace.serviceClass"-->
      <service name="Rids.Services.SurveyService" behaviorConfiguration="Rids.WcfHost.ServiceBehavior" >
        <!--contract= "namespace.serviceClass"-->
        <endpoint address=""
                  binding="wsHttpBinding"
                  bindingConfiguration="WsHttpBinding_ISurveyService"
                  contract= "Rids.Services.ISurveyService">
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        <host>
          <baseAddresses>
            <add baseAddress="https://localhost" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="Rids.WcfHost.ServiceBehavior">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false" />
          <serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true" />
          <serviceCredentials>
            <clientCertificate>
              <authentication certificateValidationMode="None" />
            </clientCertificate>
            <userNameAuthentication userNamePasswordValidationMode="Custom"
                                    customUserNamePasswordValidatorType="Rids.WcfHost.ServiceUserValidator,Rids.WcfHost"/>

            <!--Specify the Certificate-->
            <serviceCertificate    findValue="rids_2014.04.15"
                               storeLocation="LocalMachine"
                                x509FindType="FindBySubjectName"
                                   storeName="My"/>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

When I want to add this service to client, it can not read the metadata and gave the error below:

There was an error downloading 'https://localhost:44300/SurveyService.svc/_vti_bin/ListData.svc/$metadata'.
Unable to connect to the remote server
Hedef makine etkin olarak reddettiğinden bağlantı kurulamadı 127.0.0.1:44300
Metadata contains a reference that cannot be resolved: 'https://localhost:44300/SurveyService.svc'.
There was no endpoint listening at https://localhost:44300/SurveyService.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
Unable to connect to the remote server
Hedef makine etkin olarak reddettiğinden bağlantı kurulamadı 127.0.0.1:44300
If the service is defined in the current solution, try building the solution and adding the service reference again.

--

But if I delete name tag from behavior(name="Rids.WcfHost.ServiceBehavior" part) and behaviorConfiguration tag from service (behaviorConfiguration="Rids.WcfHost.ServiceBehavior" part); then I can add the service(https://localhost:44300/SurveyService.svc) to client without error. Also this doesn't solve my problem.

After adding service to client, client service model was like below:

<system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_ISurveyService" />
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:11067/SurveyService.svc"
        binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ISurveyService"
        contract="Survey.ISurveyService" name="BasicHttpBinding_ISurveyService" />
    </client>
</system.serviceModel>

The problems I saw is:

  1. Client service model sees basicHttpBinding although my service binding configuration is wsHttpBinding.
  2. Client service model doesn't see ssl address although I added the service in the path: https://localhost:44300/SurveyService.svc.
  3. I can not add the service to client if service has the behaviorConfiguration tag and behavior has name tag in host configuration.
  4. Custom userNamePasswordValidationMode doesn't work and even if I add service to client without error, service doesn't see validation class or validation method. It works without validation.

Note: Service host project property of 'SSL Enabled' is True; and in project configuration project url is set to https://localhost:44300/.

I've encountered problems in problems. Any advice or solution? Thanks in advance.

Was it helpful?

Solution

I learned how to solve this problem. I made it using EditWcfConfiguration tool in visual studio 2012 as explained below.

Firstly, set property of 'SSL Enabled' as true in host project properties. Under this property automatically ssl url will be generated(such as 'https://localhost:44300/') Then, right click host project and select properties. In project properties Web tab, check 'Use Local IIS Web server' then check 'Use IIS Express'

-- In host project WebConfig, right click then select EditWcfConfiguration:

In EditWcfConfiguration firstly add service, then add a binding for endpoint of service, then add a behavior for service.

1- Add Service

  • Browse service type at host's bin folder
  • Select communication mode as HTTP
  • Select Advanced Web Service interoperability as Simplex communication
  • Leave the address blank
  • After adding behavior configuration; select BehaviorConfiguration
  • After adding binding configuration; open end point of service then, select binding(customBinding) and bindingConfiguration

2- Add a custom binding

  • Rename binding to use in service's BehaviorConfiguration property (such as 'custom_binding').
  • Add security, httpsTransport tags.
  • Select 'AuthenticationMode' as 'UserNameOverTransport' under security tag.

3- In Advanced/Service Behaviors folder, add new service behavior configuration

  • Rename behavior to use in service end point's BindingConfiguration property (such as safe_behavior).
  • Add serviceCredentials, serviceMetadata, serviceDebug tags.
  • For serviceCredentials tag properties:

    a-) Select customUserNamePasswordValidatorType as your validator class and its namespace (such as: 'Rids.WcfHost.ServiceUserValidator, Rids.WcfHost')

    b-) Select userNamePasswordValidationMode as custom

  • For clientCertificate tag(under serviceCredentials tag) properties, select certificateValidationMode as None and revocationMode as NoCheck

  • For serviceMetadata tag properties set HttpsGetEnabled as True
  • For serviceDebug tag properties set includeExceptionDetailInFaults as True

After these steps, resulting service model is:

<system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="safe_behavior">
          <serviceCredentials>
            <clientCertificate>
              <authentication certificateValidationMode="None" revocationMode="NoCheck" />
            </clientCertificate>
            <userNameAuthentication userNamePasswordValidationMode="Custom"
              customUserNamePasswordValidatorType="Rids.WcfHost.ServiceUserValidator, Rids.WcfHost" />
          </serviceCredentials>
          <serviceMetadata httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <customBinding>
        <binding name="custom_binding">
          <security authenticationMode="UserNameOverTransport" />
          <httpsTransport />
        </binding>
      </customBinding>
    </bindings>
    <services>
      <service behaviorConfiguration="safe_behavior" name="Rids.Services.Services.SurveyService">
        <endpoint address="" binding="customBinding"
          bindingConfiguration="custom_binding" contract="Rids.Services.Services.ISurveyService" />
      </service>
    </services>
  </system.serviceModel>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top