Vibrant discussion about CSLA .NET and using the framework to build great business applications.
We ran into the problem of losing our principal when calling BusinessBase.BeginSave() I read on this forum and in the eBook that Microsoft clears the thread out and that "feature" causes us to lose the Principal object. Rocky suggested a static variable and to hook an event in the dataportal to re-hook the principal if it's different (or unauthenticated, or missing).
I have added a change to the framework instead of opting for a static variable, but I want to know if it's safe to do. In DataPortalT.cs, in the Execute_DoWork(), I added code there since thats what receives the DataPortalAsyncRequest object. Here is the change from that method (in Bold):
That's true. If you have the need for several different principals within the context of a single smart-client app (really???) then the current ApplicationContext.User implementation won't work for you.
Fortunately, ApplicationContext.User uses a provider model to manage principals, so you can override the default behavior if necessary.
What should really happen in the data portal, is that it should be using Csla.Threading.BackgroundWorker. Our BackgroundWorker automatically flows the principal to the new thread, basically doing what you show.
All that said, much of the existing data portal code around async is changing in 4.5 due to the new async/await keywords, and everything prior to 4.5 is in maintenance mode. In other words, the existing 4.3 implementation is what it is, and the 4.5 implementation will be different in any case.
That is probably fine for the data portal. I chose to use a static field because I wanted to also allow the use of the thread pool for other work too, so it provides a broader solution.
There is also the problem of setting the principal multiple times during the life of the app (such as a kiosk or shared workstation scenario like in a clinic or on a manufacturing floor). The standard WPF behavior makes that quite hard to do.
Am I missing something?? It seems to me that if I had a pool of threads with different principals, then any thread calling an async dataportal method would still assign the correct principal. Also, Even if a user logs in/out or if principals change because of context switching or impersonation, the thread at that time should always hold the correct user. So if thats the case, it seems like that code change I made would work out.
Maybe I am missing some scenario (very possible) but can you elaborate on a scenario where my code might not work? I just don't want to run into anything unexpected later.
Also, I wanted to mention to anyone that wants to use this code, that you also would need to do it for the other DataPortal_XYZ async methods.
I see, thanks for clarifying!! We actually do use impersonation inside a smart-client app. We wrote a callcenter application where certain things are locked out to people in certain Roles. Things like price override are locked to normal users. If the customer record needs a price override, a manager comes in and clicks a manager price override button. They then have to log into the domain with their own credentials and the price override happens in their context and gets logged as the proper user. After the price override, we roll back to the previous normal user. (just fyi).
Thanks for the explanation! See you in 4.5 mode!