Determine wsHttpBinding at runtime with WCF - wcf

I have a web application that exposes web services using WCF and wsHttpBindings. It is possible to have the application on different machines and different urls. This would mean the WCF service location would be different for each.
I am building a Windows Service that will reference each application and perform a task. Each task needs to call a service on the web application. I understand that the bindings are all setup in the app.config, but is there a simpler way to call the service dynamically, or how would I structure the app.config?
<webApplication WebServiceUrl="http://location1.com/LunarChartRestService.svc" />
<webApplication WebServiceUrl="http://location2.com/LunarChartRestService.svc"/>

Your client's config file could look something like this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint name="Endpoint1"
address="http://location1.com/LunarChartRestService.svc"
binding="wsHttpBinding"
contract="(whatever-your-contract-is)" />
<endpoint name="Endpoint2"
address="http://location2.com/LunarChartRestService.svc"
binding="wsHttpBinding"
contract="(whatever-your-contract-is)" />
<endpoint name="Endpoint3"
address="http://location3.com/LunarChartRestService.svc"
binding="wsHttpBinding"
contract="(whatever-your-contract-is)" />
</client>
</system.serviceModel>
</configuration>
Then in code, you can create such an endpoint (client proxy) based on its name and thus you can pick whichever location you need. There's nothing stopping you from creating multiple client proxies, either! So you can connect to multiple server endpoints using multiple client proxies, no problem.
Alternatively, you can of course also create an instance of "WsHttpBinding" and "EndpointAddress" in code, and set the necessary properties (if any), and then call the constructor for the client proxy with this ready made objects, thus overriding the whole app.config circus and creating whatever you feel is needed:
EndpointAddress epa =
new EndpointAddress(new Uri("http://location1.com/LunarChartRestService.svc"));
WSHttpBinding binding = new WSHttpBinding();
Marc

From your description, it sounds as if all servers are exposing the same service contract. If so, you could very well just declare multiple endpoints in your web.config and choose one at runtime based on the endpoint name.
Of course, it may be that you prefer not to deal with that part of the WCF configuration and would rather just have a simpler list of URLs and be done with it. That's perfectly possible as well; you just need to do a little bit more work on the code side to instantiate the client side proxies / channel objects.

Related

Do the WCF timeouts on server side bindings have any relevance?

I host a WCF Service on IIS and have the following binding in web.config:
<bindings>
<wsHttpBinding>
<binding name="transactionalBinding"
transactionFlow = "true"
sendTimeout = "00:00:01"
receiveTimeout = "00:00:01"
openTimeout = "00:00:01"
closeTimeout = "00:00:01">
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
</security>
</binding>
</wsHttpBinding>
</bindings>
In my service method I sleep for 10 seconds. I do not get a timeout exception when calling my service method from a client.
Is there any meaning in defining timeouts in server side bindings?
I do not get a timeout exception when calling my service method from a client.
TL;DR: because WCF timeouts by default are one minute so naturally a server operation that only takes 10 seconds isn't going to timeout. The timeouts you have specified on the server would only affect transmission not execution of your method. (you aren't calling anything else)
You are specifying the timeouts in the server config. What you need to do is specify the timeouts in the client's config file, specifically SendTimeout. Essentially whatever end is making the call, needs to specify the operation timeout. Probably not relevant in your case but if your "server" in turn made another WCF call to another service, you would want your own timeout there too.
MSDN:
SendTimeout – used to initialize the OperationTimeout, which governs the whole process of sending a message, including receiving a reply message for a request/reply service operation. This timeout also applies when sending reply messages from a callback contract method.
Generally, WCF client and server configs should match one another and unless you are using Add Service Reference/Refresh Service Reference each time the server contracts and/or config change, the client won't know about it. By the way, avoid the latter because it duplicates your model and can lead to runtime errors if they are out of sync. Not to mention service contracts can get out of sync.
A passing thought
And this brings up one of the problems of WCF configuration via config files, they are subject to runtime errors impossible to find at compile time.
A better practice is to do away with config files completely and do programatic configuration via a common assembly that both your client and server use. Specify bindings in code along with your timeouts.
That way both server and client are always in sync with regards to WCF configuration.
With both client and server agreeing on timeouts would have addressed some issues.
Tell me more
WCF the Manual Way… the Right Way

WCF / WebService to act as Listener for MQ Message?

Perhaps I am barking up the wrong tree - but I have a set of services (WebAPI and WCF) that use WebSphere MQ to interact with other systems.
This works without issue - until I now need to find a way of listening for messages on one of the queues.
Is this even possible, or do I need to go down the windows Service route?
You could write a Windows service that is continually calling MQ Get on the queue, and invokes a WCF service to process the message. Or you could write a trigger program (a console application) that MQ will launch for you when a message arrives, that invokes the WCF service.
I might be just better at googling than you are, but I seem to have found the answer here.
Seems you want to load the IBM binding configuration in you app.config
<extensions>
<bindingElementExtensions>
<add name="IBM.XMS.WCF.SoapJmsIbmTransportChannel"
type="IBM.XMS.WCF.SoapJmsIbmTransportBindingElementConfig, IBM.XMS.WCF, Version=7.5.0.0, Culture=neutral, PublicKeyToken=8c7c0be90afcd8ba"/>
</bindingElementExtensions>
</extensions>
Then you can add a WebSphere WCF binding config.
<bindings>
<customBinding>
<binding name="CustomBinding_WMQ">
<textMessageEncoding messageVersion="Soap11" />
<IBM.XMS.WCF.SoapJmsIbmTransportChannel />
</binding>
</customBinding>
</bindings>
Your problem can be broken down into two distinct elements:
How to integrate MQ with a WCF-supported transport
How to expose a WCF endpoint over this transport
To address the first issue, you should look at the MQ-MSMQ bridge which ships with Host Integration Server up to version 2009 (not R2), which allows you to have messages delivered to MQSeries queues forwarded to local MSMQs in windows. Although this feature is deprecated it's probably the easiest way if you have a MSDN license.
Another way of addressing this issue is to use BizTalk server which ships with a MQSeries adapter, though unless you're using BizTalk currently in your enterprise I would avoid.
The last way you could do this is to program directly against the MQSeries .NET client libraries or via the XMS client.
If you manage to solve the first issue then solving the second one is easy enough. You can expose one way WCF service operations over msmq transport by using the netMsmqBinding (for WCF on both ends), or msmqIntegrationBinding for clients using System.Messaging or native msmq COM libraries.
This in-effect acts as a listener service, with messages being handled by the service operation.
how to get connect with ibm websphere mq by using c#.net
Perhaps you could use the above answer and within that queue consumer app create a "Service Reference" to your WCF service.

Connect to a single WCF service with two different endpoint bindings

I am new to WCF and (I hope) I'm having a "noob" problem. I searched the site and did not find the answer I'm looking for. I apologize if this has already been answered and I missed it.
I am programmaticly connecting to my service using a ChannelFactory. The problem I'm having is that the client cannot connect to my first service endpoint, unless I comment out the second one (the MSMQ one). Hopefully that helps.
The contracts are different, and I'm specifying the correct bindings (WSDualHttpBinding and NetMsmqBinding, respectively) on the client-side.
Please let me know if there is a way to fix this, or if more information is required.
I appreciate the help.
Tyler
<services>
<service behaviorConfiguration="DefaultBehavior" name="[intentionally removed]">
<endpoint
address="[intentionally removed]"
behaviorConfiguration="DefaultEndpointBehavior"
binding="wsDualHttpBinding"
bindingConfiguration="DualBinding"
name="WrapperEndpoint"
contract="[intentionally removed]"
/>
<endpoint
address="[intentionally removed]"
behaviorConfiguration="DefaultEndpointBehavior"
binding="netMsmqBinding"
bindingConfiguration="MsmqBinding"
name="MsmqEndpoint"
contract="[intentionally removed]"
/>
</service>
</services>
This topic might be related: http://social.msdn.microsoft.com/Forums/is/wcf/thread/643371b4-00a7-472b-8bea-3055f2eb90ed
I don't think you can have a single service with 2 different contracts. I think when you have both endpoints, WCF is just failing to start up properly, but when you comment out 1 endpoint, then it works fine because all endpoints share the same contract.
WCF is also going to try to define a WSDL for the service (not per endpoint) based off the contract, but if the service has more than 1 contract, it won't know what to do.
The proper thing to do would be to split this into 2 services.
Edit:
On the other hand, this article indicates that having a service with multiple endpoints with different contracts works just fine, so perhaps I am wrong.
Hmmm....

Anyone got IIS working reliably as a WCF client

