Documentation Coverage Report
Current view: top level - Cqrs/Hosts - CqrsHttpApplication.cs Hit Total Coverage
Version: 2.2 Artefacts: 17 17 100.0 %
Date: 2017-09-22

          Line data    Source code
       1             : #region Copyright
       2             : // // -----------------------------------------------------------------------
       3             : // // <copyright company="Chinchilla Software Limited">
       4             : // //   Copyright Chinchilla Software Limited. All rights reserved.
       5             : // // </copyright>
       6             : // // -----------------------------------------------------------------------
       7             : #endregion
       8             : 
       9             : using System;
      10             : using System.Collections.Generic;
      11             : using System.Linq;
      12             : using System.Reflection;
      13             : using System.Security;
      14             : using System.Web;
      15             : using System.Web.SessionState;
      16             : using cdmdotnet.Logging;
      17             : using Cqrs.Authentication;
      18             : using Cqrs.Commands;
      19             : using Cqrs.Configuration;
      20             : using Cqrs.Events;
      21             : using Cqrs.Services;
      22             : 
      23             : namespace Cqrs.Hosts
      24             : {
      25             :         /// <summary>
      26             :         /// An <see cref="HttpApplication"/> that prepares and configures CQRS with use in IIS or other web server.
      27             :         /// </summary>
      28             :         public abstract class CqrsHttpApplication
      29             :                 : HttpApplication
      30             :         {
      31             :                 /// <summary>
      32             :                 /// Each <see cref="Type"/> will be traced back to it's assembly, and that assembly will be scanned for other handlers to auto register.
      33             :                 /// </summary>
      34             :                 protected Type[] HandlerTypes { get; set; }
      35             : 
      36             :                 /// <summary>
      37             :                 /// The <see cref="IEventReceiver"/> that will be configured to receive <see cref="IEvent{TAuthenticationToken}">events</see>.
      38             :                 /// </summary>
      39             :                 protected IEventReceiver EventBus { get; set; }
      40             : 
      41             :                 /// <summary>
      42             :                 /// The <see cref="ICommandReceiver"/> that will be configured to receive <see cref="ICommand{TAuthenticationToken}">commands</see>.
      43             :                 /// </summary>
      44             :                 protected ICommandReceiver CommandBus { get; set; }
      45             : 
      46             :                 /// <summary>
      47             :                 /// Instantiate a new instance of a <see cref="CqrsHttpApplication"/>
      48             :                 /// </summary>
      49           2 :                 protected CqrsHttpApplication()
      50             :                 {
      51             :                         HandlerTypes = new Type[]{};
      52             :                 }
      53             : 
      54             :                 /// <summary>
      55             :                 /// Calls <see cref="SetBuses"/>, <see cref="RegisterCommandAndEventHandlers"/>, <see cref="RegisterServiceParameterResolver"/>, <see cref="StartBuses"/> and finally <see cref="LogApplicationStarted"/>.
      56             :                 /// Gets executed once during the life cycle of the application when the first request for any resource in the application is made. A resource can be a page or an image in the application. 
      57             :                 /// If the server where the application is hosted is restarted then this is fired once again upon the first request for any resource in the application.
      58             :                 /// </summary>
      59           2 :                 protected virtual void Application_Start(object sender, EventArgs e)
      60             :                 {
      61             :                         SetBuses();
      62             : 
      63             :                         RegisterCommandAndEventHandlers();
      64             :                         RegisterServiceParameterResolver();
      65             : 
      66             :                         StartBuses();
      67             : 
      68             :                         LogApplicationStarted();
      69             :                 }
      70             : 
      71             :                 /// <summary>
      72             :                 /// Set <see cref="EventBus"/> and <see cref="CommandBus"/>.
      73             :                 /// </summary>
      74           2 :                 protected abstract void SetBuses();
      75             : 
      76             :                 /// <summary>
      77             :                 /// Start the <see cref="BusRegistrar"/> by calling <see cref="BusRegistrar.Register(System.Type[])"/> passing <see cref="HandlerTypes"/>
      78             :                 /// </summary>
      79           2 :                 protected virtual BusRegistrar RegisterCommandAndEventHandlers()
      80             :                 {
      81             :                         var registrar = new BusRegistrar(DependencyResolver.Current);
      82             :                         registrar.Register(HandlerTypes);
      83             : 
      84             :                         return registrar;
      85             :                 }
      86             : 
      87             :                 /// <summary>
      88             :                 /// Call the static "RegisterDataContracts" method on any <see cref="IServiceParameterResolver"/> we can find in the <see cref="Assembly"/> of any <see cref="Type"/> in <see cref="HandlerTypes"/>
      89             :                 /// </summary>
      90           2 :                 protected virtual void RegisterServiceParameterResolver()
      91             :                 {
      92             :                         foreach (Type handlerType in HandlerTypes)
      93             :                         {
      94             :                                 Assembly executorsAssembly = handlerType.Assembly;
      95             :                                 IEnumerable<Type> serviceParameterResolverTypes = executorsAssembly
      96             :                                         .GetTypes()
      97             :                                         .Where(type => typeof(IServiceParameterResolver).IsAssignableFrom(type));
      98             : 
      99             :                                 foreach (Type serviceParameterResolverType in serviceParameterResolverTypes)
     100             :                                 {
     101             :                                         MethodInfo registerDataContractsMethod = serviceParameterResolverType.GetMethod("RegisterDataContracts");
     102             :                                         if (registerDataContractsMethod != null)
     103             :                                                 registerDataContractsMethod.Invoke(null, null);
     104             :                                 }
     105             :                         }
     106             :                 }
     107             : 
     108             :                 /// <summary>
     109             :                 /// Starts the command bus and event bus receivers depending on configuration settings
     110             :                 /// </summary>
     111           2 :                 protected virtual void StartBuses()
     112             :                 {
     113             : 
     114             :                         var configurationManager = DependencyResolver.Current.Resolve<IConfigurationManager>();
     115             :                         bool setting;
     116             :                         if (!configurationManager.TryGetSetting("Cqrs.Hosts.EnableEventReceiving", out setting))
     117             :                                 setting = true;
     118             :                         if (setting)
     119             :                                 EventBus.Start();
     120             :                         if (!configurationManager.TryGetSetting("Cqrs.Hosts.EnableCommandReceiving", out setting))
     121             :                                 setting = true;
     122             :                         if (setting)
     123             :                                 CommandBus.Start();
     124             :                 }
     125             : 
     126             :                 /// <summary>
     127             :                 /// Log that the application has started
     128             :                 /// </summary>
     129           2 :                 protected virtual void LogApplicationStarted()
     130             :                 {
     131             :                         try
     132             :                         {
     133             :                                 ILogger logger = DependencyResolver.Current.Resolve<ILogger>();
     134             : 
     135             :                                 if (logger != null)
     136             :                                 {
     137             :                                         DependencyResolver.Current.Resolve<ICorrelationIdHelper>().SetCorrelationId(Guid.Empty);
     138             :                                         logger.LogInfo("Application started.");
     139             :                                 }
     140             :                         }
     141             :                         catch { /* */ }
     142             :                 }
     143             : 
     144             :                 /// <summary>
     145             :                 /// Gets executed once during the life cycle of the application when it is unloaded.
     146             :                 /// This is normally fired when the application is taken off-line or when the server is stopped.
     147             :                 /// </summary>
     148           2 :                 protected virtual void Application_End(object sender, EventArgs e)
     149             :                 {
     150             :                         try
     151             :                         {
     152             :                                 ILogger logger = DependencyResolver.Current.Resolve<ILogger>();
     153             : 
     154             :                                 if (logger != null)
     155             :                                 {
     156             :                                         DependencyResolver.Current.Resolve<ICorrelationIdHelper>().SetCorrelationId(Guid.Empty);
     157             :                                         logger.LogInfo("Application stopped.");
     158             :                                 }
     159             :                         }
     160             :                         catch { /* */ }
     161             :                 }
     162             : 
     163             :                 /// <summary>
     164             :                 /// Logs all error via <see cref="ILogger.LogError"/> unless the execution is <see cref="SecurityException"/>, in which case <see cref="ILogger.LogWarning"/> is used.
     165             :                 /// Gets executed when any un-handled <see cref="Exception"/>/error occurs anywhere in the application. Any un-handled <see cref="Exception"/> here means exception which are not caught using try catch block. Also if you have custom errors enabled in your application i.e. in web.config file then the configuration in web.config takes precedence and all errors will be directed to the file mentioned in the tag.
     166             :                 /// </summary>
     167           2 :                 protected virtual void Application_Error(object sender, EventArgs e)
     168             :                 {
     169             :                         try
     170             :                         {
     171             :                                 Exception ex = Server.GetLastError();
     172             : 
     173             :                                 ILogger logger = DependencyResolver.Current.Resolve<ILogger>();
     174             :                                 Action<string, string, Exception, IDictionary<string, object>, IDictionary<string, object>> loggerFunction = logger.LogError;
     175             :                                 if (ex is SecurityException)
     176             :                                         loggerFunction = logger.LogWarning;
     177             : 
     178             :                                 loggerFunction("An error occurred.", null, ex, null, null);
     179             :                         }
     180             :                         catch { /* */ }
     181             :                 }
     182             : 
     183             :                 /// <summary>
     184             :                 /// Gets executed for each and every request which comes to the application to generate a new CorrelationId and then sets the generated CorrelationId via <see cref="ICorrelationIdHelper.SetCorrelationId"/>.
     185             :                 /// The generated CorrelationId is also set in the <see cref="HttpResponse.Headers"/>.
     186             :                 /// </summary>
     187           2 :                 protected virtual void Application_BeginRequest(object sender, EventArgs e)
     188             :                 {
     189             :                         try
     190             :                         {
     191             :                                 Guid correlationId = Guid.NewGuid();
     192             :                                 DependencyResolver.Current.Resolve<ICorrelationIdHelper>().SetCorrelationId(correlationId);
     193             :                                 Response.AddHeader("CorrelationId", correlationId.ToString("N"));
     194             :                         }
     195             :                         catch (NullReferenceException) { }
     196             :                 }
     197             : 
     198             :                 /// <summary>
     199             :                 /// Gets executed after <see cref="Application_BeginRequest"/> and before the stream starts getting sent to the client.
     200             :                 /// </summary>
     201           2 :                 protected virtual void Application_EndRequest(object sender, EventArgs e)
     202             :                 {
     203             :                 }
     204             : 
     205             :                 /// <summary>
     206             :                 /// Gets executed after <see cref="Application_BeginRequest"/>.
     207             :                 /// Override this method to extract any authentication token from the request and then call <see cref="IAuthenticationTokenHelper{TAuthenticationToken}.SetAuthenticationToken"/>.
     208             :                 /// </summary>
     209           2 :                 protected virtual void Application_AuthenticateRequest(object sender, EventArgs e)
     210             :                 {
     211             :                 }
     212             : 
     213             :                 /// <summary>
     214             :                 /// Makes a call to retrieve the <see cref="HttpSessionState.SessionID"/>. This is done so the session is generated at the beginning of the request.
     215             :                 /// If this isn't called the session (when using WCF) is generated late in the pipeline, which can cause issues when trying to work with WCF.
     216             :                 /// Gets executed after <see cref="Application_AuthenticateRequest"/> when a new session for a "user" starts such as a first request or after a session has expired.
     217             :                 /// This event doesn't get triggered if you are not using sessions which can be disabled in the web.config.
     218             :                 /// </summary>
     219           2 :                 protected virtual void Session_Start(object sender, EventArgs e)
     220             :                 {
     221             :                         // This is required otherwise the first call per new session will fail due to a WCF issue. This forces the SessionID to be created now, not after the response has been flushed on the pipeline.
     222             :                         // ReSharper disable UnusedVariable
     223             :                         string sessionId = Session.SessionID;
     224             :                         // ReSharper restore UnusedVariable
     225             :                 }
     226             : 
     227             :                 /// <summary>
     228             :                 /// Whenever a user's session in the application expires this gets executed. The session is no longer available or accessible. 
     229             :                 /// The session expiration time can be set in web.config file. By default session time out is set to 20 mins.
     230             :                 /// </summary>
     231           2 :                 protected virtual void Session_End(object sender, EventArgs e)
     232             :                 {
     233             :                 }
     234             :         }
     235             : 
     236             :         /// <summary>
     237             :         /// An <see cref="HttpApplication"/> that prepares and configures CQRS with use in IIS or other web server with knowledge of a basic type authentication token being sent in <see cref="HttpRequest.Headers"/>, <see cref="HttpRequest.Cookies"/>, <see cref="HttpRequest.Form"/> or <see cref="HttpRequest.QueryString"/>.
     238             :         /// A basic type authentication token is <see cref="Guid"/>, <see cref="string"/> or <see cref="int"/>.
     239             :         /// </summary>
     240             :         /// <typeparam name="TAuthenticationToken">The <see cref="Type"/> of the authentication token.</typeparam>
     241             :         public abstract class CqrsHttpApplication<TAuthenticationToken>
     242             :                 : CqrsHttpApplication
     243           2 :         {
     244             :                 #region Overrides of CqrsHttpApplication
     245             : 
     246             :                 /// <summary>
     247             :                 /// Gets executed after <see cref="CqrsHttpApplication.Application_BeginRequest"/>.
     248             :                 /// Extracts the authentication token looking for a <see cref="KeyValuePair{TKey,TValue}"/> where the key as defined by the <see cref="System.Configuration.ConfigurationManager.AppSettings"/> "Cqrs.Web.AuthenticationTokenName",
     249             :                 /// from the <see cref="HttpRequest.Headers"/>, if one isn't found we then try the following in order 
     250             :                 /// <see cref="HttpRequest.Cookies"/>, <see cref="HttpRequest.Form"/> or <see cref="HttpRequest.QueryString"/>; then
     251             :                 /// calls <see cref="IAuthenticationTokenHelper{TAuthenticationToken}.SetAuthenticationToken"/> to make it accessible to others parts of the system if one is found.
     252             :                 /// </summary>
     253           2 :                 protected override void Application_AuthenticateRequest(object sender, EventArgs e)
     254             :                 {
     255             :                         if (typeof (TAuthenticationToken) != typeof (Guid) && typeof (TAuthenticationToken) != typeof (string) && typeof (TAuthenticationToken) != typeof (int))
     256             :                                 return;
     257             : 
     258             :                         string authenticationTokenName = DependencyResolver.Current.Resolve<IConfigurationManager>().GetSetting("Cqrs.Web.AuthenticationTokenName") ?? "X-Token";
     259             : 
     260             :                         string xToken = Request.Headers[authenticationTokenName];
     261             :                         if (string.IsNullOrWhiteSpace(xToken))
     262             :                         {
     263             :                                 HttpCookie authCookie = Request.Cookies[authenticationTokenName];
     264             :                                 if (authCookie != null)
     265             :                                         xToken = authCookie.Value;
     266             :                         }
     267             :                         if (string.IsNullOrWhiteSpace(xToken))
     268             :                                 xToken = Request.Form[authenticationTokenName];
     269             :                         if (string.IsNullOrWhiteSpace(xToken))
     270             :                                 xToken = Request.QueryString[authenticationTokenName];
     271             :                         if (typeof(TAuthenticationToken) == typeof(Guid))
     272             :                         {
     273             :                                 Guid token;
     274             :                                 if (Guid.TryParse(xToken, out token))
     275             :                                 {
     276             :                                         // Pass the authentication token to the helper to allow automated authentication handling
     277             :                                         DependencyResolver.Current.Resolve<IAuthenticationTokenHelper<TAuthenticationToken>>().SetAuthenticationToken((TAuthenticationToken)(object)token);
     278             :                                 }
     279             :                         }
     280             :                         else if (typeof(TAuthenticationToken) == typeof(int))
     281             :                         {
     282             :                                 int token;
     283             :                                 if (int.TryParse(xToken, out token))
     284             :                                 {
     285             :                                         // Pass the authentication token to the helper to allow automated authentication handling
     286             :                                         DependencyResolver.Current.Resolve<IAuthenticationTokenHelper<TAuthenticationToken>>().SetAuthenticationToken((TAuthenticationToken)(object)token);
     287             :                                 }
     288             :                         }
     289             :                         else
     290             :                                 DependencyResolver.Current.Resolve<IAuthenticationTokenHelper<TAuthenticationToken>>().SetAuthenticationToken((TAuthenticationToken)(object)xToken);
     291             :                 }
     292             : 
     293             :                 /// <summary>
     294             :                 /// Set <see cref="CqrsHttpApplication.EventBus"/> and <see cref="CqrsHttpApplication.CommandBus"/>.
     295             :                 /// </summary>
     296           2 :                 protected override void SetBuses()
     297             :                 {
     298             :                         EventBus = DependencyResolver.Current.Resolve<IEventReceiver<TAuthenticationToken>>();
     299             :                         CommandBus = DependencyResolver.Current.Resolve<ICommandReceiver<TAuthenticationToken>>();
     300             :                 }
     301             : 
     302             :                 #endregion
     303             :         }
     304             : }

Generated by: LCOV version 1.10