From b41e264e1e2ed69e6d089e1f338b9c3dd36881b8 Mon Sep 17 00:00:00 2001 From: Steven Giesel Date: Thu, 16 Sep 2021 20:36:12 +0200 Subject: [PATCH] Storage in AppConfiguration instead of backed in --- .../StorageProviderExtensionsTests.cs | 46 +++++++++++++++++ .../StorageProviderExtensions.cs | 31 ++++++++++++ LinkDotNet.Blog.Web/Startup.cs | 13 +---- LinkDotNet.Blog.Web/appsettings.json | 3 +- .../Persistence/PersistenceProvider.cs | 17 +++++++ Readme.md | 49 ++++++++++--------- 6 files changed, 123 insertions(+), 36 deletions(-) create mode 100644 LinkDotNet.Blog.IntegrationTests/Web/RegistrationExtensions/StorageProviderExtensionsTests.cs create mode 100644 LinkDotNet.Blog.Web/RegistrationExtensions/StorageProviderExtensions.cs create mode 100644 LinkDotNet.Infrastructure/Persistence/PersistenceProvider.cs diff --git a/LinkDotNet.Blog.IntegrationTests/Web/RegistrationExtensions/StorageProviderExtensionsTests.cs b/LinkDotNet.Blog.IntegrationTests/Web/RegistrationExtensions/StorageProviderExtensionsTests.cs new file mode 100644 index 00000000..d7502f43 --- /dev/null +++ b/LinkDotNet.Blog.IntegrationTests/Web/RegistrationExtensions/StorageProviderExtensionsTests.cs @@ -0,0 +1,46 @@ +using System; +using System.Linq; +using FluentAssertions; +using LinkDotNet.Blog.Web.RegistrationExtensions; +using LinkDotNet.Infrastructure.Persistence; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Moq; +using Xunit; + +namespace LinkDotNet.Blog.IntegrationTests.Web.RegistrationExtensions +{ + public class StorageProviderExtensionsTests + { + [Theory] + [InlineData("SqlServer")] + [InlineData("SqliteServer")] + [InlineData("RavenDb")] + [InlineData("InMemory")] + public void ShouldRegisterPersistenceProvider(string persistenceKey) + { + var collection = new ServiceCollection(); + var config = new Mock(); + config.Setup(c => c["PersistenceProvider"]) + .Returns(persistenceKey); + + collection.AddStorageProvider(config.Object); + + var enumerable = collection.Select(c => c.ServiceType).ToList(); + enumerable.Should().Contain(typeof(IRepository<>)); + } + + [Fact] + public void ShouldThrowExceptionWhenNotKnown() + { + var collection = new ServiceCollection(); + var config = new Mock(); + config.Setup(c => c["PersistenceProvider"]) + .Returns("not known"); + + Action act = () => collection.AddStorageProvider(config.Object); + + act.Should().Throw(); + } + } +} \ No newline at end of file diff --git a/LinkDotNet.Blog.Web/RegistrationExtensions/StorageProviderExtensions.cs b/LinkDotNet.Blog.Web/RegistrationExtensions/StorageProviderExtensions.cs new file mode 100644 index 00000000..f947bbc7 --- /dev/null +++ b/LinkDotNet.Blog.Web/RegistrationExtensions/StorageProviderExtensions.cs @@ -0,0 +1,31 @@ +using LinkDotNet.Infrastructure.Persistence; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +namespace LinkDotNet.Blog.Web.RegistrationExtensions +{ + public static class StorageProviderExtensions + { + public static void AddStorageProvider(this IServiceCollection services, IConfiguration configuration) + { + var persistenceProvider = PersistenceProvider.Create(configuration["PersistenceProvider"]); + + if (persistenceProvider == PersistenceProvider.InMemory) + { + services.UseInMemoryAsStorageProvider(); + } + else if (persistenceProvider == PersistenceProvider.RavenDb) + { + services.UseRavenDbAsStorageProvider(); + } + else if (persistenceProvider == PersistenceProvider.SqliteServer) + { + services.UseSqliteAsStorageProvider(); + } + else if (persistenceProvider == PersistenceProvider.SqlServer) + { + services.UseSqlAsStorageProvider(); + } + } + } +} \ No newline at end of file diff --git a/LinkDotNet.Blog.Web/Startup.cs b/LinkDotNet.Blog.Web/Startup.cs index c3f85fe3..a7f8e390 100644 --- a/LinkDotNet.Blog.Web/Startup.cs +++ b/LinkDotNet.Blog.Web/Startup.cs @@ -29,17 +29,8 @@ public void ConfigureServices(IServiceCollection services) { services.AddRazorPages(); services.AddServerSideBlazor(); - services.AddSingleton(service => - AppConfigurationFactory.Create(service.GetService())); - - // This can be extended to use other repositories - services.UseSqlAsStorageProvider(); - /**************** - * Possible Storage Providers: - * services.UseSqliteAsStorageProvider(); - * services.UseRavenDbAsStorageProvider(); - * services.UseInMemoryAsStorageProvider(); - */ + services.AddSingleton(_ => AppConfigurationFactory.Create(Configuration)); + services.AddStorageProvider(Configuration); // Here you can setup up your identity provider if (environment.IsDevelopment()) diff --git a/LinkDotNet.Blog.Web/appsettings.json b/LinkDotNet.Blog.Web/appsettings.json index 5f06a70c..76c6af78 100644 --- a/LinkDotNet.Blog.Web/appsettings.json +++ b/LinkDotNet.Blog.Web/appsettings.json @@ -15,6 +15,7 @@ "BackgroundUrl": "assets/profile-background.webp", "ProfilePictureUrl": "assets/profile-picture.webp" }, + "PersistenceProvider": "SqlServer", "ConnectionString": "", "DatabaseName": "", "Auth0": { @@ -29,4 +30,4 @@ "Heading": "Software Engineer", "ProfilePictureUrl": "assets/profile-picture.webp" } -} +} \ No newline at end of file diff --git a/LinkDotNet.Infrastructure/Persistence/PersistenceProvider.cs b/LinkDotNet.Infrastructure/Persistence/PersistenceProvider.cs new file mode 100644 index 00000000..b99e193d --- /dev/null +++ b/LinkDotNet.Infrastructure/Persistence/PersistenceProvider.cs @@ -0,0 +1,17 @@ +using LinkDotNet.Domain; + +namespace LinkDotNet.Infrastructure.Persistence +{ + public class PersistenceProvider : Enumeration + { + public static readonly PersistenceProvider SqlServer = new(nameof(SqlServer)); + public static readonly PersistenceProvider SqliteServer = new(nameof(SqliteServer)); + public static readonly PersistenceProvider RavenDb = new(nameof(RavenDb)); + public static readonly PersistenceProvider InMemory = new(nameof(InMemory)); + + protected PersistenceProvider(string key) + : base(key) + { + } + } +} \ No newline at end of file diff --git a/Readme.md b/Readme.md index 02d7f8ab..94afcb6f 100644 --- a/Readme.md +++ b/Readme.md @@ -22,7 +22,6 @@ The appsettings.json file has a lot of options to customize the content of the b ```json { - ... "BlogName": "linkdotnet", "GithubAccountUrl": "", "LinkedInAccountUrl": "", @@ -31,6 +30,7 @@ The appsettings.json file has a lot of options to customize the content of the b "BackgroundUrl": "assets/profile-background.webp", "ProfilePictureUrl": "assets/profile-picture.webp" }, + "PersistenceProvider": "SqlServer", "ConnectionString": "", "DatabaseName": "", "Auth0": { @@ -49,33 +49,34 @@ The appsettings.json file has a lot of options to customize the content of the b ``` -| Property | Type | Description | -| ------------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | -| BlogName | string | Name of your blog. Is used in the navbar and is used as the title of the page. | -| GithubAccountUrl | string | Url to your github account. If not set the navigation link is not shown | -| LinkedInAccountUrl | string | Url to your LinkedIn account. If not set the navigation link is not shown | -| Introduction | | Is used for the introduction part of the blog | -| Description | MarkdownString | Small introduction text for yourself. This is also used for `` tag. For this the markup will be converted to plain text. | -| BackgroundUrl | string | Url or path to the background image | -| ProfilePictureUrl | string | Url or path to your profile picture | -| ConnectionString | string | Is used for connection to a database. Not used when `InMemoryStorageProvider` is used | -| DatabaseName | string | Name of the database. Only used with `RavenDbStorageProvider` | -| Auth0 | | Configuration for setting up Auth0 | -| Domain | string | See more details here: https://manage.auth0.com/dashboard/ | -| ClientId | string | See more details here: https://manage.auth0.com/dashboard/ | -| ClientSecret | string | See more details here: https://manage.auth0.com/dashboard/ | -| BlogPostsPerPage | int | Gives the amount of blog posts loaded and display per page. For more the user has to use the navigation | -| IsAboutMeEnabled | bool | If true, enalbes the "About Me" page | -| AboutMeProfileInformation | node | If `IsAboutMeEnabled` is set to `false` this node can be left empty. | -| Name | string | Name, which is displayed on top of the profile card | -| Heading | string | Displayed under the name. For example job title | -| ProfilePictureUrl | string | Displayed profile picture | +| Property | Type | Description | +| ------------------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | +| BlogName | string | Name of your blog. Is used in the navbar and is used as the title of the page. | +| GithubAccountUrl | string | Url to your github account. If not set the navigation link is not shown | +| LinkedInAccountUrl | string | Url to your LinkedIn account. If not set the navigation link is not shown | +| Introduction | | Is used for the introduction part of the blog | +| Description | MarkdownString | Small introduction text for yourself. This is also used for `` tag. For this the markup will be converted to plain text. | +| BackgroundUrl | string | Url or path to the background image | +| ProfilePictureUrl | string | Url or path to your profile picture | +| PersistenceProvider | string | Declares the type of the storage provider (one of the following: `SqlServer`, `SqliteServer`, `RavenDb`, `InMemory`). More in-depth explanation down below | +| ConnectionString | string | Is used for connection to a database. Not used when `InMemoryStorageProvider` is used | +| DatabaseName | string | Name of the database. Only used with `RavenDbStorageProvider` | +| Auth0 | | Configuration for setting up Auth0 | +| Domain | string | See more details here: https://manage.auth0.com/dashboard/ | +| ClientId | string | See more details here: https://manage.auth0.com/dashboard/ | +| ClientSecret | string | See more details here: https://manage.auth0.com/dashboard/ | +| BlogPostsPerPage | int | Gives the amount of blog posts loaded and display per page. For more the user has to use the navigation | +| IsAboutMeEnabled | bool | If true, enalbes the "About Me" page | +| AboutMeProfileInformation | node | If `IsAboutMeEnabled` is set to `false` this node can be left empty. | +| Name | string | Name, which is displayed on top of the profile card | +| Heading | string | Displayed under the name. For example job title | +| ProfilePictureUrl | string | Displayed profile picture | The usage might shift directly into the extension methods, where they are used. ## Storage Provider Currently there are 4 Storage-Provider: - * InMemory - Basically a list holding your data (per request) + * InMemory - Basically a list holding your data (per request). If the User hits a hard reload, the data is gone. * RavenDb - As the name suggests for RavenDb * Sqlite - Based on EF Core, so it can be easily adapted for other Sql Dialects * SqlServer - Based on EF Core, so it can be easily adapted for other Sql Dialects @@ -120,4 +121,4 @@ Furthermore the following tags are set: | Tag | Index | Display Blog Post | | ---------------------------------------- | ------------------------------------ | ----------------------------- | | Title of the web page | Defined in AppConfiguration.BlogName | Title of the blogpost | -| <meta name="keyword" content="" /> | not set | Tags defined in the Blog Post | +| <meta name="keyword" content="" /> | not set | Tags defined in the Blog Post | \ No newline at end of file