views:

2674

answers:

3

Hi.

I'd like some basic guidance on setting up my WCF configuration. This is my first serious effort with WCF (and first post on stackoverflow).

I have a WCF class library (APILibrary) that I am referncing in my web project. In the wcf library, I currently have two services - IAuthService and ITradeService.

Along these lines, I have three questions:

1) My problem (and the original reason for this post) is that when I compile my application I am able to call TradeServiceCient but not AuthServiceClient in my web app. The latter does not appear in the intellisense. I have a feeling that it has to do with the fact that they are sharing the same port (and only one endpoint got included) but I am obviously unclear.

2) I am attempting to expose two service endpoints at the same time (and, likely a few more) while I develop and test. When I move over to staging and hosting, each endpoint will have its own address. Until then, how do I do this (I have a feeling this relates to my question above)?

3) I am noticing in a lot of posts people have examples of the "client" and "server" "system.serviceModel" code. Are these unique files or tags in the App.config file that resides in my WCF library? What is each doing? Currently, I think I just have the server side?

Here is what I currently have in my App.config file (in my WCF Library):

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.web>
    <compilation debug="true" />
  </system.web>
  <!-- When deploying the service library project, the content of the config file must be added to the host's 
  app.config file. System.Configuration does not support config files for libraries. -->
  <system.serviceModel>
    <client />
    <services>
      <service behaviorConfiguration="ApiLibrary.ApiBehavior" name="SpoonSys.Api.Trade.TradeService">
        <endpoint address="" binding="wsHttpBinding" contract="SpoonSys.Api.Trade.ITradeService">
          <identity>
            <dns value="localhost:8731" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8731/Design_Time_Addresses/ApiLibrary/Trade/" />
          </baseAddresses>
        </host>
      </service>

      <service behaviorConfiguration="ApiLibrary.ApiBehavior" name="SpoonSys.Api.Authentication.AuthService">
        <endpoint address="" binding="wsHttpBinding" contract="SpoonSys.Api.Authentication.IAuthService">
          <identity>
            <dns value="localhost:8731" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8731/Design_Time_Addresses/ApiLibrary/Authentication/" />
          </baseAddresses>
        </host>
      </service>  
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ApiLibrary.ApiBehavior">
          <!-- To avoid disclosing metadata information, 
          set the value below to false and remove the metadata endpoint above before deployment -->
          <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" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

My configuration is ASP.NET / Framework 3.5 / VS 2008 / C#

I appreciate your help.

A: 

I only see a single contract there. Maybe you need to provide more detail?

John Saunders
+1  A: 

Yes, in your case, you're only dealing with the server side - so your config looks quite okay, actually.

The only thing I would change in your config is the split between "baseAddress" and the actual service address. You currently define the entire complete address in your base address - that kinda defeats the purpose of the base address. I would split it like so:

 <service name="SpoonSys.Api.Services"
          behaviorConfiguration="ApiLibrary.ApiBehavior" >
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:8731/Design_Time_Addresses/ApiLibrary/" />
      </baseAddresses>
    </host>
    <endpoint 
       address="Trade" 
       binding="wsHttpBinding" 
       contract="SpoonSys.Api.Trade.ITradeService">
      <identity>
        <dns value="localhost:8731" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>

That way, you could basically collapse your two endpoints into one - the base address defines just that - a common base for all other addresses - while the endpoint defines the details of the full address:

 <service name="SpoonSys.Api.Services"
          behaviorConfiguration="ApiLibrary.ApiBehavior" >
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:8731/Design_Time_Addresses/ApiLibrary/" />
      </baseAddresses>
    </host>
    <endpoint 
       address="Trade" 
       binding="wsHttpBinding" 
       contract="SpoonSys.Api.Trade.ITradeService">
      <identity>
        <dns value="localhost:8731" />
      </identity>
    </endpoint>
    <endpoint 
       address="Authentication" 
       binding="wsHttpBinding" 
       contract="SpoonSys.Api.Authentication.IAuthService">
      <identity>
        <dns value="localhost:8731" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>

This works if you have a single Service class "SpoonSys.Api.Services" that implements both of these service contracts - that's totally fine and quite useful at times.

