Skip to content

Commit

Permalink
Merge pull request #2487 from rockfordlhotka/2480-context
Browse files Browse the repository at this point in the history
Flow all context values to logical server in all scenarios
  • Loading branch information
rockfordlhotka authored Sep 16, 2021
2 parents 767a6ff + 79baf8b commit dfaf152
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 112 deletions.
41 changes: 0 additions & 41 deletions Source/Csla.Shared/DataPortalT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,47 +29,6 @@ public class DataPortal<T> : IDataPortal<T>
/// </summary>
public Csla.Core.ContextDictionary GlobalContext { get; set; }

private class DataPortalAsyncRequest
{
public object Argument { get; set; }
public System.Security.Principal.IPrincipal Principal { get; set; }
public Csla.Core.ContextDictionary ClientContext { get; set; }
public Csla.Core.ContextDictionary GlobalContext { get; set; }
public object UserState { get; set; }
// passes CurrentCulture and CurrentUICulture to the async thread
public CultureInfo CurrentCulture;
public CultureInfo CurrentUICulture;

public DataPortalAsyncRequest(object argument, object userState)
{
this.Argument = argument;
this.Principal = Csla.ApplicationContext.User;
this.ClientContext = Csla.ApplicationContext.ClientContext;
#pragma warning disable CS0618 // Type or member is obsolete
this.GlobalContext = Csla.ApplicationContext.GlobalContext;
#pragma warning restore CS0618 // Type or member is obsolete
this.UserState = userState;
this.CurrentCulture = System.Globalization.CultureInfo.CurrentCulture;
this.CurrentUICulture = System.Globalization.CultureInfo.CurrentUICulture;
}
}

private class DataPortalAsyncResult
{
public T Result { get; set; }
public Csla.Core.ContextDictionary GlobalContext { get; set; }
public object UserState { get; set; }
public Exception Error { get; set; }

public DataPortalAsyncResult(T result, Csla.Core.ContextDictionary globalContext, Exception error, object userState)
{
this.Result = result;
this.GlobalContext = globalContext;
this.UserState = userState;
this.Error = error;
}
}

