1

We have a Windows Form, C#, .NET 4.5.1 application that calls a class library also in C# and 4.5.1. It's worked for years without a problem. This week when I tried to make a change I've run in to a strange error and a strange work around. I'd love to know what is going on if someone could explain it.

So the error I'm getting is on the main form. The error is "Could not find default endpoint element that references contract 'ShipService.IShipService' in the ServiceModel client confirmation section. This might be because no configuration file was found in your application, or because no endpoint element matching hihs contract could be found in the client element."

I've found multiple links (see here, here, and here) that say to make sure the config in your class library matches what's in your main program. I tried this and was still getting the error. I didn't find any other suggestions besides "check your config".

Here's where it gets odd. If I delete my local copy and download the code from the master branch, I'm able to run the program with no errors as long as I don't open MainForm.cs. So, I debugged it and found the error was in the business logic layer in this method:

public void ResetShipService()
{
    shipClient = new ShipServiceClient();
}

If I comment out the above, and instead create a new instance of ShipServiceClient instead of calling ResetShipService, everything works fine. The program runs and I can open MainForm.cs. I'm just moving it a different place in the same class. I have no idea why this works or what is going on here. Can someone explain what's going on and/or give me a better way of fixing this than just commenting out code and moving it somewhere else?

Here's the layout of what's involved:

ShippingService - class library
- Endpoint is net.tcp://localhost:9000/Shipping
- I have no access to change this class library

ShippingApplication - Windows Form Application
- Shipping - Main project
    - MainForm.cs - This is the form that shows the design time error
    - User controls
        - ItemsControl.cs - This is a user control in MainForm.cs that calls the business logic layer
- ShippingBusinessLogicLayer - Business logic layer
    - ShippingBLL.cs - Calls the ShippingService class library

Here's the error I'm getting: enter image description here

Here's the code in the BLL where the error is coming from:

public class ShipmentBLL
{
    private ShipServiceClient shipClient;

    public ShipmentBLL()
    {
        ResetShipService();
    }

    public void ResetShipService()
    {
        shipClient = new ShipServiceClient(); // If I comment out this, the design time error goes away
    }

    private ShipmentDTO processShipment (QuickShipmentDTO QuickShipmentDTO, bool TestShipment = false, bool RelieveInventory = true)
    {
        Ship ship = new Ship();

        if (shipClient.InnerChannel.State == System.ServiceModel.CommunicationState.Faulted)
        {
            ResetShipService(); 
        }

        ship = shipClient.ProcessShipment(ship, TestShipment);
    }
}

Here's the code in ItemsControl.cs that creates the instance of the BLL:

public partial class ItemsToShipControl : UserControl
{
    public ItemsToShipControl()
    {
        InitializeComponent();

        shipmentBLL = new ShipmentBLL();
    }
}

Here's code from MainForm.cs designer setting up the user control:

this.ItemsToShipPane = new NTSupply.NTShipping.UserControls.ItemsControl();
this.Controls.Add(this.ItemsToShipPane);
private UserControls.ItemsControl ItemsToShipPane;

Here's service model section of the app.config from the ShippingService:

<system.serviceModel>
    <bindings>
        <netTcpBinding>
            <binding name="longTimeoutBinding" receiveTimeout="00:30:00" sendTimeout="00:30:00">
            </binding>
        </netTcpBinding>
    </bindings>
    <services>
       <service behaviorConfiguration="ShippingServiceBehavior" name="NTSupply.Shipping.ShipService">
           <endpoint address="net.tcp://localhost:9000/Shipping" binding="netTcpBinding" bindingConfiguration="longTimeoutBinding"
      contract="NTSupply.Shipping.IShipService" />
           <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
           <host>
               <baseAddresses>
                  <add baseAddress="net.tcp://localhost:9000/Shipping" />
               </baseAddresses>
           </host>
      </service>
    </services>
<behaviors>
  <serviceBehaviors>
    <behavior name="ShippingServiceBehavior">
      <serviceMetadata/>
      <serviceDebug includeExceptionDetailInFaults="True" />
      <dataContractSerializer maxItemsInObjectGraph="65536" />
    </behavior>
  </serviceBehaviors>
    </behaviors>
</system.serviceModel>

Here's the app.config from the Shipping project:

