Check for Presence of WCF Transport Session - wcf

Given a svcutil generated WCF client, is there a way to query the client to find out if transport session is being used by the underlying binding?
I'd like to dynamically check this so that I can write a WCF client wrapper which opens and closes the proxy safely while accounting for channel-fault cases that only apply when transport session is in play.
I see there is a MyClient.InnerChannel.SessionID which may be helpful. Perhaps if it is non-null it implies that transport session is active. But I think that is perhaps too big of an assumption. For example, I understand wsHttpBinding can emulate transport session. When that happens, the SessionId may be non-null and yet presumably there would not be a true transport session that could be faulted.
I also see I can peek at MyClient.ChannelFactory.Endpoing.Binding, but I'm not sure from there what might provide a clue.

Related

Recommended WCF client channel lifetime with Message security

I have a question with regards to WCF client channel lifetime while using Message security, but first, a few notes on my company's setup and guidelines:
Our client-server applications are solely for intranet use
Our clients are WPF applications
Our company's guidelines for WCF usage are:
Use wsHttpBinding
Use Message Security
Service InstanceMode: PerCall
Service ConcurrencyMode: Multiple
It is the first time I have to use message security on an intranet setup. Here's how I typically use my client channels to limit the amount of resources kept on the client and server and literally just to keep things simple:
Instantiate + open channel (with ChannelFactory)
Make the WCF call
Close / dispose the channel asap
While monitoring this strategy with Fiddler 2, I noticed that because of Message Security, a single WCF call ended up causing 5 round-trips to my service:
3 initial round-trips for handshaking
1 round-trip for the actual WCF call
1 call to close the session (since I am using PerCall, I am assuming this is more a security session at the IIS level)
If I were to turn off Message Security, as one would expect, one WCF ended up being... A single round-trip.
As of now, I must use Message Security because that's our guideline. With this in mind and knowing that we make hundreds of WCF calls from each client WPF app a session, would you therefore advise to open the client channel and keep it open for re-use instead of disposing of it every time?
I would advise not to preemptively turn off features until you know they are a known problem. Preoptimization is needless work. Until you notice your clients having lagging problems, I would not worry about the message security. At that point, try a few things: one of your approaches of keeping a client open longer; two, try grouping requests together without turning off message security; three, consider caching, if you can; four, if the message security is the final culprit, then try a different method. I wouldn't just turn something off because I see a bit more network traffic until I knew it was the absolute last thing that I could do to improve performance.

WebHttpBinding and Callbacks

I have asp.net site where I call my WCF service using jQuery.
Sometimes the WCF service must have an ability to ask user with confirmation smth and depend on user choice either continue or cancel working
does callback help me here?
or any other idea appreciated!
Callback contracts won't work in this scenario, since they're mostly for duplex communication, and there's no duplex on WebHttpBinding (there's a solution for a polling duplex scenario in Silverlight, and I've seen one implementation in javascript which uses it, but that's likely way too complex for your scenario).
What you can do is to split the operation in two. The first one would "start" the operation and return an identifier and some additional information to tell the client whether the operation will be just completed, or whether additional information is needed. In the former case, the client can then call the second operation, passing the identifier to get the result. In the second one, the client would again make the call, but passing the additional information required for the operation to complete (or to be cancelled).
Your architecture is wrong. Why:
Service cannot callback client's browser. Real callback over HTTP works like reverse communication - client is hosting service called by the client. Client in your case is browser - how do you want to host service in the browser? How do you want to open port for incoming communication from the browser? Solutions using "callback like" functionality are based on pooling the service. You can use JavaScript timer and implement your own pooling mechanism.
Client browser cannot initiate distributed transaction so you cannot start transaction on the client. You cannot also use server side transaction over multiple operations because it requires per-session instancing which in turn requires sessinoful channel.
WCF JSON/REST services don't support HTTP callback (duplex communication).
WCF JSON/REST services don't build pooling solution for you - you must do it yourselves
WCF JSON/REST services don't support distributed transactions
WCF JSON/REST services don't support sessionful channels / server side sessions
That was technical aspect of your solution.
Your solution looks more like scenario for the Workflow service where you start the workflow and it runs till some point where it waits for the user input. Until the input is provided the workflow can be persisted to the database so generally user can provide the input several days later. When the input is provided the service can continue. Starting the service and providing each needed input is modelled as separate operation called from the client. This is not usual scenario for something called from JavaScript but it should be possible because you can write custom WebHttpContextBinding to support workflows. It will still not achieve the situation where user will be automatically asked for something - that is your responsibility to find when the popup should appear and handle it.
If you leave standard WCF world you can check solutions like COMET which provides AJAX push/callback.

wcf binding properties

What happens when WCF binding properties like MaxReceivedMessageSize, OpenTimeout, ReceiveTimeout, SendTimeout and Security on the client program have different values than server program ones? Thanks.
Security settings: you will not be able to connect / execute operations if you use different security mechanisms. The server decides how it wants to control security, and the client has to conform to his demands.
Otherwise: nothing specific really. Of course when you run into a MessageSize boundary, or hit a timeout, the client will receive an exception message if it has happened on the server side, or generate an exception if it happened on the client side.
Specifically in security, properties like SecurityMode (Message or Transport), ClientCredentialType (Message or Transport) must be match in server and client, or am I wrong??
As C. Evenhuis said, the security stuff is determined by the server, but in general, you want to be careful with the other settings as well. If the server will send a max size message of n bytes, then it doesn't help for the client to attempt to accept something much larger.
In my experience, a lot of engineers get confused when they try to increase one of these other settings on the client and don't get the result they're expecting. This is usually because they forget about the relevant settings on the server side.
If you don't have a view into what settings the server is configured for (one of the few beefs I have with WCF), then it will be more difficult to know the boundaries you can set for your client.

