1
votes

I cannot get Windsor WCF facility to generate client endpoints without them being explicitly defined in the Web/App.config file.

My contracts, clients, and callbacks were generated as a service reference, and I want to register everything programmatically without using config files. However, I am receiving this error when the endpoint information is not present in the App/Web.config:

Error: Could not find default endpoint element that references contract 'ServiceReference1.IWcfContract' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.

Registration

Component.For<IWcfContract>()
    .ImplementedBy<WcfContractClient>()
    .AsWcfClient(new DefaultClientModel(
        WcfEndpoint
            .ForContract<IWcfContract>()
            .BoundTo(MyConfig.NetTcpBinding)
            .At(MyConfig.WcfHostAddressAndPort)),
    .LifestyleTransient());
Component.For<IWcfContractClientFactory>()
    .AsFactory(new WcfContractClientFactorySelector())

Typed Factory

IWcfContractCreate(WcfContractClientCallback callback);
void Release(IWcfContractinstance);

Factory Selector

public class WcfContractClientFactorySelector : DefaultTypedFactoryComponentSelector
{
    protected override IDictionary GetArguments(MethodInfo method, object[] arguments)
    {
        Arguments args = new Arguments();
        args.Add("callbackInstance", new InstanceContext(arguments[0]));
        return args;
    }
}

Resolving the Client

IWcfContractClientFactory factory = container.Resolve<IWcfContractClientFactory>();
IWcfContract client = factory.Create(new WcfContractClientCallback());

At this point, if I have the endpoint information in the Web/App.config file, then everything works fine. If I take it out, I receive the error mentioned above. Thanks!

1
What is MyConfig? Seems like that would have something to do with it if it's trying to go to the App.config.Patrick Quirk
It's binding and endpoint addresses that can be shared between the service and the client. That way I'm not updating multiple config files every time I make a change.Steven
The issue is actually that it won't read from MyConfig. It's either App/Web.config or nothing.Steven
Just to be sure, you're not removing the addresses that MyConfig points to, right? Maybe if you posted a small part of the App.config that shows what you're removing (commented out) and what MyConfig points to. Is MyConfig your class, or a 3rd party class?Patrick Quirk
Ah, I just figured it out. It's an auto-generated ServiceContractAttribute on the service reference contract interface which is pointing to the App/Web.config file. I've removed it, but now have other errors. I'll post an answer shortly.Steven

1 Answers

0
votes

This issue was caused by the client constructors in the auto-generated service reference class. The client has five constructors, four of which are looking for configuration files. For some reason, Windsor's WCF facility was using those constructors. Also, those constructors are in a class that is marked as DebuggerStepThrough, so the exception was being hidden from the debugger.

The resolution was to get Windsor to use the last constructor, which does not need a config file, but I had to remove the .AsWcfClient. If anybody knows of a way to use .AsWcfClient without running into this constructor issue, please post another answer and I will accept it. Thanks.

Service Reference Constructors

    public SearchServiceContextClient(InstanceContext callbackInstance)
    public SearchServiceContextClient(InstanceContext callbackInstance, string endpointConfigurationName)
    public SearchServiceContextClient(InstanceContext callbackInstance, string endpointConfigurationName, string remoteAddress)
    public SearchServiceContextClient(InstanceContext callbackInstance, string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress)
    public SearchServiceContextClient(InstanceContext callbackInstance, Binding binding, EndpointAddress remoteAddress)

Registration

Component.For<IWcfContract>()
    .ImplementedBy<WcfContractClient>()
    .DependsOn(new
    {
        binding = MyConfig.NetTcpBinding,
        remoteAddress = new EndpointAddress(MyConfig.WcfHostAddressAndPort)
    })
.LifestyleTransient()),
Component.For<IWcfContractClientFactory>()
    .AsFactory(new WcfContractClientFactorySelector())