Mysterious change in ApplicationContext.User?

Mysterious change in ApplicationContext.User?

Old forum URL: forums.lhotka.net/forums/t/7177.aspx


rsbaker0 posted on Friday, June 26, 2009

One of my co-workers is working on a companion application written using CSLA, and we are observing a strange and unexplainable change in the value of the ApplicationContext.User value.

He has even gone so far as to temporarily modify the CSLA code so that the setter and getter trace the current values to the debug output.

On one Get call, the value is our current user ID that we explicitly set. Then after making another call over the local data portal, the next Get displays 'AdminIdentity' as the value, with no intervening call to the setter.

There are no references to Thread.CurrentPrincipal anywhere else in the source code, so this is baffling.

Do you have any ideas on how this might get changed under the covers?

To be fair, this is a "dual data portal" application where CSLA is configured to use the WebService proxy, but some classes are explicitly tagged to be forced over the local data portal. 

This is the client/local side that we are tracing.

ajj3085 replied on Friday, June 26, 2009

Any threads being spun up? That would be my first instinct to check.

RockfordLhotka replied on Friday, June 26, 2009

It is also the case that WPF messes with the current principal, though ApplicationContext.User explicitly includes code to help deal with this "feature" of WPF.

So it really is most likely an issue with threading - remember that the .NET current principal is set on the thread, not the AppDomain or process or anything, and that can certainly cause complications.

rsbaker0 replied on Tuesday, June 30, 2009

Yes, it turns out this involves some threading. Evidently, the principal is being set via a delegate invoked from another thread. We are using Control.Invoke(), which I was under the impression would ensure that the delegate was properly executed on the same thread as the control, but it turns out that it stays set only for the duration of the delegate's execution.

My co-worker has tried 3 different threading approaches (background worker, etc.) and produced a small test app that does not include CSLA, and they all do the same thing.

Is this by design? I thought each thread could set its own principal and it would remain unchanged unless explicitly changed.

RockfordLhotka replied on Tuesday, June 30, 2009

What version of CSLA are you using?

It is true that WPF "protects" you from principal changes triggered by background threads. In my experience this results in there being no practical way to actually change/set the principal. I suggested to Microsoft that this is a bug, but they insist that it is a valuable feature. I continue to disagree.

In a relatively recent version (maybe 3.6?) of CSLA I enhanced ApplicationContext.User to manage the principal itself when running in a WPF environment. All code using ApplicationContext.User should get a consistent and reliable result.

This is NOT a complete fix! The actual principal on the threads is still wrong, and I can't fix that because WPF does what it does. But at least all CSLA code, and your code if you use ApplicationContext.User, should work as expected.

rsbaker0 replied on Tuesday, June 30, 2009

Thanks for confirming what we are seeing. I'm using CSLA 3.5.x with WinForms now, but the CSLA ApplicationContext is what we are using for all our security so it's nice to see that there may be help down the road.

I wonder why they think this is "valuable". The particular use case we have here is a keyboard wedge barcode parser and we're trying to login the employee from a barcode scan intercepted by a keyboard hook. The barcode parser synchronously interrogates the registered handlers to see if they "want" the barcode, but then asynchronously passes it to them for processing. After all, you can't hold up the keyboard while someone goes off to a server to read the database.

RockfordLhotka replied on Tuesday, June 30, 2009

I really don't understand the value either. Basically they work very hard to prevent you from changing the principal after the WPF runtime is initialized. It seems entirely counter-intuitive to me, and basically prevents WPF from being useful in any kiosk or shared-workstation scenarios.

Odds are that no one on the WPF team has ever worked in a manufacturing environment (or similar)...

RockfordLhotka replied on Tuesday, June 30, 2009

btw, you may be able to back-port the User code from ApplicationContext in 3.6 to 3.5. I suspect it would be pretty easy, because the code is pretty self-contained and doesn't use any .NET features that are new in .NET 3.5 SP1.

Copyright (c) Marimer LLC