How can I share one session between several wcf's clients?

I have several web services. One of this services is used for retrieve a session id (authentication). I pass this id when call other services through SessionInfo.
I want to use WCF instead of classic web methods. How can I share one session between several wcf's clients?
It is not clear what do you mean by session. WCF supports four types of sessions:
Transport session - for transport protocol which maintains session between server and client. For example: Net.Tcp, Net.Pipe
Reliable session - support for reliable in order delivery over unreliable channel if both client and server are running
Security session - client has to be authenticated only for the first call, subsequent calls are authenticated by session token. This session is also called security context.
Application session - this has a meaning for IsInitiating and IsTerminating parameters of operation contract and PerSession instancing. This session can be used only if any of preceding sessions is used as well = it can't be used in BasicHttpBinding because it doesn't support transport, reliable and security session.
All these sessions are related to communication between single client proxy and single service instance. Nothing else is provided out of the box. Moreover there is no special "session" object.
So what exactly are you trying to achieve? Are you going to replace ASMX services wich are using ASP.NET session? In that case check this sample.
Edit:
The idea about receiving single Id from the first service and reusing this Id on subsequent calls to multiple services should be called corelation (one big activity/transaction) or federation (security related) not session.
As marc_s says you cannot share the session.
But what you can do is to pass the session id as a parameter in your WCF calls, so that you know on whos behalf the call is being made.
Make sure that you use encryption on these calls.
The recommanded way to that is by manually maintaining session state between calls. You generate session IDs the way you want and load/persist session information into a database on every call using your own logic.
By doing that, you will support sessions in a way that will enable:
Load balancing
Session sharing
Fail over

WCF Design questions

I am designing a WCF service.
I am using netTCP binding.
The Service could be called from multi-threaded clients.
The multi-threaded clients are not sharing the proxy.
1. WCF Service design question.
Client has to sent these 2 values in every call: UserID and SourceSystemID. This will help the Service to identify the user and the system he belongs.
Instead of passing these 2 values in every call, I decided to have them cached with the Service for the duration of call from the client.
I decided to have a parameterized constructor for the Service and store these values in the ChannelContext as explained in this article.
http://www.danrigsby.com/blog/index.php/2008/09/21/using-icontextchannel-extensions-to-store-custom-data/
Initially I wanted to go with storing the values in the Session and have a method for initialization and termination. But there I found that I need to manually clean up the session in each case. When I am storing values in the channel context, I don’t have to clean it up every time and when the channel closes the values stored are already destroyed.
Can somebody please make sure that I am correct in my assumption?
2. Should I use SessionMode?
For my contract, I used : [ServiceContract(SessionMode = SessionMode.Required)] and without this service attribute.
Irrespective of my choice, I am always finding a value for : System.ServiceModel.OperationContext.Current.SessionId
How can this be explained?
When I say SessionMode.Required, does my InstanceContextMode automatically change to PerSession?
3. InstanceContextMode to be used?
My service is stateless except that I am storing some values in the Channel Context as mentioned in (1).
Should I use Percall or PerSession as InstanceContextMode?
The netTcp always has a transport-level session going - so that's why you always have a SessionId. So basically, no matter what you choose, with netTcp, you've got a session-ful connection right from the transport level on up.
As for InstanceContextMode - as long as you don't need anything else from a session except the SessionId - no reliable messaging etc. - then I'd typically pick Per-Call - it's more scalable, it typically performs better, it gives you less "glue" to worry about and less bits and pieces that you need to manage.
I would use an explicitly required session only if you need to turn on reliable messaging or something else that absolutely requires a WCF session. If you don't - then it's just unnecessary overhead, in my opinion.
Setting SessionMode to SessionMode.Required will enforce using bindings which support sessions, like NetTcpBinding, WSHttpBinding, etc. In fact if you try using a non-session-enabled binding , the runtime will throw an exception when you try to open the host.
Setting InstanceContextMode to PerSession means that only one instance of the service will be crated per session and that instance will serve all the requests coming from that session.
Having SessionId set by the runtime means that you might have a transport session or a reliable session or security session. Having those does not necessarily mean you have an application session , that is a single service object serving the requests per proxy. In other words, you might switch off application session by setting InstanceContextMode=PerCall forcing the creation of a new service object for every call, while maintaining a transport session due to using netTcpBinding, or a reliable or security session.
Think of the application session that is configured by InstanceContextMode and Session Mode as a higher level session, relying on a lower-level session /security, transport or reliable/. An application session cannot actually be established without having one of the other sessions in place, from there the requirement for the binding .
It is getting a bit long already, but for simple values I would recommend you to pass those values every time instead of creating application session. That will ensure the service objects have a short lifetime and no unnecessary resources will be kept alive on the server. It makes a lot sense with more clients, or proxies talking to your service. And you could always cache the values in the clients, even pass them as custom headers if you want.