If I set my servis instance as Per Session or Single can I send some data between services instance in session? It should be done in Asp.net session - HttpContext.Current.Session
or wcf have own session ?
As I said - WCF is not ASP.NET and its session handling is vastly different. While ASP.NET sessions and WCF sessions are called the same - they are vastly different in their purpose and usefulness.
Read the MSDN page Using Sessions in WCF for more details.
One sentence reads: There is no general data store associated with a WCF session. - so the answer is no - sessions in WCF are not meant for data storage.
WCF sessions are merely to "tie together" several messages into a conversation. By default, with the "per-call" model, each WCF service request would get its own, freshly instantiated service class instance to handle the request, and that service class instance will be freed after returning the answer. Using sessions avoids this - the service class instance handling the first call of a session will stay alive on the server side (and thus also taking up memory on the server) and will handle all subsequent requests within the same session.
WCF and web services in general should however preferably be stateless, so sessions are a bit of an oddball architecture in a proper SOA environment - and that's most likely why sessions in WCF are also not nearly as useful as ASP.NET sessions are for web apps.
To remain stateless and support the per-call method (the preferred best practice), if you need to store data between calls, store it in a persistent store (e.g. a database) and fetch it back from there when needed later on.
If you're hosting services in IIS, you can enable ASP.Net Compatability mode. This will allow you to use ASP.Net session state, just like you would in a web application.
Related
I'm developing a UWP client project which need to consume some services of a WCF server. I uses the "add service reference" tool of Visual Studio to auto generate service clients(proxies). The binding type is NetTcpBinding. Below is some code snippet which create the service client:
NetTcpBinding tcpBinding = new NetTcpBinding();
tcpBinding.Security.Mode = SecurityMode.None;
tcpBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;
tcpBinding.Security.Message.ClientCredentialType = MessageCredentialType.None;
MainServiceClient = new MainServiceClient(tcpBinding, new EndpointAddress("net.tcp://localhost:8773/MyWCF/MainService/tcp"));
The question is do I need to call OpenAsync() method of MainServiceClient? It seems the service client can be auto opened when it is first called. But I read from this article that auto-opened service client would have some performance penalty. The article was written in 2007. I just wonder if this mechanism have changed today, especially in UWP project. Can anyone share more light on this topic? Thanks!
To explain this case, you should know three ways to do WCF instance management. WCF has provided three ways by which you can control WCF service instances:Per call, Per session, Single instance.
When we configure a WCF service as per call, new service instances are created for every method call you make via a WCF proxy client.
Very often we need to maintain state between method calls or for a particular session. For those kinds of scenarios, we will need to configure the service per session. In per session, only one instance of a WCF service object is created for a session interaction.
Often we would like to create one global WCF instance for all WCF clients. To create a single instance of a WCF service, we need to configure the WCF service as Single instance mode.
And there are three ways by which you can handle concurrency for each service instance in WCF :single, multiple, and reentrant.
Single: A single request has access to the WCF service object at a given moment of time. So only one request will be processed at any given moment of time. The other requests have to wait until the request processed by the WCF service is completed.
Multiple: In this scenario, multiple requests can be handled by the WCF service object at any given moment of time. In other words, requests are processed at the same time by spawning multiple threads on the WCF server object. So you have great throughput here but you need to ensure concurrency issues related to WCF server objects.
Reentrant: A single request thread has access to the WCF service object, but the thread can exit the WCF service to call another WCF service or can also call a WCF client through callback and reenter without deadlock.
In "Instance mode = Per Session and Concurrency = Single" combination, one WCF service instance is created for every WCF client session because the WCF instance mode is set to per session. All the method are executed in a sequential manner one by one. In other words, only one thread is available for all method calls for a particular service instance.
For the above scenario, you should always open WCF client proxy explicitly before you are making any calls. Because it will maintain service state between method calls and obtain high performance.
For more detail you could refer to "WCF Concurrency (Single, Multiple, and Reentrant) and Throttling" and "Three ways to do WCF instance management".
What Works
I built a DataSnap web service in Delphi-XE2, which uses the TDSServer and TDSHTTPService components. Clients attach to the server (web service) and run DataSnap server methods to retrieve data. The server uses TDSLifeCycle.Session for all connections. I want to continue to use Session if possible because I store session information in thread variables...
I can use Internet Explorer to authenticate to and retrieve data from the DataSnap server. If I don't let IE sit idle for 30 seconds (or it disconnects from the server), it will reuse the same connection for every method request.
I can use a simple Delphi app that uses TIdHTTP to connect to the DataSnap server. Adding keep-alive to its Request.Connection property makes it stay connected forever and reuse the one connection for all method calls.
.
Problem
A 3rd party company is building a WCF app to access the DataSnap service. They can't get WCF app to use only one connection to the service. The initial authentication request and 1st method call use the same connection, but subsequent requests create new connections, evident by running netstat on their computer and seeing new ESTABLISHED connections from their app to my service using multiple source ports. New connections create new threads in the DataSnap server, which can't access the authenticated thread's session variables.
.
Possible Workaround
I know that I can change the DataSnap server to an Invocation model, making it unnecessary to maintain one persistent connection per client, and will do this if needed. Before doing so, I thought it prudent to see if anyone else knows how solve the problem.
.
My Question
Is it possible for a WCF client app to create a single persistent connection to a non-WCF server (DataSnap server) that it uses for all method calls without it creating new connections? How is this done? Is it as simple as adding the right [decoration] to the C# WCF project in Visual Studio?
Any suggestions are greatly appreciated!
.
FYI - I don't have access to the 3rd party's code, so I can't provide samples of the WCF code.
Your Delphi application provides a stateful web service (using session variables), and WCF web services are stateless by default, including WCF clients.
Maybe this answer points to the correct configuration (wsHttpBinding and SessionMode of the ServiceContract).
From the MSDN ocumentation:
For example, if the SessionMode property is set to
SessionMode.Required and the InstanceContextMode property is set to
PerSession, clients can use the same connection to make repeated calls
to the same service object.
(highlighting by me)
However, as DataSnap is not primarily designed for interoperability with WCF it might be easier to re-design the Delphi side to use a stateless web service model instead of stateful. This would require authentication with every service request, but internally the Delphi web service could some cache data to reduce lookup times, similar to the current session state.
Our application architecture is as follows:
1) WCF service acts as a facade layer and sits on top of Service, Business Logic and Data Access layer
2) Every client, be it an MVC/ASP.NET, or any other type of application has a ClientTag that first needs to be authenticated and issued an "access token". This token is then passed by the client with every message into the Facade layer
3) The system will be hosted on Windows Azure
This would have been easy to implement with WCF sessions like so:
1) Client initiates a call to WCF to get the token (Client to WCF Session is established, thus every subsequent communication is part of the same "conversation")
2) WCF authenticates the ClientTag, issues the token, and stores it as a local variable
3) Client stores the token in it's own Session and pass it to WCF with every request
Where it breaks down is the fact that Azure (due to its high-availability/load-balancing nature) doesn't support WCF sessions. So, the questions is how do we implement this.
One solution is to use AppFabric caching to imitate session state in WCF layer. We would store the Access Token there and then validate it against what the client passes in. The problem with this is that there is no concurrency between client and WCF. So, we would have to advance WCF session timeout on every request from the same client but we'd want to avoid updating the cache on every request (it could be hundreds/sec).
Any suggestions? Has anyone implemented anything similar to this on Azure. Any feedback would be greatly appreciated.
P.S. It's not only authentication that would happen on the server, but also custom authorization for each client. (Some client might have access to some functions, and others might not).
Thanks!
I'm in the middle of implementing something directly similar to this, but using OAuth 2.0 as the authentication architecture through ACS.
The model I'm following is shamelessly stolen copied from an MSDN sample here: https://connect.microsoft.com/site1168/Downloads/DownloadDetails.aspx?DownloadID=35417. This assumes the client has a user interface, so the user can present some kind of username and password either directly or through some third-party identity provider.
The advantage of this approach is that the WCF layer doesn't need to use any kind of session state, so there's no tedious mucking about with machine keys or whatnot. You'll still get something that can be mapped to an IPrincipal, however, so if you want you can create a custom RoleProvider and use declarative roles in the usual way.
Note the sample uses old-school ASP.NET, and has a dependency on an opaque (and possibly rather buggy) assembly Microsoft.IdentityModel.Protocols.Oauth. And, unless I'm missing something, I've not seen this released anywhere else (e.g. as part of Windows Identity Foundation) so I suspect it's rather new.
An alternative approach could again be to use ACS, this time to authenticate a SAML token, again following the OAuth 2.0 protocols. Details and sample code is here: http://msdn.microsoft.com/en-us/library/windowsazure/hh127795.aspx. That may be better suited to a system with no UI.
I have to create a WCF web service that proxies an IMAP service (so that it can be consumed by a SL application).
The IMAP service requires that first the Login(credentials) method is called, to authenticate with the IMAP server. After the Login method is called the connection is kept open and other operations can be performed.
Does anybody know how can achieve this with a WCF service?
One solution I want to avoid is the proxy to login for every operation it has to perform (as the login operation usually takes 1-2 seconds). And I would have to pass the credentials every time: GetMail(credentials), GetFolders(credentials), etc.
I know it is highly recommended that WCF services not to be stateful, but it seems I need to keep the state of IMAP connection for every client. How can I do this?
Thanks!
This is one of those rather rare cases where I think using WCF sessions makes sense:
your first call that calls the IMAP Login method starts a WCF session
any subsequent call will be using the same session
some final call (e.g. something like a Done or Logout) will terminate that session
With a session in WCF, your service class on the server stays in memory for the duration of the entire session, i.e. it's not constantly re-created, and thus you can keep the IMAP connection "live" inside your service class.
Resources:
Sessions, Instancing, and Concurrency (MSDN)
Using Sessions (MSDN)
WCF Sessions - a brief introduction
WCF Sessions
Per-Session Instance Management in WCF
Be aware: WCF sessions are NOT ASP.NET sessions - those are two totally different things! Just to be clear from the get-go.
Also: only a handful of WCF bindings support sessions - netTcpBinding, wsHttpBinding and netNamedPipeBinding (as far as I know)
While making my first ajax attempts, I decided also, to go to use IIS hosted WCF now. The strange thing is, that the WCF cannot process several requests parallel for the same user/session, if sessionmode is enabled! If sessionmode is disabled on asp.net, the requests are processed parallel. The broser/client may execute several different requests, where some of them are long running. This blocks all further requets and make my ajax app unusable.
This applies to asmx [webservices] also. I had a big hope, to compile the webservice methods using "IReadOnlySessionState" interface, but this has - in oppsite to webpages - no influence. But I need access [most times readonly] to the asp.net session!
Does someone knows any solution to this problems.
Anyway, thanks a lot!
br--mabra
In .NET 4, you can do this in Application_BeginRequest
if (Context.Request.Path.EndsWith("xxx.svc"))
Context.SetSessionStateBehavior(SessionStateBehavior.ReadOnly);
I found this:
http://blogs.msdn.com/silverlightws/archive/2009/09/30/having-a-pollingduplex-service-and-any-other-wcf-service-in-the-same-website-causes-silverlight-calls-to-be-slow.aspx
Which states,
"All WCF services require read/write session state access if you enable ASP.Net sessions, which causes the replies to be queued sequentially. Ideally user should be able configure the WCF handler to be read only, which would allow polling duplex services to work with sessions. Unfortunately this is unsupported at this point."
...the only thing I can think of is if there's some way to manually force early release of the lock. I'm looking into that now.
You can provide a custom session state provider
See: http://koolsand.blogspot.com/2010/02/why-iis-hosted-wcf-services-does-not.html
whenever a request contains svc in the
path it intimates default session
state provider to use readonly lock
and not read-write lock. So using
readonly lock will allow the next wcf
call to be executed concurrently.