From e0a8bc0e2c051e9b3ff79a6e3897bc0a890e6e2c Mon Sep 17 00:00:00 2001 From: "David G. Moore, Jr." <dev@dgmjr.io> Date: Tue, 20 Feb 2024 19:00:39 -0500 Subject: [PATCH] Refactor project structure and update target frameworks - Introduced `ActiveUsers` feature in `Blazor` with classes and interfaces to manage user states. - Removed obsolete `Directory.Build.targets.no` and added `Directory.Build.targets` targeting `DgmjrSdk`. - Updated `Dgmjr.AspNetCore.csproj` to correct the property name for multi-targeting frameworks. - Standardized time zone notation across all `LICENSE.md` files and extended copyright to 2024. - Added `.vscode` configuration files to aid in debugging and task management for `Http` project. - Cleaned up and commented out unused package references in various `.csproj` files. - Removed redundant `Dgmjr.AspNetCore.Mvc.sln` as part of solution consolidation. - Streamlined MVC framework extension methods and improved logging with expanded `LoggerExtensions`. - Consolidated license and metadata information across various component licenses. The restructuring streamlines project configurations and prepares for the integration of new features while ensuring consistency in licensing metadata and smoothing out development workflows with the provision of editor configurations. The addition of the `ActiveUser` functionality paves the way for improved user state management in Blazor applications, reinforcing the ecosystem's capabilities for real-time interactivity. --- Directory.Build.targets | 20 +++++ Directory.Build.targets.no | 20 ----- src/All/Dgmjr.AspNetCore.csproj | 2 +- src/All/LICENSE.md | 28 +++---- src/All/icon.png | Bin 0 -> 26997 bytes src/Blazor.ActiveUsers/ConnectedUser.cs | 27 +++++++ .../ConnectedUsersAutoConfigurator.cs | 16 ++++ src/Blazor.ActiveUsers/ConnectedUsersList.cs | 25 +++++++ .../Dgmjr.Blazor.ActiveUsers.csproj | 19 +++++ src/Blazor.ActiveUsers/IActiveUsersList.cs | 12 +++ src/Blazor.ActiveUsers/LICENSE.md | 35 +++++++++ src/Blazor.ActiveUsers/icon.png | Bin 0 -> 26997 bytes .../Dgmjr.Blazor.EntityFrameworkCore.csproj | 8 ++ src/Formatters/LICENSE.md | 26 +++---- src/Hosting.Extensions/LICENSE.md | 28 +++---- src/Http/.vscode/launch.json | 35 +++++++++ src/Http/.vscode/tasks.json | 41 ++++++++++ .../Extensions/Dgmjr.Http.Extensions.csproj | 2 +- src/Mvc/Dgmjr.AspNetCore.Mvc.csproj | 19 +++-- src/Mvc/Dgmjr.AspNetCore.Mvc.sln | 70 ------------------ src/Mvc/LoggerExtensions.cs | 30 ++++++-- src/Mvc/MvcAutoConfigurator.cs | 5 +- src/Mvc/MvcOptions.cs | 2 + .../ConflictProblemDetailsExample.cs | 3 +- src/Mvc/ServiceNames.cs | 4 +- src/Mvc/TypeNameAndAssemblyConfigurator.cs | 56 ++++++++++---- src/Security/Authorization/LICENSE.md | 28 +++---- src/Security/Security/LICENSE.md | 28 +++---- 28 files changed, 398 insertions(+), 191 deletions(-) create mode 100755 Directory.Build.targets delete mode 100755 Directory.Build.targets.no create mode 100644 src/All/icon.png create mode 100644 src/Blazor.ActiveUsers/ConnectedUser.cs create mode 100644 src/Blazor.ActiveUsers/ConnectedUsersAutoConfigurator.cs create mode 100644 src/Blazor.ActiveUsers/ConnectedUsersList.cs create mode 100644 src/Blazor.ActiveUsers/Dgmjr.Blazor.ActiveUsers.csproj create mode 100644 src/Blazor.ActiveUsers/IActiveUsersList.cs create mode 100644 src/Blazor.ActiveUsers/LICENSE.md create mode 100644 src/Blazor.ActiveUsers/icon.png create mode 100644 src/Blazor.EfCore/Dgmjr.Blazor.EntityFrameworkCore.csproj create mode 100644 src/Http/.vscode/launch.json create mode 100644 src/Http/.vscode/tasks.json delete mode 100644 src/Mvc/Dgmjr.AspNetCore.Mvc.sln diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100755 index 00000000..6a774cf6 --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,20 @@ +<!-- + * Directory.Build.targets + * + * Created: 2023-01-11-05:08:45 + * Modified: 2023-01-11-11:47:51 + * + * Author: David G. Moore, Jr, <david@dgmjr.io> + * + * Copyright © 2022-2023 David G. Moore, Jr,, All Rights Reserved + * License: MIT (https://opensource.org/licenses/MIT) +--> + +<Project> + <Import Project="Sdk.targets" Sdk="DgmjrSdk" Condition="'$(DgmjrSdkTargets)' == ''" /> + <PropertyGroup> + <DgmjrSdkTargets>$(MSBuildThisFileDirectory)Sdk.targets</DgmjrSdkTargets> + <!-- <InheritedDirectoryBuildTargets>$([MSBuild]::GetPathOfFileAbove('Directory.Build.targets', '$(MSBuildThisFileDirectory)../'))</InheritedDirectoryBuildTargets> --> + </PropertyGroup> + <!-- <Import Project="$(InheritedDirectoryBuildTargets)" Condition="Exists('$(InheritedDirectoryBuildTargets)')" /> --> +</Project> diff --git a/Directory.Build.targets.no b/Directory.Build.targets.no deleted file mode 100755 index 4e6d4c7b..00000000 --- a/Directory.Build.targets.no +++ /dev/null @@ -1,20 +0,0 @@ -<!-- - * Directory.Build.targets - * - * Created: 2023-01-11-05:08:45 - * Modified: 2023-01-11-11:47:51 - * - * Author: David G. Moore, Jr, <david@dgmjr.io> - * - * Copyright © 2022-2023 David G. Moore, Jr,, All Rights Reserved - * License: MIT (https://opensource.org/licenses/MIT) ---> - -<Project> - <Import Project="Sdk.targets" Condition="Exists('Sdk.targets')" Sdk="JustinWritesCodeSdk" Condition="'$(JustinWritesCodeSdkTargets)' == ''" /> - <PropertyGroup> - <JustinWritesCodeSdkTargets>$(MSBuildThisFileDirectory)Sdk.targets</JustinWritesCodeSdkTargets> - <InheritedDirectoryBuildTargets>$([MSBuild]::GetPathOfFileAbove('Directory.Build.targets', '$(MSBuildThisFileDirectory)../'))</InheritedDirectoryBuildTargets> - </PropertyGroup> - <Import Project="$(InheritedDirectoryBuildTargets)" Condition="Exists('$(InheritedDirectoryBuildTargets)')" /> -</Project> diff --git a/src/All/Dgmjr.AspNetCore.csproj b/src/All/Dgmjr.AspNetCore.csproj index 4abfc686..e3bf91a7 100644 --- a/src/All/Dgmjr.AspNetCore.csproj +++ b/src/All/Dgmjr.AspNetCore.csproj @@ -12,7 +12,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>netstandard2.0;netstandard2.1;net6.0;net8.0</TargetFramework> + <TargetFrameworks>netstandard2.0;netstandard2.1;net6.0;net8.0</TargetFrameworks> <Description>This is a metapackage of all of the ASP.NET Core Dgmjr packages</Description> </PropertyGroup> <ItemGroup> diff --git a/src/All/LICENSE.md b/src/All/LICENSE.md index 4f608744..4f592f86 100755 --- a/src/All/LICENSE.md +++ b/src/All/LICENSE.md @@ -1,22 +1,22 @@ --- -date: 2023-07-13T05:44:46:00.048Z +date: 2023-07-13T05:44:46:00-05:00Z description: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files, yadda, yadda, yadda... keywords: - - IP - - copyright - - license - - mit +- IP +- copyright +- license +- mit permissions: - - commercial-use - - modifications - - distribution - - private-use +- commercial-use +- modifications +- distribution +- private-use conditions: - - include-copyright +- include-copyright limitations: - - liability - - warranty -lastmod: 2023-08-29T17:13:51:00.216Z +- liability +- warranty +lastmod: 2024-01-0T00:39:00.0000+05:00Z license: MIT slug: mit-license title: MIT License @@ -25,7 +25,7 @@ type: license # MIT License -## Copyright © 2022-2023 [David G. Moore, Jr.](mailto:david@dgmjr.io "Send David an email") ([@dgmjr](https://github.com/dgmjr "Contact david on GitHub")), All Rights Reserved +## Copyright © 2022-2024 [David G. Moore, Jr.](mailto:david@dgmjr.io "Send Dr. Moore") ([@dgmjr](https://github.com/dgmjr "Contact Dr. Moore on GitHub")), All Rights Reserved Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/src/All/icon.png b/src/All/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..db07a039193d57c5147e651a7ab732121bfd20ba GIT binary patch literal 26997 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%0D}P5 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 CAey28 literal 0 HcmV?d00001 diff --git a/src/Blazor.ActiveUsers/ConnectedUser.cs b/src/Blazor.ActiveUsers/ConnectedUser.cs new file mode 100644 index 00000000..38c03ace --- /dev/null +++ b/src/Blazor.ActiveUsers/ConnectedUser.cs @@ -0,0 +1,27 @@ +namespace Dgmjr.Blazor.ActiveUsers; +using System.Security.Claims; +using Microsoft.Identity.Web; + +public record class ActiveUser : IDisposable +{ + public ActiveUser(ClaimsPrincipal? User = null, ActiveUsersList? ActiveUsersList = null) + { + this.User = User; + this.ActiveUsersList = ActiveUsersList; + ActiveUsersList?.Add(this); + } + + public ClaimsPrincipal? User { get; } + public ActiveUsersList? ActiveUsersList { get; } + + public string UserId => User?.GetObjectId() ?? "Unknown"; + public string? Name => User?.GetName(); + public string? Username => User?.GetUsername(); + public string? Email => User?.GetEmail(); + public string? PhoneNumber => User?.GetPhoneNumber(); + + public void Dispose() + { + ActiveUsersList?.Remove(this); + } +} diff --git a/src/Blazor.ActiveUsers/ConnectedUsersAutoConfigurator.cs b/src/Blazor.ActiveUsers/ConnectedUsersAutoConfigurator.cs new file mode 100644 index 00000000..3c70641e --- /dev/null +++ b/src/Blazor.ActiveUsers/ConnectedUsersAutoConfigurator.cs @@ -0,0 +1,16 @@ +namespace Dgmjr.Blazor.ActiveUsers; + +using Microsoft.AspNetCore.Builder; +using System.Security.Claims; +using Microsoft.Extensions.DependencyInjection; + +public class ActiveUsersAutoConfigurator : IConfigureIHostApplicationBuilder +{ + public ConfigurationOrder Order => ConfigurationOrder.AnyTime; + + public void Configure(WebApplicationBuilder builder) + { + builder.Services.AddScoped<ActiveUser>(); + builder.Services.AddSingleton<IActiveUsersList, ActiveUsersList>(); + } +} diff --git a/src/Blazor.ActiveUsers/ConnectedUsersList.cs b/src/Blazor.ActiveUsers/ConnectedUsersList.cs new file mode 100644 index 00000000..ad90d46d --- /dev/null +++ b/src/Blazor.ActiveUsers/ConnectedUsersList.cs @@ -0,0 +1,25 @@ +namespace Dgmjr.Blazor.ActiveUsers; + +using System.Collections; +using System.Collections.Concurrent; +using System.Threading.Tasks.Sources; +using System.Collections.Generic; + +public class ActiveUsersList : ConcurrentDictionary<string, ActiveUser>, IActiveUsersList, IDictionary<string, ActiveUser>, ICollection<ActiveUser> +{ + public virtual bool IsReadOnly => false; + + public virtual bool Remove(ActiveUser user) => TryRemove(user.UserId, out _); + public new virtual ActiveUser[] ToArray() => Values.ToArray(); + public virtual void CopyTo(ActiveUser[] array, int index) => Values.CopyTo(array, index); + + public virtual void Add(ActiveUser user) => TryAdd(user.UserId, user); + + public virtual bool Contains(ActiveUser user) => Contains(user.UserId); + + public virtual bool Contains(guid userId) => Contains(userId.ToString()); + + public virtual bool Contains(string userId) => base.ContainsKey(userId); + + IEnumerator<ActiveUser> IEnumerable<ActiveUser>.GetEnumerator() => Values.GetEnumerator(); +} diff --git a/src/Blazor.ActiveUsers/Dgmjr.Blazor.ActiveUsers.csproj b/src/Blazor.ActiveUsers/Dgmjr.Blazor.ActiveUsers.csproj new file mode 100644 index 00000000..6c268c36 --- /dev/null +++ b/src/Blazor.ActiveUsers/Dgmjr.Blazor.ActiveUsers.csproj @@ -0,0 +1,19 @@ +<Project Sdk="Microsoft.NET.Sdk.Razor"> + <PropertyGroup> + <TargetFramework>net8.0</TargetFramework> + <TargetFrameworks>net8.0</TargetFrameworks> + </PropertyGroup> + <ItemGroup> + <FrameworkReference Include="Microsoft.AspNetCore.App" /> + </ItemGroup> + <ItemGroup> + <PackageReference Include="Microsoft.EntityFrameworkCore.Usings" /> + <PackageReference Include="Microsoft.Identity.Web" /> + <PackageReference Include="Dgmjr.Identity.Claims" /> + <PackageReference Include="Dgmjr.Configuration.Extensions" /> + </ItemGroup> + <ItemGroup> + <PackageFile Include="./icon.png" PackagePath="icon.png" /> + <PackageFile Include="./bin/$(Configuration)/$(TargetFramework)/**/*.dll" PackagePath="lib/$(TargetFramework)/%(Filename)%(Extension)" /> + </ItemGroup> +</Project> diff --git a/src/Blazor.ActiveUsers/IActiveUsersList.cs b/src/Blazor.ActiveUsers/IActiveUsersList.cs new file mode 100644 index 00000000..3055af89 --- /dev/null +++ b/src/Blazor.ActiveUsers/IActiveUsersList.cs @@ -0,0 +1,12 @@ +namespace Dgmjr.Blazor.ActiveUsers; +using System.Collections.Generic; + +public interface IActiveUsersList +{ + void Add(ActiveUser user); + ActiveUser[] ToArray(); + bool Remove(ActiveUser user); + bool Contains(ActiveUser user); + bool Contains(guid userId); + int Count { get; } +} diff --git a/src/Blazor.ActiveUsers/LICENSE.md b/src/Blazor.ActiveUsers/LICENSE.md new file mode 100644 index 00000000..4f592f86 --- /dev/null +++ b/src/Blazor.ActiveUsers/LICENSE.md @@ -0,0 +1,35 @@ +--- +date: 2023-07-13T05:44:46:00-05:00Z +description: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files, yadda, yadda, yadda... +keywords: +- IP +- copyright +- license +- mit +permissions: +- commercial-use +- modifications +- distribution +- private-use +conditions: +- include-copyright +limitations: +- liability +- warranty +lastmod: 2024-01-0T00:39:00.0000+05:00Z +license: MIT +slug: mit-license +title: MIT License +type: license +--- + +# MIT License + +## Copyright © 2022-2024 [David G. Moore, Jr.](mailto:david@dgmjr.io "Send Dr. Moore") ([@dgmjr](https://github.com/dgmjr "Contact Dr. Moore on GitHub")), All Rights Reserved + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/src/Blazor.ActiveUsers/icon.png b/src/Blazor.ActiveUsers/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..db07a039193d57c5147e651a7ab732121bfd20ba GIT binary patch literal 26997 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%0D}P5 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 CAey28 literal 0 HcmV?d00001 diff --git a/src/Blazor.EfCore/Dgmjr.Blazor.EntityFrameworkCore.csproj b/src/Blazor.EfCore/Dgmjr.Blazor.EntityFrameworkCore.csproj new file mode 100644 index 00000000..27de846c --- /dev/null +++ b/src/Blazor.EfCore/Dgmjr.Blazor.EntityFrameworkCore.csproj @@ -0,0 +1,8 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <TargetFramework>net8.0</TargetFramework> + </PropertyGroup> + <ItemGroup> + <PackageReference Include="Microsoft.EntityFrameworkCore.Usings" /> + </ItemGroup> +</Project> diff --git a/src/Formatters/LICENSE.md b/src/Formatters/LICENSE.md index c80a6760..4f592f86 100755 --- a/src/Formatters/LICENSE.md +++ b/src/Formatters/LICENSE.md @@ -1,21 +1,21 @@ --- -date: 2023-07-13T05:44:46:00+05:00Z +date: 2023-07-13T05:44:46:00-05:00Z description: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files, yadda, yadda, yadda... keywords: - - IP - - copyright - - license - - mit +- IP +- copyright +- license +- mit permissions: - - commercial-use - - modifications - - distribution - - private-use +- commercial-use +- modifications +- distribution +- private-use conditions: - - include-copyright +- include-copyright limitations: - - liability - - warranty +- liability +- warranty lastmod: 2024-01-0T00:39:00.0000+05:00Z license: MIT slug: mit-license @@ -25,7 +25,7 @@ type: license # MIT License -## Copyright © 2022-2023 [David G. Moore, Jr.](mailto:david@dgmjr.io "Send Dr. Moore an email") ([@dgmjr](https://github.com/dgmjr "Contact Dr. Moore on GitHub")), All Rights Reserved +## Copyright © 2022-2024 [David G. Moore, Jr.](mailto:david@dgmjr.io "Send Dr. Moore") ([@dgmjr](https://github.com/dgmjr "Contact Dr. Moore on GitHub")), All Rights Reserved Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/src/Hosting.Extensions/LICENSE.md b/src/Hosting.Extensions/LICENSE.md index 4f608744..4f592f86 100755 --- a/src/Hosting.Extensions/LICENSE.md +++ b/src/Hosting.Extensions/LICENSE.md @@ -1,22 +1,22 @@ --- -date: 2023-07-13T05:44:46:00.048Z +date: 2023-07-13T05:44:46:00-05:00Z description: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files, yadda, yadda, yadda... keywords: - - IP - - copyright - - license - - mit +- IP +- copyright +- license +- mit permissions: - - commercial-use - - modifications - - distribution - - private-use +- commercial-use +- modifications +- distribution +- private-use conditions: - - include-copyright +- include-copyright limitations: - - liability - - warranty -lastmod: 2023-08-29T17:13:51:00.216Z +- liability +- warranty +lastmod: 2024-01-0T00:39:00.0000+05:00Z license: MIT slug: mit-license title: MIT License @@ -25,7 +25,7 @@ type: license # MIT License -## Copyright © 2022-2023 [David G. Moore, Jr.](mailto:david@dgmjr.io "Send David an email") ([@dgmjr](https://github.com/dgmjr "Contact david on GitHub")), All Rights Reserved +## Copyright © 2022-2024 [David G. Moore, Jr.](mailto:david@dgmjr.io "Send Dr. Moore") ([@dgmjr](https://github.com/dgmjr "Contact Dr. Moore on GitHub")), All Rights Reserved Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/src/Http/.vscode/launch.json b/src/Http/.vscode/launch.json new file mode 100644 index 00000000..32276328 --- /dev/null +++ b/src/Http/.vscode/launch.json @@ -0,0 +1,35 @@ +{ + "version": "0.2.0", + "configurations": [ + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/dotnet/vscode-csharp/blob/main/debugger-launchjson.md. + "name": ".NET Core Launch (web)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/CorrelationId/samples/3.1/MvcSample/bin/Local/netcoreapp3.1/MvcSample.dll", + "args": [], + "cwd": "${workspaceFolder}/CorrelationId/samples/3.1/MvcSample", + "stopAtEntry": false, + // Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser + "serverReadyAction": { + "action": "openExternally", + "pattern": "\\bNow listening on:\\s+(https?://\\S+)" + }, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} \ No newline at end of file diff --git a/src/Http/.vscode/tasks.json b/src/Http/.vscode/tasks.json new file mode 100644 index 00000000..2632cd29 --- /dev/null +++ b/src/Http/.vscode/tasks.json @@ -0,0 +1,41 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/CorrelationId/samples/3.1/MvcSample/MvcSample.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary;ForceNoAlign" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/CorrelationId/samples/3.1/MvcSample/MvcSample.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary;ForceNoAlign" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/CorrelationId/samples/3.1/MvcSample/MvcSample.csproj" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/src/Http/Extensions/Dgmjr.Http.Extensions.csproj b/src/Http/Extensions/Dgmjr.Http.Extensions.csproj index f3e1d0f1..76a116e2 100644 --- a/src/Http/Extensions/Dgmjr.Http.Extensions.csproj +++ b/src/Http/Extensions/Dgmjr.Http.Extensions.csproj @@ -28,7 +28,7 @@ <ItemGroup> <PackageReference Include="System.Text.Json" /> <PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" /> - <PackageReference Include="Microsoft.AspNetCore.Mvc" /> + <!-- <PackageReference Include="Microsoft.AspNetCore.Mvc" /> --> <!-- <PackageReference Include="Dgmjr.Enumerations.Enumeration" /> --> <!-- <PackageReference Include="Dgmjr.Mime" /> --> <PackageReference Include="System.ComponentModel.Usings" IncludeAssets="Build;BuildTransitive;BuildMultitargeting;Runtime;Compile" ExcludeAssets="ContentFiles;Native;Analyzers" PrivateAssets="None" /> diff --git a/src/Mvc/Dgmjr.AspNetCore.Mvc.csproj b/src/Mvc/Dgmjr.AspNetCore.Mvc.csproj index d9f9a22a..537a310e 100644 --- a/src/Mvc/Dgmjr.AspNetCore.Mvc.csproj +++ b/src/Mvc/Dgmjr.AspNetCore.Mvc.csproj @@ -12,8 +12,8 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFrameworks>net6.0;net8.0</TargetFrameworks> - <TargetFramework>net8.0</TargetFramework> + <TargetFrameworks>netstandard2.0;netstandard2.1;net6.0;net8.0</TargetFrameworks> + <!-- <TargetFramework>net8.0</TargetFramework> --> <Description>This package contains a set of extensions and things for ASP.NET Core MVC</Description> </PropertyGroup> <ItemGroup> @@ -29,8 +29,8 @@ <PackageReference Include="System.Text.Json" /> <PackageReference Include="System.Net.Http.Json" /> <PackageReference Include="Dgmjr.InterfaceGenerator" IncludeAssets="Analyzers;Build" ExcludeAssets="Native;BuildTransitive;BuildMultitargeting;ContentFiles;Compile;Runtime" PrivateAssets="All" /> - <PackageReference Include="Dgmjr.Configuration.Extensions" /> - <PackageReference Include="Microsoft.AspNetCore.Components" /> + <PackageReference Include="Dgmjr.Configuration.Extensions" Condition="!$(TargetFramework.StartsWith('netstandard'))" /> + <PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'net8.0'" /> <ProjectReference Include="../Http/Mime/Dgmjr.Mime.csproj" /> <ProjectReference Include="../Http/ResponseCodes/Dgmjr.Http.StatusCodes.csproj" /> </ItemGroup> @@ -43,10 +43,19 @@ <Using Include="System.IO.Path" Static="true" /> </ItemGroup> <ItemGroup> - <Content Include="LICENSE.md" Pack="true" PackagePath="LICENSE.md" /> + <PackageFile Include="LICENSE.md" Pack="true" PackagePath="LICENSE.md" /> + <PackageFile Include="icon.png" Pack="true" PackagePath="icon.png" /> + <PackageFile Include="./bin/$(Configuration)/$(TargetFramework)/**/*.*" Pack="true" PackagePath="lib/$(TargetFramework)/%(RecursiveDir)%(Filename)%(Extension)" /> </ItemGroup> <ItemGroup> <Reference Include="Assembly Microsoft.AspNetCore.Components.Endpoints" /> </ItemGroup> + <ItemGroup> + <Compile Remove="./IHostApplicationBuilderMvcExtensions.cs" Condition="$(TargetFramework.StartsWith('netstandard'))" /> + <Compile Remove="./MvcAutoConfigurator.cs" Condition="$(TargetFramework.StartsWith('netstandard'))" /> + <Compile Remove="./ViewControllerBase.cs" Condition="$(TargetFramework.StartsWith('netstandard'))" /> + <Compile Remove="./TypeNameAndAssemblyConfigurator.cs" Condition="$(TargetFramework.StartsWith('netstandard'))" /> + <Compile Remove="./MvcOptions.cs" Condition="$(TargetFramework.StartsWith('netstandard'))" /> + </ItemGroup> <Import Project="../Http/Mime/Dgmjr.Mime.props" /> </Project> diff --git a/src/Mvc/Dgmjr.AspNetCore.Mvc.sln b/src/Mvc/Dgmjr.AspNetCore.Mvc.sln deleted file mode 100644 index 783bd627..00000000 --- a/src/Mvc/Dgmjr.AspNetCore.Mvc.sln +++ /dev/null @@ -1,70 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B283EBC2-E01F-412D-9339-FD56EF114549}" - ProjectSection(SolutionItems) = preProject - ..\..\Directory.Build.props = ..\..\Directory.Build.props - ..\..\..\..\Directory.Build.targets = ..\..\..\..\Directory.Build.targets - ..\..\..\..\global.json = ..\..\..\..\global.json - ..\..\..\..\Packages\Versions.Local.props = ..\..\..\..\Packages\Versions.Local.props - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dgmjr.Mime", "..\Http\Mime\Dgmjr.Mime.csproj", "{FD4A80E2-D49C-4E08-B0A0-A4F99CEE64D6}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dgmjr.Http.StatusCodes", "..\Http\ResponseCodes\Dgmjr.Http.StatusCodes.csproj", "{86A9240C-CB92-4EC7-9C82-ACC429BAD774}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dgmjr.AspNetCore.Mvc", "Dgmjr.AspNetCore.Mvc.csproj", "{75CCEE17-7ED6-4DAD-85E8-971722052B7F}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Local|Any CPU = Local|Any CPU - Debug|Any CPU = Debug|Any CPU - Testing|Any CPU = Testing|Any CPU - Staging|Any CPU = Staging|Any CPU - Production|Any CPU = Production|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {FD4A80E2-D49C-4E08-B0A0-A4F99CEE64D6}.Local|Any CPU.ActiveCfg = Local|Any CPU - {FD4A80E2-D49C-4E08-B0A0-A4F99CEE64D6}.Local|Any CPU.Build.0 = Local|Any CPU - {FD4A80E2-D49C-4E08-B0A0-A4F99CEE64D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FD4A80E2-D49C-4E08-B0A0-A4F99CEE64D6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FD4A80E2-D49C-4E08-B0A0-A4F99CEE64D6}.Testing|Any CPU.ActiveCfg = Testing|Any CPU - {FD4A80E2-D49C-4E08-B0A0-A4F99CEE64D6}.Testing|Any CPU.Build.0 = Testing|Any CPU - {FD4A80E2-D49C-4E08-B0A0-A4F99CEE64D6}.Staging|Any CPU.ActiveCfg = Staging|Any CPU - {FD4A80E2-D49C-4E08-B0A0-A4F99CEE64D6}.Staging|Any CPU.Build.0 = Staging|Any CPU - {FD4A80E2-D49C-4E08-B0A0-A4F99CEE64D6}.Production|Any CPU.ActiveCfg = Local|Any CPU - {FD4A80E2-D49C-4E08-B0A0-A4F99CEE64D6}.Production|Any CPU.Build.0 = Local|Any CPU - {FD4A80E2-D49C-4E08-B0A0-A4F99CEE64D6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FD4A80E2-D49C-4E08-B0A0-A4F99CEE64D6}.Release|Any CPU.Build.0 = Release|Any CPU - {86A9240C-CB92-4EC7-9C82-ACC429BAD774}.Local|Any CPU.ActiveCfg = Local|Any CPU - {86A9240C-CB92-4EC7-9C82-ACC429BAD774}.Local|Any CPU.Build.0 = Local|Any CPU - {86A9240C-CB92-4EC7-9C82-ACC429BAD774}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {86A9240C-CB92-4EC7-9C82-ACC429BAD774}.Debug|Any CPU.Build.0 = Debug|Any CPU - {86A9240C-CB92-4EC7-9C82-ACC429BAD774}.Testing|Any CPU.ActiveCfg = Testing|Any CPU - {86A9240C-CB92-4EC7-9C82-ACC429BAD774}.Testing|Any CPU.Build.0 = Testing|Any CPU - {86A9240C-CB92-4EC7-9C82-ACC429BAD774}.Staging|Any CPU.ActiveCfg = Staging|Any CPU - {86A9240C-CB92-4EC7-9C82-ACC429BAD774}.Staging|Any CPU.Build.0 = Staging|Any CPU - {86A9240C-CB92-4EC7-9C82-ACC429BAD774}.Production|Any CPU.ActiveCfg = Local|Any CPU - {86A9240C-CB92-4EC7-9C82-ACC429BAD774}.Production|Any CPU.Build.0 = Local|Any CPU - {86A9240C-CB92-4EC7-9C82-ACC429BAD774}.Release|Any CPU.ActiveCfg = Release|Any CPU - {86A9240C-CB92-4EC7-9C82-ACC429BAD774}.Release|Any CPU.Build.0 = Release|Any CPU - {75CCEE17-7ED6-4DAD-85E8-971722052B7F}.Local|Any CPU.ActiveCfg = Local|Any CPU - {75CCEE17-7ED6-4DAD-85E8-971722052B7F}.Local|Any CPU.Build.0 = Local|Any CPU - {75CCEE17-7ED6-4DAD-85E8-971722052B7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {75CCEE17-7ED6-4DAD-85E8-971722052B7F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {75CCEE17-7ED6-4DAD-85E8-971722052B7F}.Testing|Any CPU.ActiveCfg = Testing|Any CPU - {75CCEE17-7ED6-4DAD-85E8-971722052B7F}.Testing|Any CPU.Build.0 = Testing|Any CPU - {75CCEE17-7ED6-4DAD-85E8-971722052B7F}.Staging|Any CPU.ActiveCfg = Staging|Any CPU - {75CCEE17-7ED6-4DAD-85E8-971722052B7F}.Staging|Any CPU.Build.0 = Staging|Any CPU - {75CCEE17-7ED6-4DAD-85E8-971722052B7F}.Production|Any CPU.ActiveCfg = Local|Any CPU - {75CCEE17-7ED6-4DAD-85E8-971722052B7F}.Production|Any CPU.Build.0 = Local|Any CPU - {75CCEE17-7ED6-4DAD-85E8-971722052B7F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {75CCEE17-7ED6-4DAD-85E8-971722052B7F}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {F2976566-223F-4393-9A1E-BB8EA5953CED} - EndGlobalSection -EndGlobal diff --git a/src/Mvc/LoggerExtensions.cs b/src/Mvc/LoggerExtensions.cs index f55ee960..08a42aed 100644 --- a/src/Mvc/LoggerExtensions.cs +++ b/src/Mvc/LoggerExtensions.cs @@ -19,30 +19,44 @@ public static partial class LoggerExtensions [LoggerMessage( EventId = 3, Level = LogLevel.Information, - Message = "MvcAutoConfigurator.Configure(WebApplicationBuilder)")] - public static partial void MvcAutoConfiguratorConfigureWebApplicationBuilder(this ILogger logger); + Message = "MvcAutoConfigurator.Configure(WebApplicationBuilder)" + )] + public static partial void MvcAutoConfiguratorConfigureWebApplicationBuilder( + this ILogger logger + ); [LoggerMessage( EventId = 4, Level = LogLevel.Information, - Message = "MvcAutoConfigurator.Configure(IApplicationBuilder)")] + Message = "MvcAutoConfigurator.Configure(IApplicationBuilder)" + )] public static partial void MvcAutoConfiguratorConfigureIApplicationBuilder(this ILogger logger); [LoggerMessage( EventId = 5, Level = LogLevel.Information, - Message = "Setting up Mvc service: {ServiceName}")] + Message = "Setting up Mvc service: {ServiceName}" + )] public static partial void SettingUpMvcService(this ILogger logger, string serviceName); [LoggerMessage( EventId = 6, Level = LogLevel.Information, - Message = "Setting up Mvc service: {ServiceName} with options: {Options}")] - public static partial void SettingUpMvcService(this ILogger logger, string serviceName, object options); + Message = "Setting up Mvc service: {ServiceName} with options: {Options}" + )] + public static partial void SettingUpMvcService( + this ILogger logger, + string serviceName, + object options + ); [LoggerMessage( EventId = 7, Level = LogLevel.Information, - Message = "Adding Mvc service to the pipeline: {ServiceName}")] - public static partial void AddingMvcServiceToThePipeline(this ILogger logger, string serviceName); + Message = "Adding Mvc service to the pipeline: {ServiceName}" + )] + public static partial void AddingMvcServiceToThePipeline( + this ILogger logger, + string serviceName + ); } diff --git a/src/Mvc/MvcAutoConfigurator.cs b/src/Mvc/MvcAutoConfigurator.cs index 8da0f229..4ed9b9cc 100644 --- a/src/Mvc/MvcAutoConfigurator.cs +++ b/src/Mvc/MvcAutoConfigurator.cs @@ -6,7 +6,10 @@ namespace Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Dgmjr.Abstractions; -public class MvcAutoConfigurator(ILogger<MvcAutoConfigurator> logger) : IConfigureIHostApplicationBuilder, IConfigureIApplicationBuilder, ILog +public class MvcAutoConfigurator(ILogger<MvcAutoConfigurator> logger) + : IConfigureIHostApplicationBuilder, + IConfigureIApplicationBuilder, + ILog { public ILogger? Logger => logger; private const string Mvc = nameof(Mvc); diff --git a/src/Mvc/MvcOptions.cs b/src/Mvc/MvcOptions.cs index 119e12c0..bce01f42 100644 --- a/src/Mvc/MvcOptions.cs +++ b/src/Mvc/MvcOptions.cs @@ -29,8 +29,10 @@ public MvcOptions() /// <summary><see langword="true" /> if you want to add Razor pages, <see langword="false" /> otherwise</summary> public virtual bool AddRazorPages { get; set; } = false; + /// <summary><see langword="true" /> if you want to add Razor components, <see langword="false" /> otherwise</summary> public virtual bool AddRazorComponents { get; set; } = false; + /// <summary><see langword="true" /> if you want to add interactive server components, <see langword="false" /> otherwise</summary> public virtual bool AddInteractiveServerComponents { get; set; } = false; diff --git a/src/Mvc/ProblemDetailsExamples/ConflictProblemDetailsExample.cs b/src/Mvc/ProblemDetailsExamples/ConflictProblemDetailsExample.cs index d4f19b64..7b9ec42c 100644 --- a/src/Mvc/ProblemDetailsExamples/ConflictProblemDetailsExample.cs +++ b/src/Mvc/ProblemDetailsExamples/ConflictProblemDetailsExample.cs @@ -27,5 +27,6 @@ public record class ConflictProblemDetailsExample : IProblemDetails /// <value>{ { "traceId", "0HLQ9V1J3Q0:40000003" } }</value> /// <example>{ { "traceId", "0HLQ9V1J3Q0:40000003" } }</example> - public IDictionary<string, object?> Extensions => new Dictionary<string, object?> { { "traceId", "0HLQ9V1J3Q0:40000003" } }; + public IDictionary<string, object?> Extensions => + new Dictionary<string, object?> { { "traceId", "0HLQ9V1J3Q0:40000003" } }; } diff --git a/src/Mvc/ServiceNames.cs b/src/Mvc/ServiceNames.cs index d4cd7ab1..cb6d8b54 100644 --- a/src/Mvc/ServiceNames.cs +++ b/src/Mvc/ServiceNames.cs @@ -9,7 +9,9 @@ public static class ServiceNames public const string Controllers = nameof(Controllers); public const string ControllersAsServices = nameof(ControllersAsServices); public const string XmlSerializerFormatters = nameof(XmlSerializerFormatters); - public const string XmlDataContractSerializerFormatters = nameof(XmlDataContractSerializerFormatters); + public const string XmlDataContractSerializerFormatters = nameof( + XmlDataContractSerializerFormatters + ); public const string Cors = nameof(Cors); public const string MicrosoftIdentityUI = nameof(MicrosoftIdentityUI); public const string RazorComponents = nameof(RazorComponents); diff --git a/src/Mvc/TypeNameAndAssemblyConfigurator.cs b/src/Mvc/TypeNameAndAssemblyConfigurator.cs index 67b827a0..17ca1787 100644 --- a/src/Mvc/TypeNameAndAssemblyConfigurator.cs +++ b/src/Mvc/TypeNameAndAssemblyConfigurator.cs @@ -1,5 +1,7 @@ +using System; using System.Collections; using System.Runtime.Loader; +using System.Text.RegularExpressions; namespace Dgmjr.AspNetCore.Mvc; @@ -11,6 +13,11 @@ public class TypeNameAndAssemblyConfigurator<T, U>( where T : class where U : class { + private const string TypeWithAssemblyPattern = + @"^(?<TypeName>([A-Za-z0-9_\.]+(?:\+?[A-Za-z0-9_]+)*(\`\d+\[(?:[^\[\]]+|(\2))*\])?)),\s*(?<AssemblyName>([A-Za-z0-9_\.]+))$"; + private static readonly Regex TypeWithAssemblyRegex = + new(TypeWithAssemblyPattern, RegexOptions.Compiled); + public virtual void Configure(T options) { var configurationSection = configuration; @@ -21,28 +28,49 @@ public virtual void Configure(T options) var list = property.Compile().Invoke(options); - foreach (var (assemblyName, typeName) in configurationSection.GetChildren().Select(GetType)) + foreach (var t in configurationSection.GetChildren().Select(configSection => configSection.Value).WhereNotNull().Select(type.GetType)) { - var u = Activator.CreateInstance(assemblyName, typeName).Unwrap() as U; - if(u is not null) + if(t != null) { - list.Add(u); + var u = Activator.CreateInstance(t) as U; + if (u is not null) + { + list.Add(u); + } } } } - private (string assemblyName, string typeName) GetType(IConfigurationSection section) - { - var parts = section.Value.Split( - ',', - StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries - ); - var assemblyName = parts[1]; - var typeName = parts[0]; - return (assemblyName, typeName); + // private (string assemblyName, string typeName) GetType(IConfigurationSection section) + // { + // try + // { + // var type = Type.GetType(section.Value); + // if (type is not null) + // return (type.FullName, type.Assembly.GetName().FullName); + // else + // return (section.Value, section.Value); + // } + // catch { } + // return (section.Value, section.Value); + // var match = TypeWithAssemblyRegex.Match(section.Value); + // if (!match.Success) + // { + // throw new InvalidOperationException( + // $"Invalid type name and assembly name configuration: {section.Value}" + // ); + // } + // return (match.Groups["AssemblyName"].Value, match.Groups["TypeName"].Value); + // var parts = section.Value.Split( + // ',', + // StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries + // ); + // var assemblyName = parts[1]; + // var typeName = parts[0]; + // return (assemblyName, typeName); // var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName( // new AssemblyName(assemblyName) // ); // return assembly.GetType(typeName); - } + // } } diff --git a/src/Security/Authorization/LICENSE.md b/src/Security/Authorization/LICENSE.md index 4f608744..4f592f86 100755 --- a/src/Security/Authorization/LICENSE.md +++ b/src/Security/Authorization/LICENSE.md @@ -1,22 +1,22 @@ --- -date: 2023-07-13T05:44:46:00.048Z +date: 2023-07-13T05:44:46:00-05:00Z description: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files, yadda, yadda, yadda... keywords: - - IP - - copyright - - license - - mit +- IP +- copyright +- license +- mit permissions: - - commercial-use - - modifications - - distribution - - private-use +- commercial-use +- modifications +- distribution +- private-use conditions: - - include-copyright +- include-copyright limitations: - - liability - - warranty -lastmod: 2023-08-29T17:13:51:00.216Z +- liability +- warranty +lastmod: 2024-01-0T00:39:00.0000+05:00Z license: MIT slug: mit-license title: MIT License @@ -25,7 +25,7 @@ type: license # MIT License -## Copyright © 2022-2023 [David G. Moore, Jr.](mailto:david@dgmjr.io "Send David an email") ([@dgmjr](https://github.com/dgmjr "Contact david on GitHub")), All Rights Reserved +## Copyright © 2022-2024 [David G. Moore, Jr.](mailto:david@dgmjr.io "Send Dr. Moore") ([@dgmjr](https://github.com/dgmjr "Contact Dr. Moore on GitHub")), All Rights Reserved Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/src/Security/Security/LICENSE.md b/src/Security/Security/LICENSE.md index 4f608744..4f592f86 100755 --- a/src/Security/Security/LICENSE.md +++ b/src/Security/Security/LICENSE.md @@ -1,22 +1,22 @@ --- -date: 2023-07-13T05:44:46:00.048Z +date: 2023-07-13T05:44:46:00-05:00Z description: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files, yadda, yadda, yadda... keywords: - - IP - - copyright - - license - - mit +- IP +- copyright +- license +- mit permissions: - - commercial-use - - modifications - - distribution - - private-use +- commercial-use +- modifications +- distribution +- private-use conditions: - - include-copyright +- include-copyright limitations: - - liability - - warranty -lastmod: 2023-08-29T17:13:51:00.216Z +- liability +- warranty +lastmod: 2024-01-0T00:39:00.0000+05:00Z license: MIT slug: mit-license title: MIT License @@ -25,7 +25,7 @@ type: license # MIT License -## Copyright © 2022-2023 [David G. Moore, Jr.](mailto:david@dgmjr.io "Send David an email") ([@dgmjr](https://github.com/dgmjr "Contact david on GitHub")), All Rights Reserved +## Copyright © 2022-2024 [David G. Moore, Jr.](mailto:david@dgmjr.io "Send Dr. Moore") ([@dgmjr](https://github.com/dgmjr "Contact Dr. Moore on GitHub")), All Rights Reserved Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: