Question

I'm working with a 3rd party system that is only accessible through web and service references. While building a Windows Service that handles automated processing I have discovered that if web/service references are used by a solution, they must also be set up in any solution that references the first.

Is there a way to prevent this? I would like to make a class library that will hold all of the actual API calls and use that as a NuGet package without having to also add the references to every project down the road.

EDIT: Here's an example of how I call the API currently:

internal class ApiAccess
{
    private readonly Account_SSPSoapClient _apiAccount;

    public ApiAccess()
    {
        _apiAccount = new Account_SSPSoapClient();
    }

    public string GetAccountId(string accountName)
    {
        return _apiAccount.GetID(accountName);
    }
}
Was it helpful?

Solution

This is a problem, but it's not the problem that it appears to be.

You don't actually need the service reference in all projects which use your code - all you need is some information out of the app.config. Specifically, the binding and endpoint address. You can hardcode them into your code, and then you should be able to reference it just fine.

The simplest case:

var request = new MyServiceRequest { /* set properties here */ };
var client  = MyServiceReferenceClient(new BasicHttpBinding(), new EndpointAddress(@"https://my.service.com/path/to/service"));
var channel = client.ChannelFactory.CreateChannel();
var result  = channel.MyService(request);

You'll want to set some paramenters on the BasicHttpBinding to match what's in the app.config file, and the URL also comes out of there.

See this answer for why it doesn't work by default.


Edit: For your code, you'd just replace new Account_SSPSoapClient(); with something along the lines of:

new Account_SSPSoapClient(new BasicHttpBinding(), new EndpointAddress(@"https://my.service.com/path/to/service"));

Everything else should go the same, but it'll use those values instead of the app.config values (which is what it does with no parameters).

Look in the app.config file for something like:

    <bindings>
        <basicHttpBinding>
            <binding name="LabelRecoveryBinding" closeTimeout="00:01:00"
                openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                useDefaultWebProxy="true">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <security mode="None">
                    <transport clientCredentialType="None" proxyCredentialType="None"
                        realm="" />
                    <message clientCredentialType="UserName" algorithmSuite="Default" />
                </security>
            </binding>
        </basicHttpBinding>

Everything in that corresponds to a property you can set on the BasicHttpBinding object created above - most of it is the default values, but you may want to manually set everything just to be safe.

Likewise, look for

<client>
        <endpoint address="http://153.2.133.60:48010/xoltws_ship/LBRecovery"
            binding="basicHttpBinding" bindingConfiguration="LabelRecoveryBinding"
            contract="UPSLabelRecoveryService.LabelRecoveryPortType" name="LabelRecoveryPort" />
</client>

That tells you what URL to supply to the new EndpointAddress.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top