views:

42

answers:

1

I've just read this interesting article regarding simultaneously calling multiple methods on a WCF service from Silverlight:

http://weblogs.asp.net/olakarlsson/archive/2010/05/20/simultaneously-calling-multiple-methods-on-a-wcf-service-from-silverlight.aspx

The article states: "It turns out that the issue is founded in a mix of Silverlight, Asp.Net and WCF, basically if you’re doing multiple calls to a single WCF web-service and you have Asp.Net session state enabled, the calls will be executed sequentially by the service, hence any long running calls will block subsequent ones."

I am assuming that the blocking is only an issue if you are making multiple calls to the same service, and that two simultaneous calls to two different methods on two different services should not result in one blocking the other?

The suggested solution to the problem in SL3 involves using the following syntax in the Application_Startup method:

WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);

The session state will then have to be maintained on WCF calls by seting up a cookie container, and sharing it across all of your proxies (see http://forums.silverlight.net/forums/p/174322/393032.aspx)

Is this still the recommended solution in Silverlight 4? Has anyone used an alternative approach?

+1  A: 

If you are making a call into an ASP.Net application, and you are using session cookies, then all the calls into the application are serialized (apart from ones where the page explicitly opts out of session state).

Normally this isn't a big issue, because a client browser typically hits an ASP.Net page plus a bunch of resources (images, js, css etc...), and these latter aren't mapped to ASP.Net so IIS serves them up natively. But if you try and hit two ASP.Net pages at the same time (eg in a frameset) you will see them load up one after another.

Now I don't know that this happens with WCF, but based on what you say, if you see that behaviour for one service I would expect to see that for all of them, because the session is per-user, not per-service.

In ASP.Net you can 'opt out' of session state on a page by page basis. If that's possible for a hosted WCF service, and viable for your scenario (to make the services stateless) that would aleviate the issue. Or move one or more services to a different ASP.Net application (different session)

Bear in mind that you can see other issues here to do with the instancing and reentrancy models of the service. Your problem as described above is a per-user concurrency issue, but there are others. For example, if you set the service up as a singleton (InstanceContextMode.Single) and non-reentrant (ConcurrencyMode.Single) then only one request will ever be processed at a time across all users.

Update: Doing some doco reading:

  • WCF services aren't enrolled into ASP.Net sessions unless you ask for it (using )
  • WCF services can on a per service basis opt in, using the [AspNetCompatibilityRequirements] attribute on the service implementation
  • There doesn't seem to be any way of opting in but not opting into Session state.

There's a good blog post about this on Wenlong Dong's site

So from what I can see you should be able to use AspNetCompatibilityRequirementsMode.NotAllowed to opt out individual services completely from ASP.Net services. Alternatively, leave it off by default and only opt-in the ones that need access to the ASP.Net session (bearing in mind that unless you really need to share the same session with ASP.Net, just using WCF's session services is probably a better bet).

piers7
But what about Silverlight applications hosted in a browser?
Myles J
But that's the point: unless you use the silverlight HTTP stack (as per your link above), Silverlight in a browser *works just like the browser would*.
piers7
Point taken. I have tried to make one of the services stateless by using: [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.NotAllowed)] on the service class. This doesn't work and is probably due to the following web.config line: <serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> We need this in the web.config file as there are other services that need to have state maintained. I think the only solution may be to have certain services (those that are prone to block) in a separate asp.net application as previously mentioned.
Myles J
I noticed the following text in the Wenlong article:"Besides the application-level flag aspNetCompatibilityEnabled, users still need to explicitly opt-in for the compatibility mode on the WCF service by using the service attribute AspNetCompatibilityRequirements [ServiceBehavior][AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)]The RequirementsMode can have three different values: NotAllowed, Allowed, or Required. The default is NotAllowed."
Myles J
I am not using the AspNetCompatibilityRequirements attribute on any of my service classes. This would indicate that session state is off by default?
Myles J