IF you have to have two separate service classes, implementing one interface each, then you won't be able to collapse your config like this - then you'll have to use the full config for two separate service classes in your original post (which seemed fine to me).

The other question is why you only get to see one endpoint in your intellisense - did you create your client proxy for both endpoints? Since it's two separate contracts, you'll need two separate client proxies. How did you create your client endpoint? Can you post the client config, too?

Marc

marc_s
A: 

Hi and thanks.

I tried shortening the base address per your suggestion. I was then getting an error where one service would start, but not the other. I was being told that the metadata endpoint was already being used. I then tried changing my namespaces from SpoonSys.ApiLibrary.Authentication and SpoonSys.ApiLibrary.Trade to just SpoonSys.ApiLibary for all class files. Still - same error. When I changed back to my original server configuration it compiled. Still, the intellisense is only picking up one service, and not the other.

I am not sure what you mean about my client config file. I have not done anything particular with regard to WCF in my client app project (except inport the WCF class library as a web service reference). Maybe this is where I am going wrong? Could you tell me more here?

I have noticed a Client.dll in the WCF editor for each endpoint and have posted those below:

ENDPOINT:localhost:8731/Design_Time_Addresses/Authentication/mex

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_ITradeService" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                    messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                    allowCookies="false">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                    <reliableSession ordered="true" inactivityTimeout="00:10:00"
                        enabled="false" />
                    <security mode="Message">
                        <transport clientCredentialType="Windows" proxyCredentialType="None"
                            realm="" />
                        <message clientCredentialType="Windows" negotiateServiceCredential="true"
                            algorithmSuite="Default" establishSecurityContext="true" />
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="localhost:8731/Design_Time_Addresses/Trade/"
                binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ITradeService"
                contract="ITradeService" name="WSHttpBinding_ITradeService">
                <identity>
                    <dns value="localhost:8731" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>

ENDPOINT:http://localhost:8731/Design_Time_Addresses/Trade/mex

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_IAuthService" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                    messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                    allowCookies="false">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                    <reliableSession ordered="true" inactivityTimeout="00:10:00"
                        enabled="false" />
                    <security mode="Message">
                        <transport clientCredentialType="Windows" proxyCredentialType="None"
                            realm="" />
                        <message clientCredentialType="Windows" negotiateServiceCredential="true"
                            algorithmSuite="Default" establishSecurityContext="true" />
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="localhost:8731/Design_Time_Addresses/Authentication/"
                binding="wsHttp binding" bindingConfiguration="WSHttpBinding_IAuthService"
                contract="IAuthService" name="WSHttpBinding_IAuthService">
                <identity>
                    <dns value="localhost:8731" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>

AND Finally, here is my APP.CONFIG AGAIN:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.web>
    <compilation debug="true" />
  </system.web>
  <!-- When deploying the service library project, the content of the config file must be added to the host's 
  app.config file. System.Configuration does not support config files for libraries. -->
  <system.serviceModel>
    <services>
      <service behaviorConfiguration="ApiLibrary.ApiBehavior"
        name="SpoonSys.ApiLibrary.Trade.TradeService">
        <endpoint address="" binding="wsHttpBinding" contract="SpoonSys.Api.Trade.ITradeService">
          <identity>
            <dns value="localhost:8731" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8731/Design_Time_Addresses/Trade/" />
          </baseAddresses>
        </host>
      </service>
      <service behaviorConfiguration="ApiLibrary.ApiBehavior"
        name="SpoonSys.Api.Authentication.AuthService">
        <endpoint address="" binding="wsHttpBinding" contract="SpoonSys.ApiLibrary.Authentication.IAuthService">
          <identity>
            <dns value="localhost:8731" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="localhost:8731/Design_Time_Addresses/Authentication/" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ApiLibrary.ApiBehavior">
          <!-- To avoid disclosing metadata information, 
          set the value below to false and remove the metadata endpoint above before deployment -->
          <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" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Thanks again!

PS - I am getting "new users can only post a maximum of one hyperlink" when i try to submit my response so, i took out all "http://" references in my post. Its not a code error.

You should be updating your original question instead of posting an "answer" - this site is different than a forum.
Graham Clark