views:

843

answers:

3

I have searched and searched and I cannot find a solution. It seems like it would be relatively common to run into this... WCF REST service over https. When I add the service reference all of the proxy classes are correct and I can create the objects defined in the service, call the services, etc. However, I can't create a configured client with the proxy's client classes. I have to explicity create the bindings, behaviors, and endpoints and add them to the client. FOr example, what I should be able to do, based on all of my research is:

ServiceClient = new ServiceClient();

And be off and running. However, what I have to do is:

WebHttpBinding serviceBinding = new WebHttpBinding(WebHttpSecurityMode.Transport);
serviceBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
EndpointAddress endPointAddress
            = new EndpointAddress(<endpointaddress>);

// Create Service Client 
ServiceClient = new ServiceClient(serviceBinding, endPointAddress);

// Add Web Behavior to the EndPoint
WebHttpBehavior webHttpBehavior = new WebHttpBehavior();
ServiceClient.Endpoint.Behaviors.Add(webHttpBehavior);

// Set up the request to POST with a wrapped request
WebInvokeAttribute postAttribute = new WebInvokeAttribute();
postAttribute.Method = "POST";
postAttribute.BodyStyle = WebMessageBodyStyle.WrappedRequest;
ServiceClient.Endpoint.Contract.Operations.Find(<operationname>).Behaviors.Add(postAttribute);

In order to mimic the service configuration:

<behaviors>
      <endpointBehaviors>
        <behavior name="AspNetAjaxBehaviorXml">
          <webHttp />
        </behavior>
      </endpointBehaviors>
       <serviceBehaviors>
          <behavior name="AuthenticationServicesBehavior">
            <serviceMetadata httpsGetEnabled="true" policyVersion="Policy15" />
            <serviceDebug includeExceptionDetailInFaults="true" />
          </behavior>
          <behavior name="LoggingServicesBehavior">
             <serviceMetadata httpsGetEnabled="true" policyVersion="Policy15" />
             <serviceDebug includeExceptionDetailInFaults="true" />
          </behavior>
       </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="True" />
    <bindings>
      <webHttpBinding>
        <binding name="WebSslBinding">
          <security mode="Transport">
            <transport clientCredentialType="None" />
          </security>
        </binding>
      </webHttpBinding>
    </bindings>
    <services>
       <service behaviorConfiguration="AuthenticationServicesBehavior"
          name="AuthenticationServices">
          <endpoint address="authenticate" behaviorConfiguration="AspNetAjaxBehaviorXml"
             binding="webHttpBinding" bindingConfiguration="WebSslBinding"
             name="AuthenticationEndPoint" bindingNamespace="<mynamespace>"
             contract="IService" />
       </service>

The "Add Service Reference" is giving me this:

<bindings>
   <customBinding>
    <binding name="AuthenticationEndPoint">
     <!--    WsdlImporter encountered unrecognized policy assertions in ServiceDescription 'EchoAppsServices':    -->
     <!--    <wsdl:binding name='AuthenticationEndPoint'>    -->
     <!--        <sp:HttpsToken xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"&gt;..&lt;/sp:HttpsToken&gt;    -->
     <textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
      messageVersion="Soap12" writeEncoding="utf-8">
      <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
       maxBytesPerRead="4096" maxNameTableCharCount="16384" />
     </textMessageEncoding>
    </binding>
   </customBinding>
  </bindings>
  <client>
   <endpoint binding="customBinding" bindingConfiguration="AuthenticationEndPoint"
    contract="AuthenticationService"
    name="AuthenticationEndPoint" />
  </client>

I believe my inability to create a default client that works out of the box is related to the problem with WsdlImporter. I get a similar error when I use svcutil:

Warning: The following Policy Assertions were not Imported:
  XPath://wsdl:definitions[@targetNamespace='<mynamespace>']/wsdl:binding[@na
me='AuthenticationEndPoint']
  Assertions:
    <sp:HttpsToken xmlns:sp='http://schemas.xmlsoap.org/ws/2005/07/securitypolic
y'>..</sp:HttpsToken>

I'm sure it has something to do with my self signed cert, but I can't get makecert to give me a functioning cert with a CA that doesn't cause my IIS to crash.

Environment details: VS2008 XP 64bit .NET 3.5 IIS6

Thanks in advance for any help...

A: 

If you want to create client proxy classes, why would you use webHttpBinding. Why not just use wsHttpBinding?

The whole point of webHttpBinding was so that you could use standard Http toolkits like HttpWebRequest and Microsoft.Http.HttpClient on the client to access the service.

Darrel Miller
A: 

You bring up a good point, but I started down this road to make a RESTful web service that can be called either from the client or the server. I can call it from both right now just the way it is but I have to explicitly configure the server side. This is unacceptable because this application will be deployed to multiple end users and it's easier to change a configuration file than it is to patch. I know that I could create multiple endpoints, but I would much rather only have to maintain one per service. Thank you for your reply.

GunnerL3510
marc_s - Thanks for your insight. It is kind of a typo, I have been going back and forth trying to get this to work and you caught something that was between iterations. It is supposed to be Windows authentication. I thought my problem might have been authentication mode related, but it wasn't.The reason that I'm trying to avoid any kind of manual settings is because I want to be able to update from the WSDL but I can't right now because of the above errors.
GunnerL3510
A: 

Not sure if that's just a typo - but your code and config don't match.

See in your code:

serviceBinding.Security.Transport.ClientCredentialType = 
      HttpClientCredentialType.Windows;

but in your config:

<webHttpBinding>
    <binding name="WebSslBinding">
      <security mode="Transport">
        <transport clientCredentialType="None" />
      </security>
    </binding>
</webHttpBinding>

In code, you set your HttpClientCredentialType to Windows (integrated Windows authentication), but in config, you set it to None.

Try changing your config to use Windows as well:

      <security mode="Transport">
        <transport clientCredentialType="Windows" />
      </security>

and try again.

If you don't get any better results : why not just update the client config manually, after the import? The WSDL importer is known to have hiccups here and there, and most often, just using your brain and manual config adaption can solve the problem. You basically just need to copy the <endpointBehaviors> and the <bindings> sections into your client side config and define a <client> section which references the appropriate endpoint - that's pretty much all.

marc_s
marc_s - Please see the below comments... For some reason I don't have a comment's block when I view this page from my Droid.
GunnerL3510