/// <summary> /// Setup dependency injection for cloudscribe components /// </summary> /// <param name="services"></param> /// <param name="configuration"></param> /// <returns></returns> public static IServiceCollection ConfigureCloudscribeCore(this IServiceCollection services, IConfigurationRoot configuration) { services.AddCaching(); services.AddSession(); //services.ConfigureSession(o => //{ // o.IdleTimeout = TimeSpan.FromSeconds(10); //}); services.Configure <MultiTenantOptions>(configuration.GetSection("MultiTenantOptions")); services.Configure <SiteConfigOptions>(configuration.GetSection("SiteConfigOptions")); services.Configure <SetupOptions>(configuration.GetSection("SetupOptions")); services.Configure <UIOptions>(configuration.GetSection("UIOptions")); services.Configure <cloudscribe.Core.Web.Components.Editor.CkeditorOptions>(configuration.GetSection("CkeditorOptions")); services.AddScoped <cloudscribe.Core.Models.Setup.ISetupTask, cloudscribe.Core.Web.Components.EnsureInitialDataSetupTask>(); //services.AddScoped<cloudscribe.Core.Models.Setup.ISetupStep, cloudscribe.Core.Web.Components.EnsureSiteSetupStep2>(); //*** Database platform **************************************************************** // here is where you could change to use one of the other db platforms // we have support for MSSQL MySql, PostgreSql, Firebird, SQLite, and SqlCe // as of 2015-11-12 mssql, sqlite, pgsql work in dnxcore50 // to use one of the others you would have to remove the dnxcore50 from the project.json in this project // add a reference for one of the other cloudscribe.Core.Repositories.dbplatform // and cloudscribe.DbHelpers.dbplatform packages // this DevOptions can override from appsettings.localoverides.json // making it easy to change the db platform you are working with DevOptions devOptions = configuration.Get <DevOptions>("DevOptions"); switch (devOptions.DbPlatform) { // the commented ones don't work yet in dnxcore50 so we can't add them to project.json // without dropping dnxcore50 //case "sqlce": // services.Configure<cloudscribe.DbHelpers.SqlCe.SqlCeConnectionOptions>(configuration.GetSection("Data:SqlCeConnectionOptions")); // services.TryAddScoped<ISiteRepository, cloudscribe.Core.Repositories.SqlCe.SiteRepository>(); // services.TryAddScoped<IUserRepository, cloudscribe.Core.Repositories.SqlCe.UserRepository>(); // services.TryAddScoped<IGeoRepository, cloudscribe.Core.Repositories.SqlCe.GeoRepository>(); // services.TryAddScoped<IDbSetup, cloudscribe.Setup.SqlCe.DbSetup>(); // services.TryAddScoped<IDataPlatformInfo, cloudscribe.Setup.SqlCe.DbSetup>(); // services.TryAddScoped<ILogRepository, cloudscribe.Logging.SqlCe.LogRepository>(); // services.TryAddScoped<cloudscribe.DbHelpers.SqlCe.SqlCeConnectionStringResolver, cloudscribe.DbHelpers.SqlCe.SqlCeConnectionStringResolver>(); // break; //case "firebird": // services.Configure<cloudscribe.DbHelpers.ConnectionStringOptions>(configuration.GetSection("Data:Firebird:ConnectionStringOptions")); // services.TryAddScoped<ISiteRepository, cloudscribe.Core.Repositories.Firebird.SiteRepository>(); // services.TryAddScoped<IUserRepository, cloudscribe.Core.Repositories.Firebird.UserRepository>(); // services.TryAddScoped<IGeoRepository, cloudscribe.Core.Repositories.Firebird.GeoRepository>(); // services.TryAddScoped<IDbSetup, cloudscribe.Setup.Firebird.DbSetup>(); // services.TryAddScoped<IDataPlatformInfo, cloudscribe.Setup.Firebird.DbSetup>(); // services.TryAddScoped<ILogRepository, cloudscribe.Logging.Firebird.LogRepository>(); // break; //case "mysql": // services.Configure<cloudscribe.DbHelpers.ConnectionStringOptions>(configuration.GetSection("Data:MySql:ConnectionStringOptions")); // services.TryAddScoped<ISiteRepository, cloudscribe.Core.Repositories.MySql.SiteRepository>(); // services.TryAddScoped<IUserRepository, cloudscribe.Core.Repositories.MySql.UserRepository>(); // services.TryAddScoped<IGeoRepository, cloudscribe.Core.Repositories.MySql.GeoRepository>(); // services.TryAddScoped<IDbSetup, cloudscribe.Setup.MySql.DbSetup>(); // services.TryAddScoped<IDataPlatformInfo, cloudscribe.Setup.MySql.DbSetup>(); // services.TryAddScoped<ILogRepository, cloudscribe.Logging.MySql.LogRepository>(); // break; //case "sqlite": // services.Configure<cloudscribe.DbHelpers.SQLite.SqliteConnectionOptions>(configuration.GetSection("Data:SqliteConnectionOptions")); // services.TryAddScoped<ISiteRepository, cloudscribe.Core.Repositories.SQLite.SiteRepository>(); // services.TryAddScoped<IUserRepository, cloudscribe.Core.Repositories.SQLite.UserRepository>(); // services.TryAddScoped<IGeoRepository, cloudscribe.Core.Repositories.SQLite.GeoRepository>(); // services.TryAddScoped<IDbSetup, cloudscribe.Setup.Sqlite.DbSetup>(); // services.TryAddScoped<IDataPlatformInfo, cloudscribe.Setup.Sqlite.DbSetup>(); // services.TryAddScoped<ILogRepository, cloudscribe.Logging.Sqlite.LogRepository>(); // services.TryAddScoped<cloudscribe.DbHelpers.SQLite.SqliteConnectionstringResolver, cloudscribe.DbHelpers.SQLite.SqliteConnectionstringResolver>(); // break; //case "pgsql": // services.Configure<cloudscribe.DbHelpers.ConnectionStringOptions>(configuration.GetSection("Data:PostgreSql:ConnectionStringOptions")); // services.TryAddScoped<ISiteRepository, cloudscribe.Core.Repositories.pgsql.SiteRepository>(); // services.TryAddScoped<IUserRepository, cloudscribe.Core.Repositories.pgsql.UserRepository>(); // services.TryAddScoped<IGeoRepository, cloudscribe.Core.Repositories.pgsql.GeoRepository>(); // services.TryAddScoped<IDbSetup, cloudscribe.Setup.pgsql.DbSetup>(); // services.TryAddScoped<IDataPlatformInfo, cloudscribe.Setup.pgsql.DbSetup>(); // services.TryAddScoped<ILogRepository, cloudscribe.Logging.pgsql.LogRepository>(); // break; //case "mssql": //services.Configure<cloudscribe.DbHelpers.MSSQLConnectionOptions>(configuration.GetSection("Data:MSSQLConnectionOptions")); //services.TryAddScoped<ISiteRepository, cloudscribe.Core.Repositories.MSSQL.SiteRepository>(); //services.TryAddScoped<IUserRepository, cloudscribe.Core.Repositories.MSSQL.UserRepository>(); //services.TryAddScoped<IGeoRepository, cloudscribe.Core.Repositories.MSSQL.GeoRepository>(); //services.TryAddScoped<IDbSetup, cloudscribe.Setup.MSSQL.DbSetup>(); //services.TryAddScoped<IDataPlatformInfo, cloudscribe.Setup.MSSQL.DbSetup>(); //services.TryAddScoped<ILogRepository, cloudscribe.Logging.MSSQL.LogRepository>(); case "ef7": services.TryAddScoped <ICoreModelMapper, SqlServerCoreModelMapper>(); services.TryAddScoped <cloudscribe.Logging.EF.ILogModelMapper, cloudscribe.Logging.EF.SqlServerLogModelMapper>(); services.AddEntityFramework() .AddSqlServer() .AddDbContext <CoreDbContext>(options => options.UseSqlServer(configuration["Data:EF7ConnectionOptions:ConnectionString"]) // this is needed if you use sqlserver 2008 // .UseRowNumberForPaging() ) .AddDbContext <cloudscribe.Logging.EF.LoggingDbContext>(options => options.UseSqlServer(configuration["Data:EF7ConnectionOptions:ConnectionString"]) ); services.TryAddScoped <ISiteRepository, cloudscribe.Core.Repositories.EF.SiteRepository>(); services.TryAddScoped <IUserRepository, cloudscribe.Core.Repositories.EF.UserRepository>(); services.TryAddScoped <IGeoRepository, cloudscribe.Core.Repositories.EF.GeoRepository>(); services.TryAddScoped <IDataPlatformInfo, cloudscribe.Core.Repositories.EF.DataPlatformInfo>(); services.TryAddScoped <ILogRepository, cloudscribe.Logging.EF.LogRepository>(); break; } //************************************************************************************** // RequestSiteResolver resolves ISiteSettings based on the request to support multi tenancy based on either host name or first folder depending on configuration //services.TryAddScoped<ISiteResolver, RequestSiteResolver>(); services.TryAddScoped <ITimeZoneResolver, RequestTimeZoneResolver>(); //services.AddMultitenancy<SiteSettings, SiteResolver>(); services.AddMultitenancy <SiteSettings, CachingSiteResolver>(); services.TryAddScoped <SiteManager, SiteManager>(); services.TryAddScoped <SetupManager, SetupManager>(); services.TryAddScoped <GeoDataManager, GeoDataManager>(); services.TryAddScoped <SystemInfoManager, SystemInfoManager>(); services.TryAddScoped <IpAddressTracker, IpAddressTracker>(); // services.TryAddScoped <SiteDataProtector, SiteDataProtector>(); // VersionProviders are used by the Setup controller to determine what install and upgrade scripts to run services.AddScoped <IVersionProvider, SetupVersionProvider>(); services.AddScoped <IVersionProvider, CloudscribeCoreVersionProvider>(); services.AddScoped <IVersionProvider, cloudscribe.Logging.Web.CloudscribeLoggingVersionProvider>(); // the factory will provide access to the previously registered IVersionProviders services.TryAddScoped <IVersionProviderFactory, VersionProviderFactory>(); services.AddCloudscribeIdentity <SiteUser, SiteRole>() .AddDefaultTokenProviders(); // you can use either json or xml to maintain your navigation map we provide examples of each navigation.xml and // navigation.json in the root of this project // you can override the name of the file used with AppSettings:NavigationXmlFileName or AppSettings:NavigationJsonFileName in config.json // the file must live in the root of the web project code not in wwwroot // it is arguable which is easier for humans to read and maintain, myself I think for something like a navigation tree // that could get large xml is easier to work with and not make mistakes. in json one missing or extra comma can break it // granted xml can be broken by typos too but the end tags make it easier to keep track of where you are imho (JA) //services.TryAddScoped<INavigationTreeBuilder, JsonNavigationTreeBuilder>(); //services.TryAddScoped<INavigationTreeBuilder, HardCodedNavigationTreeBuilder>(); services.TryAddScoped <ITreeCache, MemoryTreeCache>(); services.AddScoped <INavigationTreeBuilder, XmlNavigationTreeBuilder>(); services.AddScoped <NavigationTreeBuilderService, NavigationTreeBuilderService>(); services.TryAddScoped <INodeUrlPrefixProvider, FolderTenantNodeUrlPrefixProvider>(); services.TryAddScoped <INavigationNodePermissionResolver, NavigationNodePermissionResolver>(); services.Configure <NavigationOptions>(configuration.GetSection("NavigationOptions")); services.TryAddTransient <IBuildPaginationLinks, PaginationLinkBuilder>(); //services.AddTransient<IEmailTemplateService, HardCodedEmailTemplateService>(); services.AddTransient <ISiteMessageEmailSender, SiteEmailMessageSender>(); services.AddTransient <ISmsSender, SiteSmsSender>(); services.TryAddSingleton <IThemeListBuilder, SiteThemeListBuilder>(); services.TryAddSingleton <IRazorViewEngine, CoreViewEngine>(); // cloudscribe.Core.Web.CoreViewEngine adds /Views/Sys as the last place to search for views // cloudscribe views are all under Views/Sys // to modify a view just copy it to a higher priority location // ie copy /Views/Sys/Manage/*.cshtml up to /Views/Manage/ and that one will have higher priority // and you can modify it however you like // upgrading to newer versions of cloudscribe could modify or add views below /Views/Sys // so you may need to compare your custom views to the originals again after upgrades // Add MVC services to the services container. services.AddMvc(options => { //options.Filters.Add(...); }) .AddViewLocalization(options => options.ResourcesPath = "AppResources") //.AddDataAnnotationsLocalization() //.AddXmlDataContractSerializerFormatters() .AddViewOptions(options => { }); services.Configure <RazorViewEngineOptions>(options => { options.ViewLocationExpanders.Add(new SiteViewLocationExpander()); }); //https://github.com/aspnet/Announcements/issues/71 // Configure the options for the authentication middleware. // You can add options for Google, Twitter and other middleware as shown below. // For more information see http://go.microsoft.com/fwlink/?LinkID=532715 // establish AppId and AppSecret here https://developers.facebook.com/apps // https://github.com/aspnet/Security/blob/dev/src/Microsoft.AspNet.Authentication.Facebook/FacebookAuthenticationOptions.cs //services.Configure<FacebookAuthenticationOptions>(options => //{ // // options here are only used if not specified in site settings // options.AppId = configuration["Authentication:Facebook:AppId"]; // options.AppSecret = configuration["Authentication:Facebook:AppSecret"]; // //options.AuthenticationScheme = AuthenticationScheme.External; //}); //// get clientid and secret here https://account.live.com/developers/applications/index //services.Configure<MicrosoftAccountAuthenticationOptions>(options => //{ // options.ClientId = configuration["Authentication:MicrosoftAccount:ClientId"]; // options.ClientSecret = configuration["Authentication:MicrosoftAccount:ClientSecret"]; //}); ////https://auth0.com/docs/connections/social/google //// get clientid and secret here https://console.developers.google.com/ //services.Configure<GoogleAuthenticationOptions>(options => //{ // options.ClientId = configuration["Authentication:Google:ClientId"]; // options.ClientSecret = configuration["Authentication:Google:ClientSecret"]; //}); //// get consumerkey and secret here https://apps.twitter.com/ //// unlike the other providers twitter does not allow creating localhost apps for testing //// but you can use an url shortener to mask the localhost urls //services.Configure<TwitterAuthenticationOptions>(options => //{ // options.ConsumerKey = configuration["Authentication:Twitter:ConsumerKey"]; // options.ConsumerSecret = configuration["Authentication:Twitter:ConsumerSecret"]; //}); return(services); }
// Configure is called after ConfigureServices is called. // you can change this method signature to include any dependencies that need to be injected into this method // you can see we added the dependency for IOptions<MultiTenantOptions> // so basically if you need any service in this method that was previously setup in ConfigureServices // you can just add it to the method signature and it will be provided by dependency injection public void Configure( IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IOptions <MultiTenantOptions> multiTenantOptions, IServiceProvider serviceProvider, ILogRepository logRepository) { // Configure the HTTP request pipeline. //http://blog.getglimpse.com/2015/11/19/installing-glimpse-v2-beta1/ bool enableGlimpse = Configuration.Get <bool>("DiagnosticOptions:EnableGlimpse", false); if (enableGlimpse) { app.UseGlimpse(); } // LogLevels //Debug = 1, //Trace = 2, //Information = 3, //Warning = 4, //Error = 5, //Critical = 6, // Add the console logger. loggerFactory.AddConsole(minLevel: LogLevel.Warning); // a customizable filter for logging LogLevel minimumLevel = LogLevel.Warning; List <string> excludedLoggers = new List <string>(); // add exclusions to remove noise in the logs // we need to filter out EF otherwise each time we persist a log item to the db more logs are generated // so it can become an infinite loop that keeps creating data // you can add any loggers that you want to exclude to reduce noise in the log excludedLoggers.Add("Microsoft.Data.Entity.Storage.Internal.RelationalCommandBuilderFactory"); excludedLoggers.Add("Microsoft.Data.Entity.Query.Internal.QueryCompiler"); excludedLoggers.Add("Microsoft.Data.Entity.DbContext"); Func <string, LogLevel, bool> logFilter = delegate(string loggerName, LogLevel logLevel) { if (logLevel < minimumLevel) { return(false); } if (excludedLoggers.Contains(loggerName)) { return(false); } return(true); }; // Add cloudscribe db logging loggerFactory.AddDbLogger(serviceProvider, logRepository, logFilter); //app.UseCultureReplacer(); // localization from .resx files is not really working in beta8 // will have to wait till next release var supportedCultures = new[] { new CultureInfo("en-US"), new CultureInfo("it"), new CultureInfo("fr-FR") }; var locOptions = new RequestLocalizationOptions { // You must explicitly state which cultures your application supports. // These are the cultures the app supports for formatting numbers, dates, etc. SupportedCultures = supportedCultures, SupportedUICultures = supportedCultures }; // You can change which providers are configured to determine the culture for requests, or even add a custom // provider with your own logic. The providers will be asked in order to provide a culture for each request, // and the first to provide a non-null result that is in the configured supported cultures list will be used. // By default, the following built-in providers are configured: // - QueryStringRequestCultureProvider, sets culture via "culture" and "ui-culture" query string values, useful for testing // - CookieRequestCultureProvider, sets culture via "ASPNET_CULTURE" cookie // - AcceptLanguageHeaderRequestCultureProvider, sets culture via the "Accept-Language" request header //locOptions.RequestCultureProviders.Insert(0, new CustomRequestCultureProvider(async context => //{ // // My custom request culture logic // return new ProviderCultureResult("en"); //})); //app.UseRequestLocalization(locOptions, // defaultRequestCulture: new RequestCulture(culture: "en-US", uiCulture: "en-US")); // Add the following to the request pipeline only in development environment. if (env.IsEnvironment("Development")) { //app.UseBrowserLink(); app.UseDeveloperExceptionPage(); //app.UseDatabaseErrorPage(DatabaseErrorPageOptions.ShowAll); //app.UseStatusCodePagesWithReExecute("/error/{0}"); //app.UseStatusCodePagesWithReExecute("/error/{0}"); } else { app.UseExceptionHandler("/Home/Error"); // handle 404 and other non success //app.UseStatusCodePages(); // app.UseStatusCodePages(context => context.HttpContext.Response.SendAsync("Handler, status code: " + context.HttpContext.Response.StatusCode, "text/plain")); // app.UseStatusCodePages("text/plain", "Response, status code: {0}"); // app.UseStatusCodePagesWithRedirects("~/errors/{0}"); // PathBase relative // app.UseStatusCodePagesWithRedirects("/base/errors/{0}"); // Absolute // app.UseStatusCodePages(builder => builder.UseWelcomePage()); //app.UseStatusCodePagesWithReExecute("/errors/{0}"); //app.UseStatusCodePagesWithReExecute("/error/{0}"); } // Add the platform handler to the request pipeline. //app.UseIISPlatformHandler(); app.UseIISPlatformHandler(options => options.AuthenticationDescriptions.Clear()); //app.UseRuntimeInfoPage("/info"); // Add static files to the request pipeline. app.UseStaticFiles(); // the only thing we are using session for is Alerts app.UseSession(); //app.UseInMemorySession(configure: s => s.IdleTimeout = TimeSpan.FromMinutes(20)); app.UseMultitenancy <SiteSettings>(); // this is in Startup.CloudscribeCore.cs app.UseCloudscribeCore(multiTenantOptions, Configuration); // it is very important that all authentication configuration be set before configuring mvc // ie if app.UseFacebookAuthentication(); was below app.UseMvc the facebook login button will not be shown // Add MVC to the request pipeline. app.UseMvc(routes => { // Understanding ASP.NET Routing: // it is very important that routes are registered in the correct order. more specific routes must be registered first and // less specific routes must be registered later. a request may match more than one route. // When a request comes in it is compared to routes in the route table and the first route it matches is used no matter if a // better match exists. therefore if a less specific route is registered first it will catch requests that would have a better // match with a more specific route that was registered later. // ie the default route is usually the least specific route and must be registered last // something like a route for a cms would likely need to be the default route added last especially if you are not going to use // a controller segment in the route because without a controller segment the route is less specific // default route for folder sites must be second to last if (multiTenantOptions.Value.Mode == MultiTenantMode.FolderName) { routes.MapRoute( name: "folderdefault", template: "{sitefolder}/{controller}/{action}/{id?}", defaults: new { controller = "Home", action = "Index" }, constraints: new { name = new SiteFolderRouteConstraint() } ); } // the default route has to be added last routes.MapRoute( name: "default", template: "{controller}/{action}/{id?}", defaults: new { controller = "Home", action = "Index" } ); // Uncomment the following line to add a route for porting Web API 2 controllers. // routes.MapWebApiRoute("DefaultApi", "api/{controller}/{id?}"); }) ; // https://github.com/aspnet/Announcements/issues/54 // if you want to run the IIS pipeline for requests not handled // ie you won't see the IIS 404 page without this. // if nothing else handles the 404 then you get a blank white page in the browser //app.RunIISPipeline(); //app.Run(context => //{ // context.Response.StatusCode = 404; // return Task.FromResult(0); //}); DevOptions devOptions = Configuration.Get <DevOptions>("DevOptions"); if (devOptions.DbPlatform == "ef7") { cloudscribe.Core.Repositories.EF.InitialData.InitializeDatabaseAsync(app.ApplicationServices).Wait(); // this is using EF for the logger but using EF for Core does not mean you must use EF for logging // one should be able to use the MSSQL Logger while still using EF for the core repos // one problem with EF logging is that EF logs a lot of information stuff and if we use EF for logigng // then every time a log item is inserted to the db it generates more logging events // and thus a continuous creation of data can result so the EF logger is designed to leave out // EF components from logging // by using the mssql logger instead then no extra log items will be created and you can more easily allow // EF to log things of its own // however the mssql logger depends on the setup system which is not used by EF components // this dependency is more practical than technical though, you could run the db setup script for mssql logging // manually instead of using the setup system. cloudscribe.Logging.EF.DbInitializer.InitializeDatabaseAsync(app.ApplicationServices).Wait(); } }