Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't my ChannelFactory see my endpoint configuration?

Tags:

wcf

I've been following Miguel Castro's excellent article on WCF here and it's all working nicely, except that I have the following code

public AdminClient()
{
    ChannelFactory<IProductAdmin> factory = new ChannelFactory<IProductAdmin>();
    productAdminChannel = factory.CreateChannel();
}

In my app.config file, I have the following configuration:

<system.serviceModel>
    <client>
        <endpoint address="net.tcp://localhost:8002/ProductBrowser"
                  binding="netTcpBinding"
                  contract="Contracts.IProductAdmin" />
    </client>
</system.serviceModel>

But, when I run the constructor for AdminClient I get an exception saying that the endpoint isn't defined. However, if I change my configuration to give the endpoint a name, and then create the factory as follows, it works.

public AdminClient()
{
    var fac = new ChannelFactory<IProductAdmin>("admin");
    productAdminChannel = fac.CreateChannel();
}

<system.serviceModel>
    <client>
        <endpoint name="admin" 
                  address="net.tcp://localhost:8002/ProductBrowser"
                  binding="netTcpBinding"
                  contract="Contracts.IProductAdmin" />
    </client>
</system.serviceModel>

I'd love an explanation for this. The documentation in MSDN isn't much help...

like image 709
Craig Shearer Avatar asked Jan 08 '09 21:01

Craig Shearer


4 Answers

Use "*" to use the first qualifying endpoint.

public AdminClient()
{
    ChannelFactory<IProductAdmin> factory  
         = new ChannelFactory<IProductAdmin>("*");

    productAdminChannel = factory.CreateChannel();
}

MSDN Example

like image 150
Sky Sanders Avatar answered Oct 11 '22 18:10

Sky Sanders


You need to specify the endpoint name, because you can have many endpoints for the same type of contract. (For instance a service being deployed on one tcp and one http ws endpoint). Microsoft could have of course built something in WCF to check if there is only one client specified for the contract interface, but that wouldn't have been very consistent. (that it would work if there is only one endpoint specified for the contract). When you would add another endpoint for the same contract later, the code would break in that case.

like image 38
Raymond Roestenburg Avatar answered Oct 11 '22 19:10

Raymond Roestenburg


You can get away without specifying endpoint name on service side. For client side, you need to specify the name, because you may be connecting to multiple services that have the same contract. How would WCF know then which one you want?

like image 31
Krzysztof Kozmic Avatar answered Oct 11 '22 18:10

Krzysztof Kozmic


This has been bugging me for a few days, so I went through the examples shown in the article you linked above. Everything works correctly except for the second client proxy example that you're having a problem with. As you noted and the other answerers creating a proxy in that way requires an endpoint name, coupling it with the client (which is where the endpoint is defined). I'm still not sure why it behaves the way it does, but I found no way to use that example without explicitly coupling the proxy to the endpoint.

On the other hand, the first example showing how to create the proxy requires no explicit coupling of endpoint address or binding:

 using System;
   using System.ServiceModel;

   namespace CoDeMagazine.ServiceArticle
   {
       public class ProductClient 
          : ClientBase<IProductBrowser>, 
            IProductBrowser
       {

           #region IProductBrowser Members

           public ProductData GetProduct(
              Guid productID)
           {
               return Channel.GetProduct(productID);
           }

           public ProductData[] GetAllProducts()
           {
               return Channel.GetAllProducts();
           }

           public ProductData[] FindProducts(
              string productNameWildcard)
           {
               return Channel.FindProducts(
                  productNameWildcard);
           }

           #endregion
       }

   }

That seems to work just fine. So, maybe the second proxy example is just a poor way to do things, or maybe we're missing something obvious...

like image 33
Tad Donaghe Avatar answered Oct 11 '22 20:10

Tad Donaghe