<system.serviceModel>
    <bindings>
        <netTcpBinding>
            <binding name="NetTcpBinding_IShipService" sendTimeout="00:30:00" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647"/>
         </netTcpBinding>
    </bindings>
    <client>
        <endpoint address="net.tcp://192.168.1.12:9000/Shipping" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IShipService" contract="ShipService.IShipService" name="NetTcpBinding_IShipService">
        </endpoint>
     </client>
</system.serviceModel>

Here's the app.config from the BLL:

<system.serviceModel>
<bindings>
  <netTcpBinding>
    <binding name="NetTcpBinding_IShipService" />
  </netTcpBinding>
</bindings>
<client>
  <endpoint address="net.tcp://localhost:9000/Shipping" binding="netTcpBinding"
            bindingConfiguration="NetTcpBinding_IShipService" contract="ShipService.IShipService"
            name="NetTcpBinding_IShipService">
    <identity>
      <servicePrincipalName value="host/NTSUPSHIP.anthonymulinaro.local" />
    </identity>
  </endpoint>
</client>
</system.serviceModel> 
boilers222
  • 1,901
  • 7
  • 33
  • 71

1 Answers1

1

By default, when we invoke the service by adding service reference in the class library project, there might be something amiss during cooperating with the main project. The service proxy only uses the main project configuration (Appconfig) instead of the previous configuration that is auto-generated in the class library project. In order to make it work properly, we have to move the ServiceModel section in the class library project into the configuration file recognized by the hosting environment, namely the main project configuration file.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/deploying-a-wcf-library-project
In your actual scenario, the process of instance a client proxy will try to find the client endpoint, related binding property, etc. This might come to a trouble. We could use the name of the endpoint to instance the client proxy, provided that the configuration is recognized by the main project.

NetTcpBinding_IShipService

 ServiceReference1.Service1Client client = new  ServiceReference1.Service1Client("NetTcpBinding_IShipService");

Feel free to let me know if there is anything I can help with.

Abraham Qian
  • 7,117
  • 1
  • 8
  • 22
  • Thanks. That didn't do anything in my project. I changed the instantiation of the service client in the BLL to use the name of the endpoint and I got the same error. Here's the new code: shipClient = new ShipServiceClient("NetTcpBinding_IShipService"); – boilers222 Jun 20 '19 at 12:09
  • Does the BLL project is your main project or the class library project? if the class library, it won't work. you have to call the service properly by adding service reference in your main project. Have you tried to call the service in a separate a project(by adding service reference)? – Abraham Qian Jun 24 '19 at 09:27
  • The class library is in it's own solution (it's deployed and I have no access to change it). The solution I'm working on has a main project and a BLL project. The service is called from the BLL. There is a service reference in the BLL. – boilers222 Jun 24 '19 at 15:48
  • Then you got the error in your main project when you invoke the method that is defined in the BLL project, Do you? If it does, I suggest we could invoke the service in our main project instead of the BLL project. this is the simplest way to complete this. Alternatively, we could call it in the BLL project and copy the system.ServiceModel section of the BLL project’s config(app.config/web.config) to the main project. – Abraham Qian Jun 25 '19 at 02:54
  • Besides, we could invoke the service by using ChannelFactory, with which we could hardcode the service configuration in the code. It could not cause the configuration confusion. – Abraham Qian Jun 25 '19 at 03:03
  • https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-use-the-channelfactory – Abraham Qian Jun 25 '19 at 03:04
  • Thank you for the replies. I'm not sure what you're saying. The error I'm getting is in the main project when I open MainForm.cs in the designer. I've tried copying the ServiceModel section of the BLL project's config to the main project's config, but I get the same result. There seems to be something happening at design time that doesn't have the correct credentials, but I don't know how to trace it down. – boilers222 Jun 27 '19 at 18:29
  • I mean, we call the service directly in the main project, will this eliminate the exception? First remove the reference to the BLL project, then add a reference to the WCF service in the main project, can this solve the problem? – Abraham Qian Jul 01 '19 at 02:13
  • In my opinion, this is VS IDE problem. The designer does not load correctly because of the local cache. so I advise you to call the service by adding service reference in the main project instead of refer to the BLL project. Alternatively, we could also use ChannelFactory directly in the main project to invoke the service. Because its configuration is set up in code. – Abraham Qian Jul 01 '19 at 02:24