Force a client to call a method on the service? - wcf

I'm wondering if there's any way to force a client to call a specific method on a duplex WCF service. My situation is this, my service implementation is going to keep a collection of subscribers. The problem with this approach is, what if the client doesn't call Subscribe()? I was thinking that in my client interface, I'd have a method called Subscribe, but that doesn't get me anywhere since the code to actually call the service can still be left out of the implementation. Is this possible?
Thanks!

Duplex WCF service uses WCF session so you can mark your Subscribe method with:
[OperationContract(IsInitiating=true)]
void Subscribe();
All other methods will have IsInitiating=false and because of that Subscribe method will have to be the first method called to start a new session. You can also have special method with IsTerminating=true to close the session.

Related

wcf async callback

I have WCF service which sends messages to its clients. I would like to call callback methods asynchronously. I have read this answer:
WCF asynchronous callback
But there is one problem. When I am generating IMyServiceCallback from WebServiceReference it contains both synchronous and asynchronous methods (while on the service side there is callback contract with only asynchronous methods - BeginCallbackMethod and EndCallbackMethod). What is more when I call from MyService to calback BeginCallbackMethod, on the client side (in callback implementation) it is using synchronous CallbackMethod. The question is why? Is there any way to configure it?
By default WCF will call the synchronous version of an operation if both sync and async are present; I don't know how (or if) you can change that logic, but one thing you can do is to simply remove the synchronous method from the generated callback interface. The callback code should continue to work, and it will use the asynchronous implementation instead. You can also just remove the [OperationContract] attribute from the synchronous version, to the same effect.

WCF service calls includes same information in every call

