Search code examples
c#wcfwindows-serviceswcf-binding

Client can't find endpoint element of WCF Inside Windows Service


I'm trying to put a WCF service inside a Windows Service. I used svcutil to use the CalculatorService.cs and output.config. I put the contents of the output.config into the App.config and write a client, including the CalculatorService.cs into it. When it runs, I get the error, "Could not find default endpoint element that references contract 'IAnswerResult' in the ServiceModel client configuration section". In my client, I've just copied what the wizard said to use:

protected void Page_Load(object sender, EventArgs e)
{
AnswerResultClient client = new AnswerResultClient(); // error here
client.QuestionAnswered("1", "2", "3");
}

In App.config of the client (generated) I have the following but it tells me that the contract "IAnswerResult" is invalid. I don't know why... it's what was generated by svcutil.

  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_IAnswerResult" />
      </basicHttpBinding>
      <netTcpBinding>
        <binding name="NetTcpBinding_IAnswerResult" />
      </netTcpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:6255/CalculatorService" binding="basicHttpBinding"
          bindingConfiguration="BasicHttpBinding_IAnswerResult" contract="IAnswerResult"
          name="BasicHttpBinding_IAnswerResult" />
      <endpoint address="net.tcp://localhost:6256/CalculatorService"
          binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IAnswerResult"
          contract="IAnswerResult" name="NetTcpBinding_IAnswerResult">
        <identity>
          <servicePrincipalName value="host/Server2012" />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>

Code in the Windows Service/WCF Service:

namespace EternaService
{
    [ServiceContract(Namespace = "http://EternaService")]

    public interface IAnswerResult
    {
        [OperationContract]
        string QuestionAnswered(string person_int, string course_int, string lesson_int);
    }


    public class CalculatorService : IAnswerResult
    {
        public string QuestionAnswered(string person_int, string course_int, string lesson_int)
        {
            string result = "";
            // Have input, now do something with it.
            return result;
        }

    }

    public partial class EternaService : ServiceBase
    {
        public ServiceHost serviceHost = null;

        public EternaService()
        {
            this.CanStop = true;
            this.CanHandlePowerEvent = true;
            this.CanHandleSessionChangeEvent = true;
            this.CanPauseAndContinue = true;
            this.CanShutdown = true;

            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {

            if (serviceHost != null)
            {
                serviceHost.Close();
            }
            serviceHost = new ServiceHost(typeof(CalculatorService));
            serviceHost.Open();
        }

App.config in the Windows Service/WCF Service:

<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
    </startup>
  <system.serviceModel>
    <services>
      <service name="EternaService.CalculatorService" behaviorConfiguration="myServiceBehave">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:6255/CalculatorService"/>
            <add baseAddress="net.tcp://localhost:6256/CalculatorService"/>
          </baseAddresses>
        </host>
        <endpoint address="http://localhost:6255/CalculatorService" binding="basicHttpBinding" contract="EternaService.IAnswerResult" />
        <endpoint address="net.tcp://localhost:6256/CalculatorService" binding="netTcpBinding" contract="EternaService.IAnswerResult" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="myServiceBehave">
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Any direction greatly appreciated. This is my first attempt and I'm lost!

EDIT: I changed the Windows service ServiceContract namespace to:

[ServiceContract(Namespace = "http://CADEEternaService")]

In the client CalculatorService class:

[System.ServiceModel.ServiceContractAttribute(Namespace= "http://CADEEternaService", ConfigurationName="IAnswerResult")]
public interface IAnswerResult
{

    [System.ServiceModel.OperationContractAttribute(Action= "http://CADEEternaService/IAnswerResult/QuestionAnswered", ReplyAction= "http://CADEEternaService/IAnswerResult/QuestionAnsweredResponse")]
    string QuestionAnswered(string person_int, string course_int, string lesson_int);

    [System.ServiceModel.OperationContractAttribute(Action= "http://CADEEternaService/IAnswerResult/QuestionAnswered", ReplyAction= "http://CADEEternaService/IAnswerResult/QuestionAnsweredResponse")]
    System.Threading.Tasks.Task<string> QuestionAnsweredAsync(string person_int, string course_int, string lesson_int);
}

In the client's app.config:

  <endpoint address="http://localhost:6255/CalculatorService" binding="basicHttpBinding"
      bindingConfiguration="BasicHttpBinding_IAnswerResult" contract="CADEEternaService.IAnswerResult"
      name="BasicHttpBinding_IAnswerResult" />
  <endpoint address="net.tcp://localhost:6256/CalculatorService"
      binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IAnswerResult"
      contract="CADEEternaService.IAnswerResult" name="NetTcpBinding_IAnswerResult">

But it's still flagging "CADEEternaService.IAnswerResult" as an error and I'm also getting the original error, "Could not find default endpoint element that references contract 'IAnswerResult'"... however, I find it odd that it's barking at IAnswerResult and not CADEEternaService.IAnswerResult in the error message.


Solution

  • You need to add the namespace of your Service Reference generated, before the contract .... contract="xxxxxxx.IAnswerResult

     <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_IAnswerResult" />
      </basicHttpBinding>
      <netTcpBinding>
        <binding name="NetTcpBinding_IAnswerResult" />
      </netTcpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:6255/CalculatorService" binding="basicHttpBinding"
          bindingConfiguration="BasicHttpBinding_IAnswerResult" contract="**xxxxx.IAnswerResult**"
          name="BasicHttpBinding_IAnswerResult" />
      <endpoint address="net.tcp://localhost:6256/CalculatorService"
          binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IAnswerResult"
          contract="IAnswerResult" name="NetTcpBinding_IAnswerResult">
        <identity>
          <servicePrincipalName value="host/Server2012" />
        </identity>
      </endpoint>
    </client>