// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // Since this method is resolved through the DI already, we can request any registered services by // just adding respective parameters. public void Configure( IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IEventTopic eventTopic, DenormalizerDispatcher dispatcher, CommandHandlerFactory commandHandlerFactory, IOptions <AzureTableStorageOptions> tableStorageOptions, IHubContext <CommandBus> commandBus) { Startup.CommandBus = commandBus; var configureLogger = loggerFactory.CreateLogger("Configure"); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); app.UseRewriter(new RewriteOptions().AddRedirectToHttps()); } app.UseStaticFiles(); app.UseAuthentication(); // Replay all events once from DB to the in-memory query model. // Explicitly wait as routing (below) and controllers expect the state is loaded . ReplayEvents(loggerFactory, dispatcher, tableStorageOptions.Value).Wait(); // Register all denormalizers to listen for all events. Could have more fine grained subscription logic, but this works for now. foreach (var d in dispatcher.Denormalizers.Cast <IEventConsumer>()) { configureLogger.LogInformation("Registering denormalizer {0} to receive all events", d.GetType()); eventTopic.Subscribe(d); } // Register all command handlers to listen for all events. foreach (var d in commandHandlerFactory.All.Cast <IEventConsumer>()) { configureLogger.LogInformation("Registering command handler {0} to receive all events", d.GetType()); eventTopic.Subscribe(d); } // Routes use event data (state after events), therefore register routes only after the replay string defaultHappening = QueryModelRepository.Routing.DefaultHappening; app.UseMvc(routes => { routes.MapRoute( name: "root", template: "{happening:regex(^satku[a-z]+$)?}", defaults: new { happening = defaultHappening, Controller = "Home", Action = "Index" }, constraints: null, dataTokens: new { DefaultHappening = defaultHappening }); routes.MapRoute( name: "default", template: "{happening:regex(^satku[a-z]+$)}/{*catchall}", defaults: new { happening = defaultHappening, Controller = "Home", Action = "Index" }, constraints: null, dataTokens: new { DefaultHappening = defaultHappening }); }); app.UseSignalR(routes => { routes.MapHub <CommandBus>("commandbus"); }); }