I'm trying to get IIS6 to work reliably with a WCF service I have hosted in a separate Windows Service application on the same machine. Users connect to IIS via some HTTP exposed services, which is working fine, and then IIS needs to get some information from the Windows service to put in the HTTP response. I also need a callback channel between the Windows Service and IIS.
After a lot of effort I got it working with a netTcpBinding and everything would be rosey for 5 or 10 minutes but after that IIS would report the WCF channel as being faulted and then clam up and stop processing any requests until the worker process got recycled and the whole thing repeated.
I've been trying to swap to a netNamedPipeBinding but IIS refuses or is refused access to the pipe with an "There was no endpoint listening at net.pipe://localhost/mypipename" error. I can connect to the pipe fine from a console app.
So my question is has anyone got either of those two bindings working with IIS as a client or have any other approaches?
We are using IIS 7 hosting about 20 services with the net.tcp and net.pipe bindings and it's working fine.
Your problem with the pipe looks like a misconfiguration to me. If it helps, this is how we have them configured:
Server:
<endpoint address ="" binding="fooBinding"
contract="Bla.IBlaAPI"
bindingConfiguration="BlaAPI.BindingConfig">
Binding config:
<binding name="BlaAPI.BindingConfig"
receiveTimeout = "10:50:00"
sendTimeout = "10:50:00"
maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647"
maxBufferPoolSize="2147483647"
transactionFlow="false">
<readerQuotas maxDepth="32"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="8192"
maxNameTableCharCount="2147483647" />
<security mode="None"/>
</binding>
Note that we are using long timeouts and have really high quotas for message size and etc. because we are passing some big chunks of data through this service. You can adjust for your own needs. We have the security set to "none" because the service is only being contacted from the local machine which is secured. Again, your mileage may vary.
Client:
<endpoint name="Bla.Bindings.BlaAPI" address="net.pipe://localhost/bla/IBlaAPI.svc"
behaviorConfiguration="BlaAPI.ServiceBehavior"
binding="netNamedPipeBinding" bindingConfiguration="BlaAPI.BindingConfig"
contract="Bla.IBlaAPI" />
About the Faulted state problem, please note that if an unhandled exception occurs during execution of the service code, the service instance will remain in Faulted state until it is closed properly. To avoid this, either handle exceptions at service top-level or use, for example, Enterprise Library Excexption Handling blocks.
Re NetNamedPipeBinding and "There was no endpoint listening at net.pipe://localhost/mypipename"
Is your web application impersonating its users? The above error is what you get if you try to access a WCF service via the named pipe binding, in a security context whose logon token has membership of NETWORK USERS. The WCF client-side channel stack doesn't distinguish between access denied errors and "not found" errors, when it attempts to read the shared memory object created by the service to publish the name of the pipe in use. (See http://blogs.charteris.com/blogs/chrisdi/archive/2008/05.aspx etc)
Impersonation tokens in an IIS application will always have NETWORK USERS membership.
Can you show me the code you use to dispose of the wcf client proxy?
Never use 'using' on a wcf proxy, as it will not dispose correctly every time. This can possibly lead to the faulted state.

Problem adding service reference to a WCF service hosted in a windows service

I am building a WCF service interface for an existing Windows service process. The purpose of the WCF interface is to provide an "Command Channel" to implement an administrative capability for the Windows Service. There are several OperationContract methods defined that are intended to extract information from and control the behaviour of the Windows service far beyond the Start/Stop/Pause capability of the Services applet.
This WCF service is intended to be part of the existing process. As such, running the WCF service in IIS or ServiceHost is not an option.
My problem is that although the ServiceHost does not throw an error on Open(), I cannot get "WCF Test Client" (or anyting else) to find the service.
This is my first WCF Service, and have had trouble finding examples or patterns that fit what I am trying to do. So I have no illusions and would not be suprised if I did many things wrong. Also, not that I have 'portSharingBinding=false'. I did have that on but it was throwing an error that pointed to another service that I do not wish to run.
Is port sharing required?
Config information:
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="PortBinding" portSharingEnabled="false" />
</netTcpBinding>
</bindings>
<services>
<service name="NameChanged.ServiceManager.CommandService">
<endpoint address="net.tcp://localhost"
binding="netTcpBinding"
bindingConfiguration="PortBinding"
name="ServiceManagerCommandChannel"
contract="NameChanged.ServiceManager.ICommandService" />
</service>
</services>
</system.serviceModel>
I also tried the no config route using the following code:
ServiceHost host = new ServiceHost(typeof(CommandService)))
host.AddServiceEndpoint(typeof(ICommandService),
new NetTcpBinding(), "net.tcp://localhost:8000");
host.Open();
Also, no error on the Open(). But, no success connecting to the service.
Thanks for your time,
Jim
I can only speak to the WCF Test Client, but it is looking for the metadata for your service so it can generate a proxy for it. From the above configuration, it does not appear that you are exposing a metadata exchange endpoint. Take a look at this link for more info:
http://weblogs.asp.net/fabio/archive/2009/02/28/net-tcp-mex-endpoints-and-portsharing-in-wcf.aspx
You can access your service without using exposed metatdata to generate a proxy, but it will require you to manually create channels to do so:
http://msdn.microsoft.com/en-us/library/ms734681.aspx