I built an app with Silverlight4, RIA Services, and I'm using ASP.NET Membership for authentication/authorization.
My web.config has this:
<system.web>
<sessionState timeout="20"/>
<authentication mode="Forms">
<forms name="_ASPXAUTH" timeout="20"/>
</authentication>
I have read a number of different strategies on how to deal with auth/session timeout on the client side. That is: if the client is idle for x minutes (20 here), and then they do something with the UI that triggers a RIA/WCF call, I want to trap on that event and deal with appropriately (e.g. take them back to the login screen) -- in a nutshell: I need a way to differentiate from a bona-fide server side DomainException vs. an auth failure because the session timed out.
AFAIK: there is no typed exception or property that can determine this. The only way I've been able to determine this -- which seems like a hack: is to inspect the Error's Message string and look for something like "Access denied" or "denied". For example: something like this:
if (ex.Message.Contains("denied"))
// this is probably an auth failure b/c of a session timeout
So, this is what I'm currently doing, and it works if I run and debug either with the built-in server from VS2010, or if I run in localhost IIS. If I set the timeout to 1 minute, login, wait more than a minute and trigger another call, I breakpoint on the exception and enter the if code block above and all is well.
Then I deploy the app to a remote IIS7 server and I try the same test and it doesn't work. So, I added log tracing, and here's the event where the exception happened:
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
<System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
<EventID>131076</EventID>
<Type>3</Type>
<SubType Name="Error">0</SubType>
<Level>2</Level>
<TimeCreated SystemTime="2011-10-30T22:13:54.6425781Z" />
<Source Name="System.ServiceModel" />
<Correlation ActivityID="{20c26991-372f-430f-913b-1b72a261863d}" />
<Execution ProcessName="w3wp" ProcessID="4316" ThreadID="24" />
<Channel />
<Computer>TESTPROD-HOST</Computer>
</System>
<ApplicationData>
<TraceData>
<DataItem>
<TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Error">
<TraceIdentifier>http://msdn.microsoft.com/en-US/library/System.ServiceModel.Diagnostics.TraceHandledException.aspx</TraceIdentifier>
<Description>Handling an exception.</Description>
<AppDomain>/LM/W3SVC/1/ROOT/sla-2-129644844652558594</AppDomain>
<Exception>
<ExceptionType>System.ServiceModel.FaultException`1[[System.ServiceModel.DomainServices.Hosting.DomainServiceFault, System.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]], System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message></Message>
<StackTrace>
at System.ServiceModel.DomainServices.Hosting.QueryOperationBehavior`1.QueryOperationInvoker.InvokeCore(Object instance, Object[] inputs, Object[]& outputs)
at System.ServiceModel.DomainServices.Hosting.DomainOperationInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
</StackTrace>
<ExceptionString>System.ServiceModel.FaultException`1[System.ServiceModel.DomainServices.Hosting.DomainServiceFault]: (Fault Detail is equal to System.ServiceModel.DomainServices.Hosting.DomainServiceFault).</ExceptionString>
</Exception>
</TraceRecord>
</DataItem>
</TraceData>
</ApplicationData>
</E2ETraceEvent>
The problem is that I don't have the string in the error message that indicates "denied" or "Access denied" - and I am unsure as to why this solution works in localhost IIS or VS2010 host but not in a remote IIS7 server. Is there some obscure configuration setting that I'm missing here? Is there a better way to do this in general?
You've probably gotten by this by now, but this article describes using the DomainOperationException and checking the error codes.
For convenient access (and in case the we loose access to the blog) here's the blog article by Josh Eastburn: