369 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			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
 | |
| 
 | |
|   }
 | |
| } |