I've been working on creating a self hosted application server in F#. I have the app server up and running and I can connect using a C# client, but some of the things that I want to do are better served using F#. The problem is that I can't seem to get the F# client to work properly. I've found a few examples, but I can't seem to get any of them to work. The most promising is here. Following that example I came up with the following code:
let address= new EndpointAddress("net.tcp://192.168.101.100:2009/PrevisionService/tcp")
let factory = new ChannelFactory<IPrevisionAppServer>("NetTcpBinding_IPrevisionAppServer", address)
let channel = factory.CreateChannel()//address)
let GetDataObject (sql) = channel.GetDataObject(sql)
factory.Close()
but I get the following error:
Could not find endpoint element with name 'NetTcpBinding_IPrevisionAppServer' and contract 'PrevisionAppServer.Main+IPrevisionAppServer' 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 name could be found in the client element.
I do have an app.config file, and it works just fine in C#:
<?xml version="1.0" encoding="utf-8"?>
<!--Client Config-->
<configuration>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_IPrevisionAppServer" closeTimeout="00:01:00"
openTimeout="00:20:00" receiveTimeout="01:00:00" sendTimeout="01:00:00"
hostNameComparisonMode="StrongWildcard"
maxBufferSize="2147483647"
maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://192.168.101.100:2009/PrevisionService/tcp" behaviorConfiguration="ServiceViewEventBehavior"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IPrevisionAppServer"
contract="*" name="NetTcpBinding_IPrevisionAppServer">
</endpoint>
</client>
<behaviors>
<endpointBehaviors>
<behavior name="ServiceViewEventBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>`
For whatever reason, it seems to be ignoring the app.config file. Any ideas? Is there better code to get this working? Any would be appreciated!
UPDATE: Okay, I feel stupid, but I failed to notice that I was running this in a test client that also had a C# UI as the startup, therefore the app.config is in the C# project. So, now the questions becomes, how to I apply the C# app.config to the F# project (I need it this way)? Meaning, I don't really want to code all the getting and setting of properties from the app settings to code. Ideas?
I dunno what the contract="*"
thing is (maybe some newer feature of WCF). Anyway the
'PrevisionAppServer.Main+IPrevisionAppServer'
bit in the diagnostic, where is this type defined? (F# code, C# code, a reference DLL, what?) It looks like a nested type, I wonder if that is affecting things too... I am just fishing.
(The app.config and diagnostics have never been WCF's strongest attribute, sigh.)
Unfortunately, getting F# and App.config to work together is super tricky. See this question for some help on the subject.
Given the hassle configuring F# can be, I suggest you build the whole proxy by hand in code, either setting all of the binding properties manually using in-code literals, or loading and parsing a separate configuration file and setting the binding/behavior properties from values in that file.
I would recommend doing it in a C# assembly with a simple static factory method that your F# code could reference and call to obtain a proxy.
Edit
Well, ignore the above advice, unless you're running in the interpreter. @kvb has the right of that.
That said... looking over your config file... I don't think <endpoint contract="*">
will work; I'm pretty sure you'll have to explicitly specify the contract for client endpoints.
Try this instead:
<endpoint address="net.tcp://192.168.101.100:2009/PrevisionService/tcp" behaviorConfiguration="ServiceViewEventBehavior"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IPrevisionAppServer"
contract="Correct.Namespace.IPrevisionAppServer" name="NetTcpBinding_IPrevisionAppServer">
</endpoint>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With