private async Task<object> DoCreateAsync(Type objectType, object criteria, bool isSync)
{
Server.DataPortalResult result = null;
Expand Down
74 changes: 24 additions & 50 deletions Source/Csla.Shared/Server/DataPortal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -674,79 +674,53 @@ internal void Initialize(InterceptArgs e)

private void SetContext(DataPortalContext context)
{
// set the logical execution location
_oldLocation = Csla.ApplicationContext.LogicalExecutionLocation;
ApplicationContext.SetLogicalExecutionLocation(ApplicationContext.LogicalExecutionLocations.Server);

if (!context.IsRemotePortal && ApplicationContext.WebContextManager != null && !ApplicationContext.WebContextManager.IsValid)
if (context.IsRemotePortal)
{
// local data portal and no valid HttpContext
// if context already exists, then use existing context (from AsyncLocal or TLS)
if (ApplicationContext.ClientContext == null || ApplicationContext.ClientContext.Count == 0)
ApplicationContext.SetContext(context.ClientContext, context.GlobalContext);
// indicate that the code is physically running on the server
ApplicationContext.SetExecutionLocation(ApplicationContext.ExecutionLocations.Server);
}

// if the dataportal is not remote then
// do nothing
if (!context.IsRemotePortal) return;

// set the context value so everyone knows the
// code is running on the server
ApplicationContext.SetExecutionLocation(ApplicationContext.ExecutionLocations.Server);

// set the app context to the value we got from the
// client
// set the app context to the value we got from the caller
ApplicationContext.SetContext(context.ClientContext, context.GlobalContext);

// set the thread's culture to match the client
#if !PCL46 && !PCL259// rely on NuGet bait-and-switch for actual implementation
#if NETCORE
System.Globalization.CultureInfo.CurrentCulture =
new System.Globalization.CultureInfo(context.ClientCulture);
System.Globalization.CultureInfo.CurrentUICulture =
new System.Globalization.CultureInfo(context.ClientUICulture);
#elif NETFX_CORE
var list = new System.Collections.ObjectModel.ReadOnlyCollection<string>(new List<string> { context.ClientUICulture });
Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Languages = list;
list = new System.Collections.ObjectModel.ReadOnlyCollection<string>(new List<string> { context.ClientCulture });
Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Languages = list;
#else
System.Threading.Thread.CurrentThread.CurrentCulture =
new System.Globalization.CultureInfo(context.ClientCulture);
System.Threading.Thread.CurrentThread.CurrentUICulture =
new System.Globalization.CultureInfo(context.ClientUICulture);
#endif
#endif
// set the thread's culture to match the caller
SetCulture(context);

// set current user principal
SetPrincipal(context);
}

private static void SetPrincipal(DataPortalContext context)
{
if (ApplicationContext.AuthenticationType == "Windows")
{
// When using integrated security, Principal must be null
if (context.Principal != null)
{
Csla.Security.SecurityException ex =
new Csla.Security.SecurityException(Resources.NoPrincipalAllowedException);
//ex.Action = System.Security.Permissions.SecurityAction.Deny;
throw ex;
}
#if !(ANDROID || IOS) && !NETFX_CORE
throw new Csla.Security.SecurityException(Resources.NoPrincipalAllowedException);
// Set .NET to use integrated security
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
#endif
}
else
{
// We expect the some Principal object
// We expect some Principal object
if (context.Principal == null)
{
Csla.Security.SecurityException ex =
new Csla.Security.SecurityException(
Resources.BusinessPrincipalException + " Nothing");
//ex.Action = System.Security.Permissions.SecurityAction.Deny;
throw ex;
}
throw new Csla.Security.SecurityException(Resources.BusinessPrincipalException + " Nothing");
ApplicationContext.User = context.Principal;
}
}

private static void SetCulture(DataPortalContext context)
{
System.Threading.Thread.CurrentThread.CurrentCulture =
new System.Globalization.CultureInfo(context.ClientCulture);
System.Threading.Thread.CurrentThread.CurrentUICulture =
new System.Globalization.CultureInfo(context.ClientUICulture);
}

private void ClearContext(DataPortalContext context)
{
ApplicationContext.SetLogicalExecutionLocation(_oldLocation);
Expand Down
29 changes: 8 additions & 21 deletions Source/Csla.Shared/Server/DataPortalContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,27 +106,14 @@ public ObjectFactoryAttribute FactoryInfo
/// <param name="isRemotePortal">Indicates whether the DataPortal is remote.</param>
public DataPortalContext(IPrincipal principal, bool isRemotePortal)
{
if (isRemotePortal)
{
_principal = principal;
_remotePortal = isRemotePortal;
#if NETFX_CORE
_clientCulture = System.Globalization.CultureInfo.CurrentCulture.Name;
_clientUICulture = System.Globalization.CultureInfo.CurrentUICulture.Name;
#else
_clientCulture =
System.Threading.Thread.CurrentThread.CurrentCulture.Name;
_clientUICulture =
System.Threading.Thread.CurrentThread.CurrentUICulture.Name;
#endif
_clientContext = Csla.ApplicationContext.ContextManager.GetClientContext();
_globalContext = Csla.ApplicationContext.ContextManager.GetGlobalContext();
}
else if (ApplicationContext.WebContextManager != null && ApplicationContext.WebContextManager.IsValid)
{
_clientContext = Csla.ApplicationContext.ContextManager.GetClientContext();
_globalContext = Csla.ApplicationContext.ContextManager.GetGlobalContext();
}
_principal = principal;
_remotePortal = isRemotePortal;
_clientCulture =
System.Threading.Thread.CurrentThread.CurrentCulture.Name;
_clientUICulture =
System.Threading.Thread.CurrentThread.CurrentUICulture.Name;
_clientContext = Csla.ApplicationContext.ContextManager.GetClientContext();
_globalContext = Csla.ApplicationContext.ContextManager.GetGlobalContext();
}

/// <summary>
Expand Down

0 comments on commit dfaf152

Please sign in to comment.