I have a web service that will be consumed by some application (web site currently).
The calls are almost all specific to a certain client but still the same. So one call might be getAllFoo() but I would need some parameter to say from which client the Foo is.
It would become bothersome quickly if I just add a standard parameter to all calls so I was hoping to do it a little bit DRY and automatic. Something that would be included in all service calls.
Is IDispatchMessageInspector the right thing for me here? What kind of info could that include and can I access that info inside the methods?
Should I create some sort of attribute perhaps for the calls?
If anyone could point me towards a solution for this it would be great.
Edit
Another solution I'm thinking off.
Where the service call to a specific client happens on the consumer side, it will be known at instanceCreation so I could instance the ServiceClient with a known client.
Could I use this solution for the ClientBase<> extender somehow.
Let's say I'm serving Domain1 (let's call the client Domain to not confuse it with a serviceclient/consumer) I create a InformationProvider consumer side that has a ClientBase<IInformationService> field. I ensure that the DomainName (domain1) is set at construction so I could parhaps do the same thing when instancing the ClientBase<IInformationService> so It somehow let's the service know what domain I'm calling for.
I'm just still learning about WCF so I'm not sure how one would do this.
I can understand that you want to keep you solution simple and tidy, but ultimately - as you say yourself -
... I would need some parameter to say from which client...
The obvious and simplest solution is to include a client parameter on all your service calls where it is required. Surely there'll be service calls that don't require the client parameter, and in those cases you don't need to include the parameter.
You may be able to do something clever where a client identifier is passed discreetly under the covers, but beware of doing unnecessarily clever things. I would pass the client as a simple parameter because it is being used as a parameter. Two reasons come to mind:
if someone maintains your code they quickly understand what's going on.
if someone needs to use the service it is obvious how to use it.
A possible pattern:
Make sure you service instantiates per session. This means you'll have to use wsHttpBinding, netTcpBinding, or a custom binding as http does not support sessions.
Always call an initialization operation when each session is instantiated that sets the client id for that service.
Put this initialization operation inside a constructor for a proxy.
The steps involved would be something like this:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class MyService : IMyService
{
private int clientId;
public void StartUp(int clientId)
{
this.clientId = clientId;
and then client side, assuming you use the generated proxy, wrap the client inside another proxy.
public class ExtendedClient : MyServiceClient
{
public ExtendedClient(int clientid) : base()
{
this.StartUp(clientid);
}
Now you should instantiate the ExtendedClient, it will create the channel and prime the service by delivering the client id.
I would personally prefer to simply send the client id for each service call, but if you are able to use a session-able binding then this should work.
Just some information on WCF for you. If you have a stateless service, then you'll need to include the client as a parameter in every service call. This does not mean you need to include the client everywhere throughout your code - you could, for example, retrieve it inside the ClientBase constructor. But you will need to add it to every OperationContract and all the service implementations.
The alternative is to have a stateful service - the instance that you first use will remain for you to reuse (except for timeouts / exceptions). In this case you can potentially send the client just once, and then the service will know about the client for subsequent calls. This is the pattern described above. It means that you cannot use http binding. I believe that by doing this you're only increasing the potential for problems in your application (stateful services, having to ensure the initialization operation completes, more service calls being made).

Not disposing of a WCF proxy?

I have a WCF service which is a singleton and which manages a collection of proxies to another WCF service which is session-based. The singleton creates a new proxy and passes it some work to do, and the session-based service makes calls back to the singleton service when certain activities complete (pretty much all of the OperationContract methods are one-way). The typical completion path is that the singleton receives an event from a hardware device when the process is complete, and it calls a method on the session-based service which returns the final status, and then disposes of its proxy. When an error situation is encountered and the session-based service can't continue with what it needs to do, I need to make a call back to the singleton to let it know to dispose of the proxy associated with that instance. However, to make the WCF method call back to the singleton, I need to create a proxy back to the singleton. What I'm seeing happen is that the singleton disposes of its proxy as expected, but every time the proxy to the singleton that the session-based service created times out when I try to dispose of it. Since the session ends with that method call and the instance will be disposed of, does it matter if the proxy it created doesn't get properly disposed?
Disposing of a WCF service is not the same as disposing of any other object that implements IDisposable. It is ok to dispose of the service when it is in a good state but when a fault occurs the dispose method will throw another exception.
Some insight is here and perhaps use the WCFProxyGenerator but I have not tried it
Not sure exactly the problem with the session based service and whether it is different from the WCF service.
My recommendation is not to use a singleton but use Dependency Injection to give the class that uses the WCF service a factory so when it wants the service it can create it. And when a fault occurs it can throw away the old and create a new one. Without seeing some code it is hard to see if this is possible.

In WCF is it possible to pass a delegate to the remote object?

Is it possible to pass a delegate to a WCF remote object from the client and have the remote object execute the delegate?
I would guess not since a delgate is a function pointer for the client process.
My goal is to have an interface structure that I can "subscribe" to events from a client to the interface. I would pass a delgate from the client to the interface and I want the interface to be able to execute the event.
The idea is to have the ability for the interface to be loaded either the assembly or remotly and have the code work the same.
If I can't pass the delegate how can I implement an event structure?
not a "delegate" in C# per se, but in WCF you have duplex bindings to enable call back from the service side to the client side
http://msdn.microsoft.com/en-us/library/system.servicemodel.wsdualhttpbinding.aspx
I doubt you could come up with a cohesive way to pass a delegate from a C# client to a Java service implementation and have it properly executed......
WCF is not a strict .NET implementation and thus has to deal with interop issues. It cannot rely on the assumption that both ends of the conversation are in .NET - that's why you shouldn't throw around custom exceptions between server and client either (exceptions are a .NET construct) - you need to use SOAP faults instead (which are interoperable).
So I don't think what you want to do can be done with a delegate - you'll have to come up with another way to achieve your goal.
Marc

WCF OperationContext

I'm developing a WCF service and if there is an error I want to serialize the incoming parameter from the original method that was called on the service. I am using IErrorHandler to catch all exceptions.
My initial thoughts were that I will store the serialized parameter in OperationContext.IncomingMessageProperties so that I can access it from the HandleError method. However, as this isn't run on the original thread I believe the OperationContext will be null, so I am considering accessing it from the ProvideFault method.
Does this seem feasible? And will it work with OneWay service calls?
Not sure I can really help you much here, but let me try:
on your client, your code basically calls a method and passes it parameters. The WCF stack on the client side then converts that into a SOAP message (typically with an XML body, but could be binary, too) with headers and all and then sends that message across the wire to the server to be processed.
The server then attempts to deserialize that message into an object and attempts to call a message on a server implementation object. That method on the server object will most likely have the same parameters again, as the client - however, there's a possibility that the call will fail before that method even gets called.
So what I'm trying to say is: you can't rely on the fact that your server-side method with its parameters really gets called - there might have been a problem with e.g. authentication, the message format, a missing header or something else, that causes the server side to fail and throw an exception even before the server-side method ever gets called.
In the end, in the IErrorHandler, there's no way I would know of to get a hold of the message and/or the method and its parameters - all you can get are the error that occured on the server, and you can use that to turn it into a SOAP fault.
What you could do - both on the client and the server side - is create a new behavior that plugs into the WCF stack, and that records the methods being called and the parameters being passed into them - by implementing a class that implements the IParameterInspector interface of WCF. But that only will get called if the message on the client and the server will get properly deserialized and the server-side method really gets called.
Check out some of these links for more info on WCF extensibility:
How to: Inspect or Modify Parameters
WCF Extensibility: Parameter Inspectors
IParameterInspector in WCF
Extending WCF with custom behaviors
Hope this helps a bit!
Marc