369 lines
11 KiB
C#

using System;
using System.Threading;
using System.Security.Principal;
using System.Collections.Specialized;
using System.Configuration;
using System.Web;
namespace Csla
{
/// <summary>
/// Provides consistent context information between the client
/// and server DataPortal objects.
/// </summary>
public static class ApplicationContext
{
#region User
/// <summary>
/// Get or set the current <see cref="IPrincipal" />
/// object representing the user's identity.
/// </summary>
/// <remarks>
/// This is discussed in Chapter 5. When running
/// under IIS the HttpContext.Current.User value
/// is used, otherwise the current Thread.CurrentPrincipal
/// value is used.
/// </remarks>
public static IPrincipal User
{
get
{
if (HttpContext.Current == null)
return Thread.CurrentPrincipal;
else
return HttpContext.Current.User;
}
set
{
if (HttpContext.Current != null)
HttpContext.Current.User = value;
Thread.CurrentPrincipal = value;
}
}
#endregion
#region LocalContext
private const string _localContextName = "Csla.LocalContext";
/// <summary>
/// Returns the application-specific context data that
/// is local to the current AppDomain.
/// </summary>
/// <remarks>
/// <para>
/// The return value is a HybridDictionary. If one does
/// not already exist, and empty one is created and returned.
/// </para><para>
/// Note that data in this context is NOT transferred to and from
/// the client and server.
/// </para>
/// </remarks>
public static HybridDictionary LocalContext
{
get
{
HybridDictionary ctx = GetLocalContext();
if (ctx == null)
{
ctx = new HybridDictionary();
SetLocalContext(ctx);
}
return ctx;
}
}
private static HybridDictionary GetLocalContext()
{
if (HttpContext.Current == null)
{
LocalDataStoreSlot slot = Thread.GetNamedDataSlot(_localContextName);
return (HybridDictionary)Thread.GetData(slot);
}
else
return (HybridDictionary)HttpContext.Current.Items[_localContextName];
}
private static void SetLocalContext(HybridDictionary localContext)
{
if (HttpContext.Current == null)
{
LocalDataStoreSlot slot = Thread.GetNamedDataSlot(_localContextName);
Thread.SetData(slot, localContext);
}
else
HttpContext.Current.Items[_localContextName] = localContext;
}
#endregion
#region Client/Global Context
private static object _syncClientContext = new object();
private const string _clientContextName = "Csla.ClientContext";
private const string _globalContextName = "Csla.GlobalContext";
/// <summary>
/// Returns the application-specific context data provided
/// by the client.
/// </summary>
/// <remarks>
/// <para>
/// The return value is a HybridDictionary. If one does
/// not already exist, and empty one is created and returned.
/// </para><para>
/// Note that data in this context is transferred from
/// the client to the server. No data is transferred from
/// the server to the client.
/// </para><para>
/// This property is thread safe in a Windows client
/// setting and on an application server. It is not guaranteed
/// to be thread safe within the context of an ASP.NET
/// client setting (i.e. in your ASP.NET UI).
/// </para>
/// </remarks>
public static HybridDictionary ClientContext
{
get
{
lock (_syncClientContext)
{
HybridDictionary ctx = GetClientContext();
if (ctx == null)
{
ctx = new HybridDictionary();
SetClientContext(ctx);
}
return ctx;
}
}
}
/// <summary>
/// Returns the application-specific context data shared
/// on both client and server.
/// </summary>
/// <remarks>
/// <para>
/// The return value is a HybridDictionary. If one does
/// not already exist, and empty one is created and returned.
/// </para><para>
/// Note that data in this context is transferred to and from
/// the client and server. Any objects or data in this context
/// will be transferred bi-directionally across the network.
/// </para>
/// </remarks>
public static HybridDictionary GlobalContext
{
get
{
HybridDictionary ctx = GetGlobalContext();
if (ctx == null)
{
ctx = new HybridDictionary();
SetGlobalContext(ctx);
}
return ctx;
}
}
internal static HybridDictionary GetClientContext()
{
if (HttpContext.Current == null)
{
if (ApplicationContext.ExecutionLocation == ExecutionLocations.Client)
lock (_syncClientContext)
return (HybridDictionary)AppDomain.CurrentDomain.GetData(_clientContextName);
else
{
LocalDataStoreSlot slot =
Thread.GetNamedDataSlot(_clientContextName);
return (HybridDictionary)Thread.GetData(slot);
}
}
else
return (HybridDictionary)
HttpContext.Current.Items[_clientContextName];
}
internal static HybridDictionary GetGlobalContext()
{
if (HttpContext.Current == null)
{
LocalDataStoreSlot slot = Thread.GetNamedDataSlot(_globalContextName);
return (HybridDictionary)Thread.GetData(slot);
}
else
return (HybridDictionary)HttpContext.Current.Items[_globalContextName];
}
private static void SetClientContext(HybridDictionary clientContext)
{
if (HttpContext.Current == null)
{
if (ApplicationContext.ExecutionLocation == ExecutionLocations.Client)
lock (_syncClientContext)
AppDomain.CurrentDomain.SetData(_clientContextName, clientContext);
else
{
LocalDataStoreSlot slot = Thread.GetNamedDataSlot(_clientContextName);
Thread.SetData(slot, clientContext);
}
}
else
HttpContext.Current.Items[_clientContextName] = clientContext;
}
internal static void SetGlobalContext(HybridDictionary globalContext)
{
if (HttpContext.Current == null)
{
LocalDataStoreSlot slot = Thread.GetNamedDataSlot(_globalContextName);
Thread.SetData(slot, globalContext);
}
else
HttpContext.Current.Items[_globalContextName] = globalContext;
}
internal static void SetContext(
HybridDictionary clientContext,
HybridDictionary globalContext)
{
SetClientContext(clientContext);
SetGlobalContext(globalContext);
}
/// <summary>
/// Clears all context collections.
/// </summary>
public static void Clear()
{
SetContext(null, null);
SetLocalContext(null);
}
#endregion
#region Config Settings
/// <summary>
/// Returns the authentication type being used by the
/// CSLA .NET framework.
/// </summary>
/// <value></value>
/// <returns></returns>
/// <remarks>
/// This value is read from the application configuration
/// file with the key value "CslaAuthentication". The value
/// "Windows" indicates CSLA .NET should use Windows integrated
/// (or AD) security. Any other value indicates the use of
/// custom security derived from BusinessPrincipalBase.
/// </remarks>
public static string AuthenticationType
{
get { return ConfigurationManager.AppSettings["CslaAuthentication"]; }
}
/// <summary>
/// Returns the channel or network protocol
/// for the DataPortal server.
/// </summary>
/// <value>Fully qualified assembly/type name of the proxy class.</value>
/// <returns></returns>
/// <remarks>
/// <para>
/// This value is read from the application configuration
/// file with the key value "CslaDataPortalProxy".
/// </para><para>
/// The proxy class must implement Csla.Server.IDataPortalServer.
/// </para><para>
/// The value "Local" is a shortcut to running the DataPortal
/// "server" in the client process.
/// </para><para>
/// Other built-in values include:
/// <list>
/// <item>
/// <term>Csla,Csla.DataPortalClient.RemotingProxy</term>
/// <description>Use .NET Remoting to communicate with the server</description>
/// </item>
/// <item>
/// <term>Csla,Csla.DataPortalClient.EnterpriseServicesProxy</term>
/// <description>Use Enterprise Services (DCOM) to communicate with the server</description>
/// </item>
/// <item>
/// <term>Csla,Csla.DataPortalClient.WebServicesProxy</term>
/// <description>Use Web Services (asmx) to communicate with the server</description>
/// </item>
/// </list>
/// Each proxy type does require that the DataPortal server be hosted using the appropriate
/// technology. For instance, Web Services and Remoting should be hosted in IIS, while
/// Enterprise Services must be hosted in COM+.
/// </para>
/// </remarks>
public static string DataPortalProxy
{
get
{
string result = ConfigurationManager.AppSettings["CslaDataPortalProxy"];
if (string.IsNullOrEmpty(result))
result = "Local";
return result;
}
}
/// <summary>
/// Returns the URL for the DataPortal server.
/// </summary>
/// <value></value>
/// <returns></returns>
/// <remarks>
/// This value is read from the application configuration
/// file with the key value "CslaDataPortalUrl".
/// </remarks>
public static Uri DataPortalUrl
{
get { return new Uri(ConfigurationManager.AppSettings["CslaDataPortalUrl"]); }
}
/// <summary>
/// Enum representing the locations code can execute.
/// </summary>
public enum ExecutionLocations
{
/// <summary>
/// The code is executing on the client.
/// </summary>
Client,
/// <summary>
/// The code is executing on the application server.
/// </summary>
Server
}
#endregion
#region In-Memory Settings
private static ExecutionLocations _executionLocation =
ExecutionLocations.Client;
/// <summary>
/// Returns a value indicating whether the application code
/// is currently executing on the client or server.
/// </summary>
public static ExecutionLocations ExecutionLocation
{
get { return _executionLocation; }
}
internal static void SetExecutionLocation(ExecutionLocations location)
{
_executionLocation = location;
}
#endregion
}
}