using System; using System.Threading; using System.Security.Principal; using System.Collections.Specialized; using System.Configuration; using System.Web; namespace Csla { /// /// Provides consistent context information between the client /// and server DataPortal objects. /// public static class ApplicationContext { #region User /// /// Get or set the current /// object representing the user's identity. /// /// /// 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. /// 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"; /// /// Returns the application-specific context data that /// is local to the current AppDomain. /// /// /// /// The return value is a HybridDictionary. If one does /// not already exist, and empty one is created and returned. /// /// Note that data in this context is NOT transferred to and from /// the client and server. /// /// 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"; /// /// Returns the application-specific context data provided /// by the client. /// /// /// /// The return value is a HybridDictionary. If one does /// not already exist, and empty one is created and returned. /// /// Note that data in this context is transferred from /// the client to the server. No data is transferred from /// the server to the client. /// /// 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). /// /// public static HybridDictionary ClientContext { get { lock (_syncClientContext) { HybridDictionary ctx = GetClientContext(); if (ctx == null) { ctx = new HybridDictionary(); SetClientContext(ctx); } return ctx; } } } /// /// Returns the application-specific context data shared /// on both client and server. /// /// /// /// The return value is a HybridDictionary. If one does /// not already exist, and empty one is created and returned. /// /// 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. /// /// 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); } /// /// Clears all context collections. /// public static void Clear() { SetContext(null, null); SetLocalContext(null); } #endregion #region Config Settings /// /// Returns the authentication type being used by the /// CSLA .NET framework. /// /// /// /// /// 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. /// public static string AuthenticationType { get { return ConfigurationManager.AppSettings["CslaAuthentication"]; } } /// /// Returns the channel or network protocol /// for the DataPortal server. /// /// Fully qualified assembly/type name of the proxy class. /// /// /// /// This value is read from the application configuration /// file with the key value "CslaDataPortalProxy". /// /// The proxy class must implement Csla.Server.IDataPortalServer. /// /// The value "Local" is a shortcut to running the DataPortal /// "server" in the client process. /// /// Other built-in values include: /// /// /// Csla,Csla.DataPortalClient.RemotingProxy /// Use .NET Remoting to communicate with the server /// /// /// Csla,Csla.DataPortalClient.EnterpriseServicesProxy /// Use Enterprise Services (DCOM) to communicate with the server /// /// /// Csla,Csla.DataPortalClient.WebServicesProxy /// Use Web Services (asmx) to communicate with the server /// /// /// 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+. /// /// public static string DataPortalProxy { get { string result = ConfigurationManager.AppSettings["CslaDataPortalProxy"]; if (string.IsNullOrEmpty(result)) result = "Local"; return result; } } /// /// Returns the URL for the DataPortal server. /// /// /// /// /// This value is read from the application configuration /// file with the key value "CslaDataPortalUrl". /// public static Uri DataPortalUrl { get { return new Uri(ConfigurationManager.AppSettings["CslaDataPortalUrl"]); } } /// /// Enum representing the locations code can execute. /// public enum ExecutionLocations { /// /// The code is executing on the client. /// Client, /// /// The code is executing on the application server. /// Server } #endregion #region In-Memory Settings private static ExecutionLocations _executionLocation = ExecutionLocations.Client; /// /// Returns a value indicating whether the application code /// is currently executing on the client or server. /// public static ExecutionLocations ExecutionLocation { get { return _executionLocation; } } internal static void SetExecutionLocation(ExecutionLocations location) { _executionLocation = location; } #endregion } }