diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 86232da..b7e46c3 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -31,6 +31,11 @@ updates:
update-types: ["version-update:semver-patch"]
- dependency-name: "AzureIPNetworks"
update-types: ["version-update:semver-patch"]
+ # Ignore major updates for packages used in multi-targeting
+ - dependency-name: "Microsoft.AspNetCore.Mvc.NewtonsoftJson"
+ update-types: ["version-update:semver-patch"]
+ - dependency-name: "Microsoft.AspNetCore.TestHost"
+ update-types: ["version-update:semver-patch"]
- package-ecosystem: "github-actions" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index c9194c4..65b87a7 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -39,7 +39,7 @@ jobs:
- name: Setup .NET SDK
uses: actions/setup-dotnet@v3
with:
- dotnet-version: 7.x
+ dotnet-version: 8.x
- name: Start MongoDB
uses: supercharge/mongodb-github-action@v1.10.0
diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml
index 1c9bc41..3f07f40 100644
--- a/.github/workflows/preview.yml
+++ b/.github/workflows/preview.yml
@@ -55,7 +55,7 @@ jobs:
- name: Setup .NET SDK
uses: actions/setup-dotnet@v3
with:
- dotnet-version: 7.x
+ dotnet-version: 8.x
- name: Start MongoDB
uses: supercharge/mongodb-github-action@v1.10.0
@@ -100,7 +100,7 @@ jobs:
- name: Setup .NET SDK
uses: actions/setup-dotnet@v3
with:
- dotnet-version: '7.x'
+ dotnet-version: '8.x'
source-url: ${{ secrets.PRIVATE_FEED_URL }}
env:
NUGET_AUTH_TOKEN: ${{ secrets.PRIVATE_FEED_API_KEY }}
@@ -126,7 +126,7 @@ jobs:
- name: Setup .NET SDK
uses: actions/setup-dotnet@v3
with:
- dotnet-version: '7.x'
+ dotnet-version: '8.x'
source-url: https://api.nuget.org/v3/index.json
env:
NUGET_AUTH_TOKEN: ${{ secrets.NUGET_API_KEY }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 519a64e..4c3bc8b 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -52,7 +52,7 @@ jobs:
- name: Setup .NET SDK
uses: actions/setup-dotnet@v3
with:
- dotnet-version: 7.x
+ dotnet-version: 8.x
source-url: https://api.nuget.org/v3/index.json
env:
NUGET_AUTH_TOKEN: ${{ secrets.NUGET_API_KEY }}
diff --git a/Directory.Build.props b/Directory.Build.props
index a62239f..92292b8 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -2,7 +2,7 @@
- net7.0
+ net7.0;net8.0
latest
enable
enable
diff --git a/samples/HttpAuthenticationSample/HttpAuthenticationSample.csproj b/samples/HttpAuthenticationSample/HttpAuthenticationSample.csproj
index 13e31e5..d89075a 100644
--- a/samples/HttpAuthenticationSample/HttpAuthenticationSample.csproj
+++ b/samples/HttpAuthenticationSample/HttpAuthenticationSample.csproj
@@ -1,8 +1,8 @@
-
-
+
+
diff --git a/samples/SerilogSample/SerilogSample.csproj b/samples/SerilogSample/SerilogSample.csproj
index 1925698..9224947 100644
--- a/samples/SerilogSample/SerilogSample.csproj
+++ b/samples/SerilogSample/SerilogSample.csproj
@@ -5,7 +5,7 @@
-
+
diff --git a/samples/TokensSample/Controllers/BooksController.cs b/samples/TokensSample/Controllers/BooksController.cs
index b03025a..5930fea 100644
--- a/samples/TokensSample/Controllers/BooksController.cs
+++ b/samples/TokensSample/Controllers/BooksController.cs
@@ -18,7 +18,7 @@ public IActionResult List([FromQuery] ContinuationToken? token)
query = query.Take(10); // limit the number of items to pull from the database
var books = query.ToList(); // pull from the database
- last = books.Any() ? books.Last().Created : null;
+ last = books.Count != 0 ? books.Last().Created : null;
if (last is not null)
{
diff --git a/samples/TokensSample/Program.cs b/samples/TokensSample/Program.cs
index 8e44ce1..066d80b 100644
--- a/samples/TokensSample/Program.cs
+++ b/samples/TokensSample/Program.cs
@@ -1,6 +1,6 @@
var builder = WebApplication.CreateBuilder(args);
-// see https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/introduction?view=aspnetcore-7.0
+// see https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/introduction?view=aspnetcore-8.0
builder.Services.AddDataProtection();
builder.Services.AddControllers()
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index fe541e8..30c2e48 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -7,7 +7,7 @@
true
Tingle Software
- true
+ true
@@ -29,11 +29,11 @@
- net6.0;net7.0
+ net6.0;net7.0;net8.0
- netstandard2.1;net7.0
+ netstandard2.1;net7.0;net8.0
diff --git a/src/Tingle.AspNetCore.Authentication/PassThrough/PassThroughHandler.cs b/src/Tingle.AspNetCore.Authentication/PassThrough/PassThroughHandler.cs
index dbb4304..44bbf4a 100644
--- a/src/Tingle.AspNetCore.Authentication/PassThrough/PassThroughHandler.cs
+++ b/src/Tingle.AspNetCore.Authentication/PassThrough/PassThroughHandler.cs
@@ -11,6 +11,18 @@ namespace Tingle.AspNetCore.Authentication.PassThrough;
///
public class PassThroughHandler : AuthenticationHandler
{
+#if NET8_0_OR_GREATER
+
+ ///
+ /// Create an instance of
+ ///
+ ///
+ ///
+ ///
+ public PassThroughHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder) : base(options, logger, encoder) { }
+
+#else
+
///
/// Create an instance of
///
@@ -18,11 +30,16 @@ public class PassThroughHandler : AuthenticationHandler
///
///
///
+ [Obsolete("ISystemClock is obsolete, use TimeProvider on AuthenticationSchemeOptions instead.")]
public PassThroughHandler(IOptionsMonitor options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock) : base(options, logger, encoder, clock) { }
+#endif
+
+
+
///
/// The handler calls methods on the events which give the application control at certain points where processing is occurring.
/// If it is not provided a default instance is supplied which does nothing when the methods are called.
diff --git a/src/Tingle.AspNetCore.Authentication/SharedKey/SharedKeyHandler.cs b/src/Tingle.AspNetCore.Authentication/SharedKey/SharedKeyHandler.cs
index d80d82e..aab4f89 100644
--- a/src/Tingle.AspNetCore.Authentication/SharedKey/SharedKeyHandler.cs
+++ b/src/Tingle.AspNetCore.Authentication/SharedKey/SharedKeyHandler.cs
@@ -17,6 +17,17 @@ namespace Tingle.AspNetCore.Authentication.SharedKey;
///
public class SharedKeyHandler : AuthenticationHandler
{
+#if NET8_0_OR_GREATER
+ ///
+ /// Create an instance of
+ ///
+ ///
+ ///
+ ///
+ public SharedKeyHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder) : base(options, logger, encoder) { }
+
+#else
+
///
/// Create an instance of
///
@@ -24,10 +35,12 @@ public class SharedKeyHandler : AuthenticationHandler
///
///
///
+ [Obsolete("ISystemClock is obsolete, use TimeProvider on AuthenticationSchemeOptions instead.")]
public SharedKeyHandler(IOptionsMonitor options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock) : base(options, logger, encoder, clock) { }
+#endif
///
/// The handler calls methods on the events which give the application control at certain points where processing is occurring.
@@ -131,7 +144,7 @@ protected override async Task HandleAuthenticateAsync()
}
}
- if (validationFailures.Any())
+ if (validationFailures.Count != 0)
{
var authenticationFailedContext = new AuthenticationFailedContext(Context, Scheme, Options)
{
diff --git a/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyInvalidDateException.cs b/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyInvalidDateException.cs
index f51bd06..27b798d 100644
--- a/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyInvalidDateException.cs
+++ b/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyInvalidDateException.cs
@@ -1,6 +1,4 @@
-using System.Runtime.Serialization;
-
-namespace Tingle.AspNetCore.Authentication.SharedKey.Validation.Exceptions;
+namespace Tingle.AspNetCore.Authentication.SharedKey.Validation.Exceptions;
///
[Serializable]
@@ -15,9 +13,6 @@ public SharedKeyInvalidDateException(string message) : base(message) { }
///
public SharedKeyInvalidDateException(string message, Exception inner) : base(message, inner) { }
- ///
- protected SharedKeyInvalidDateException(SerializationInfo info, StreamingContext context) : base(info, context) { }
-
///
/// The value supplied for date
///
diff --git a/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyInvalidSignatureException.cs b/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyInvalidSignatureException.cs
index 944eda0..4ff86da 100644
--- a/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyInvalidSignatureException.cs
+++ b/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyInvalidSignatureException.cs
@@ -1,6 +1,4 @@
-using System.Runtime.Serialization;
-
-namespace Tingle.AspNetCore.Authentication.SharedKey.Validation.Exceptions;
+namespace Tingle.AspNetCore.Authentication.SharedKey.Validation.Exceptions;
///
[Serializable]
@@ -14,7 +12,4 @@ public SharedKeyInvalidSignatureException(string message) : base(message) { }
///
public SharedKeyInvalidSignatureException(string message, Exception inner) : base(message, inner) { }
-
- ///
- protected SharedKeyInvalidSignatureException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
diff --git a/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyInvalidSigningKeysException.cs b/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyInvalidSigningKeysException.cs
index dacc99e..80cd1ae 100644
--- a/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyInvalidSigningKeysException.cs
+++ b/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyInvalidSigningKeysException.cs
@@ -1,6 +1,4 @@
-using System.Runtime.Serialization;
-
-namespace Tingle.AspNetCore.Authentication.SharedKey.Validation.Exceptions;
+namespace Tingle.AspNetCore.Authentication.SharedKey.Validation.Exceptions;
///
[Serializable]
@@ -15,9 +13,6 @@ public SharedKeyInvalidSigningKeysException(string message) : base(message) { }
///
public SharedKeyInvalidSigningKeysException(string message, Exception inner) : base(message, inner) { }
- ///
- protected SharedKeyInvalidSigningKeysException(SerializationInfo info, StreamingContext context) : base(info, context) { }
-
///
/// List of invalid keys
///
diff --git a/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyNoDateException.cs b/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyNoDateException.cs
index 6f9c983..77e6773 100644
--- a/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyNoDateException.cs
+++ b/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyNoDateException.cs
@@ -1,6 +1,4 @@
-using System.Runtime.Serialization;
-
-namespace Tingle.AspNetCore.Authentication.SharedKey.Validation.Exceptions;
+namespace Tingle.AspNetCore.Authentication.SharedKey.Validation.Exceptions;
///
[Serializable]
@@ -15,9 +13,6 @@ public SharedKeyNoDateException(string message) : base(message) { }
///
public SharedKeyNoDateException(string message, Exception inner) : base(message, inner) { }
- ///
- protected SharedKeyNoDateException(SerializationInfo info, StreamingContext context) : base(info, context) { }
-
///
/// List of possible header names for specifying the time
///
diff --git a/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyNoKeysException.cs b/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyNoKeysException.cs
index 79a9173..769c08d 100644
--- a/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyNoKeysException.cs
+++ b/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyNoKeysException.cs
@@ -1,6 +1,4 @@
-using System.Runtime.Serialization;
-
-namespace Tingle.AspNetCore.Authentication.SharedKey.Validation.Exceptions;
+namespace Tingle.AspNetCore.Authentication.SharedKey.Validation.Exceptions;
///
[Serializable]
@@ -14,7 +12,4 @@ public SharedKeyNoKeysException(string message) : base(message) { }
///
public SharedKeyNoKeysException(string message, Exception inner) : base(message, inner) { }
-
- ///
- protected SharedKeyNoKeysException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
diff --git a/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyTimeWindowExpiredException.cs b/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyTimeWindowExpiredException.cs
index 390b08c..6675a7d 100644
--- a/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyTimeWindowExpiredException.cs
+++ b/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyTimeWindowExpiredException.cs
@@ -1,6 +1,4 @@
-using System.Runtime.Serialization;
-
-namespace Tingle.AspNetCore.Authentication.SharedKey.Validation.Exceptions;
+namespace Tingle.AspNetCore.Authentication.SharedKey.Validation.Exceptions;
///
[Serializable]
@@ -15,9 +13,6 @@ public SharedKeyTimeWindowExpiredException(string message) : base(message) { }
///
public SharedKeyTimeWindowExpiredException(string message, Exception inner) : base(message, inner) { }
- ///
- protected SharedKeyTimeWindowExpiredException(SerializationInfo info, StreamingContext context) : base(info, context) { }
-
///
/// The date supplied
///
diff --git a/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyTokenException.cs b/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyTokenException.cs
index 38fa662..eedfd73 100644
--- a/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyTokenException.cs
+++ b/src/Tingle.AspNetCore.Authentication/SharedKey/Validation/Exceptions/SharedKeyTokenException.cs
@@ -1,6 +1,4 @@
-using System.Runtime.Serialization;
-
-namespace Tingle.AspNetCore.Authentication.SharedKey.Validation.Exceptions;
+namespace Tingle.AspNetCore.Authentication.SharedKey.Validation.Exceptions;
///
[Serializable]
@@ -14,7 +12,4 @@ public SharedKeyTokenException(string message) : base(message) { }
///
public SharedKeyTokenException(string message, Exception inner) : base(message, inner) { }
-
- ///
- protected SharedKeyTokenException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
diff --git a/src/Tingle.AspNetCore.Authorization/AuthorizationPolicyBuilderExtensions.cs b/src/Tingle.AspNetCore.Authorization/AuthorizationPolicyBuilderExtensions.cs
index 6766507..005cb47 100644
--- a/src/Tingle.AspNetCore.Authorization/AuthorizationPolicyBuilderExtensions.cs
+++ b/src/Tingle.AspNetCore.Authorization/AuthorizationPolicyBuilderExtensions.cs
@@ -26,7 +26,11 @@ public static AuthorizationPolicyBuilder RequireApprovedNetworks(this Authorizat
if (!networks.Any()) return builder;
// reduce the networks where possible (referred to as supernetting)
+#if NET8_0_OR_GREATER
+ var reduced = networks;
+#else
var reduced = IPNetwork.Supernet(networks.ToArray());
+#endif
// add the requirement
return builder.AddRequirements(new ApprovedIPNetworkRequirement(reduced));
@@ -134,7 +138,11 @@ public static AuthorizationPolicyBuilder RequireNetworkFromDns(this Authorizatio
var ips = Dns.GetHostAddresses(f);
// parse the IP addresses into IP networks
+#if NET8_0_OR_GREATER
+ var rawNetworks = ips?.Select(ip => IPNetwork.Parse($"{ip}/32")) ?? Array.Empty();
+#else
var rawNetworks = ips?.Select(ip => IPNetwork.Parse(ip.ToString(), CidrGuess.ClassLess)) ?? Array.Empty();
+#endif
// add networks into the list if there are any
if (rawNetworks?.Any() ?? false)
@@ -148,7 +156,7 @@ public static AuthorizationPolicyBuilder RequireNetworkFromDns(this Authorizatio
}
// if there are no networks, return
- if (!networks.Any()) return builder;
+ if (networks.Count == 0) return builder;
// create the requirement and add it to the builder
return builder.RequireApprovedNetworks(networks);
diff --git a/src/Tingle.AspNetCore.Authorization/README.md b/src/Tingle.AspNetCore.Authorization/README.md
index 5e0f849..98fbbec 100644
--- a/src/Tingle.AspNetCore.Authorization/README.md
+++ b/src/Tingle.AspNetCore.Authorization/README.md
@@ -43,7 +43,7 @@ builder.Services.AddHttpContextAccessor();
builder.Services.AddApprovedNetworksHandler();
```
-Details of the implementation of `my_auth_scheme` authentication scheme have been omitted here since it is beyond the scope of this discussion. More details on how to handle authentication in ASP.NET Core can be found [here](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/?view=aspnetcore-7.0).
+Details of the implementation of `my_auth_scheme` authentication scheme have been omitted here since it is beyond the scope of this discussion. More details on how to handle authentication in ASP.NET Core can be found [here](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/?view=aspnetcore-8.0).
The above code section defines `my_auth_policy` authorization policy which ensures the user who has been authenticated via the `my_auth_scheme` has access to the resource they're trying to gain access to. Using `RequireApprovedNetworks` extension method on the `AuthorizationPolicyBuilder` we can then add a comma separated list of IP networks that are approved to access the resource from.
diff --git a/src/Tingle.AspNetCore.Authorization/Tingle.AspNetCore.Authorization.csproj b/src/Tingle.AspNetCore.Authorization/Tingle.AspNetCore.Authorization.csproj
index da5b3b2..4796d51 100644
--- a/src/Tingle.AspNetCore.Authorization/Tingle.AspNetCore.Authorization.csproj
+++ b/src/Tingle.AspNetCore.Authorization/Tingle.AspNetCore.Authorization.csproj
@@ -10,7 +10,7 @@
-
+
diff --git a/src/Tingle.AspNetCore.DataProtection.MongoDB/README.md b/src/Tingle.AspNetCore.DataProtection.MongoDB/README.md
index dd6d976..b162ba2 100644
--- a/src/Tingle.AspNetCore.DataProtection.MongoDB/README.md
+++ b/src/Tingle.AspNetCore.DataProtection.MongoDB/README.md
@@ -2,7 +2,7 @@
Web applications often need to store security-sensitive data. Windows provides DPAPI for desktop applications, but this is unsuitable for web applications especially when running in a Docker container. The ASP.NET Core data protection stack provide a simple, easy to use cryptographic API a developer can use to protect data, including key management and rotation.
-Microsoft has already provided ways to persist data protection keys to [various storage systems](https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-7.0).
+Microsoft has already provided ways to persist data protection keys to [various storage systems](https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-8.0).
This package provides the functionality to persist the data protection keys to MongoDB.
diff --git a/src/Tingle.AspNetCore.JsonPatch.NewtonsoftJson/JsonPatchDocumentExtensions.cs b/src/Tingle.AspNetCore.JsonPatch.NewtonsoftJson/JsonPatchDocumentExtensions.cs
index c2349e8..7b8865b 100644
--- a/src/Tingle.AspNetCore.JsonPatch.NewtonsoftJson/JsonPatchDocumentExtensions.cs
+++ b/src/Tingle.AspNetCore.JsonPatch.NewtonsoftJson/JsonPatchDocumentExtensions.cs
@@ -19,11 +19,11 @@ public static class JsonPatchDocumentExtensions
/// The entity on which is applied.
/// The to add errors.
/// The properties that are not allowed to changed
- public static void ApplyToSafely(this JsonPatchDocument patchDoc,
- T objectToApplyTo,
- ModelStateDictionary modelState,
- IEnumerable immutableProperties)
- where T : class
+ public static void ApplyToSafely<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>(
+ this JsonPatchDocument patchDoc,
+ T objectToApplyTo,
+ ModelStateDictionary modelState,
+ IEnumerable immutableProperties) where T : class
{
if (patchDoc == null) throw new ArgumentNullException(nameof(patchDoc));
if (objectToApplyTo == null) throw new ArgumentNullException(nameof(objectToApplyTo));
@@ -47,12 +47,12 @@ public static void ApplyToSafely(this JsonPatchDocument patchDoc,
/// The to add errors.
/// The prefix to use when looking up values in .
/// The properties that are not allowed to changed
- public static void ApplyToSafely(this JsonPatchDocument patchDoc,
- T objectToApplyTo,
- ModelStateDictionary modelState,
- string prefix,
- IEnumerable immutableProperties)
- where T : class
+ public static void ApplyToSafely<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>(
+ this JsonPatchDocument patchDoc,
+ T objectToApplyTo,
+ ModelStateDictionary modelState,
+ string prefix,
+ IEnumerable immutableProperties) where T : class
{
if (patchDoc == null) throw new ArgumentNullException(nameof(patchDoc));
if (objectToApplyTo == null) throw new ArgumentNullException(nameof(objectToApplyTo));
@@ -88,10 +88,10 @@ public static void ApplyToSafely(this JsonPatchDocument patchDoc,
/// The .
/// The entity on which is applied.
/// The to add errors.
- public static void ApplyToSafely(this JsonPatchDocument patchDoc,
- T objectToApplyTo,
- ModelStateDictionary modelState)
- where T : class
+ public static void ApplyToSafely<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>(
+ this JsonPatchDocument patchDoc,
+ T objectToApplyTo,
+ ModelStateDictionary modelState) where T : class
{
if (patchDoc == null) throw new ArgumentNullException(nameof(patchDoc));
if (objectToApplyTo == null) throw new ArgumentNullException(nameof(objectToApplyTo));
diff --git a/src/Tingle.AspNetCore.JsonPatch.NewtonsoftJson/Tingle.AspNetCore.JsonPatch.NewtonsoftJson.csproj b/src/Tingle.AspNetCore.JsonPatch.NewtonsoftJson/Tingle.AspNetCore.JsonPatch.NewtonsoftJson.csproj
index 6e564bf..60c8b44 100644
--- a/src/Tingle.AspNetCore.JsonPatch.NewtonsoftJson/Tingle.AspNetCore.JsonPatch.NewtonsoftJson.csproj
+++ b/src/Tingle.AspNetCore.JsonPatch.NewtonsoftJson/Tingle.AspNetCore.JsonPatch.NewtonsoftJson.csproj
@@ -1,7 +1,6 @@
- net7.0
Extensions to ensure immutable types aren't modified or removed during JSON PATCH operations
@@ -10,7 +9,9 @@
-
+
+
+
diff --git a/src/Tingle.AspNetCore.Tokens/README.md b/src/Tingle.AspNetCore.Tokens/README.md
index b70a4fb..8dacafc 100644
--- a/src/Tingle.AspNetCore.Tokens/README.md
+++ b/src/Tingle.AspNetCore.Tokens/README.md
@@ -1,7 +1,7 @@
# Tingle.AspNetCore.Tokens
This library adds support for generation of continuation tokens in ASP.NET Core with optional expiry. This is particularly useful for pagination, user invite tokens, expiring operation tokens, etc.
-The functionality is availed through the `ContinuationToken` and `TimedContinuationToken` types. These are backed using the [DataProtection sub-system in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/introduction?view=aspnetcore-7.0).
+The functionality is availed through the `ContinuationToken` and `TimedContinuationToken` types. These are backed using the [DataProtection sub-system in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/introduction?view=aspnetcore-8.0).
See [sample](./samples/TokensSample).
@@ -10,7 +10,7 @@ First step is to register the required services.
```cs
var builder = WebApplication.CreateBuilder(args);
-// see https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/introduction?view=aspnetcore-7.0
+// see https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/introduction?view=aspnetcore-8.0
builder.Services.AddDataProtection();
builder.Services.AddControllers()
diff --git a/src/Tingle.Extensions.Caching.MongoDB/Tingle.Extensions.Caching.MongoDB.csproj b/src/Tingle.Extensions.Caching.MongoDB/Tingle.Extensions.Caching.MongoDB.csproj
index 80a550a..bfd176d 100644
--- a/src/Tingle.Extensions.Caching.MongoDB/Tingle.Extensions.Caching.MongoDB.csproj
+++ b/src/Tingle.Extensions.Caching.MongoDB/Tingle.Extensions.Caching.MongoDB.csproj
@@ -14,8 +14,8 @@ For more information, refer to https://www.mongodb.com/.
-
-
+
+
diff --git a/src/Tingle.Extensions.DataAnnotations/AllowedValuesAttribute.cs b/src/Tingle.Extensions.DataAnnotations/AllowedValuesAttribute.cs
index 1f8f5e8..07f8f00 100644
--- a/src/Tingle.Extensions.DataAnnotations/AllowedValuesAttribute.cs
+++ b/src/Tingle.Extensions.DataAnnotations/AllowedValuesAttribute.cs
@@ -1,4 +1,5 @@
-using System.Collections;
+#if !NET8_0_OR_GREATER
+using System.Collections;
namespace System.ComponentModel.DataAnnotations;
@@ -54,3 +55,4 @@ public override bool IsValid(object? value)
return !unknown.Any();
}
}
+#endif
diff --git a/src/Tingle.Extensions.DataAnnotations/Tingle.Extensions.DataAnnotations.csproj b/src/Tingle.Extensions.DataAnnotations/Tingle.Extensions.DataAnnotations.csproj
index 3db2c7b..34f0c13 100644
--- a/src/Tingle.Extensions.DataAnnotations/Tingle.Extensions.DataAnnotations.csproj
+++ b/src/Tingle.Extensions.DataAnnotations/Tingle.Extensions.DataAnnotations.csproj
@@ -9,11 +9,11 @@
$(PackageTags);validation;dataannotations
-
+
-
+
diff --git a/src/Tingle.Extensions.Http.Authentication/Tingle.Extensions.Http.Authentication.csproj b/src/Tingle.Extensions.Http.Authentication/Tingle.Extensions.Http.Authentication.csproj
index f19787d..6d6ef6a 100644
--- a/src/Tingle.Extensions.Http.Authentication/Tingle.Extensions.Http.Authentication.csproj
+++ b/src/Tingle.Extensions.Http.Authentication/Tingle.Extensions.Http.Authentication.csproj
@@ -14,12 +14,12 @@
-
-
+
+
-
-
+
+
diff --git a/src/Tingle.Extensions.Http/HttpApiResponseException.cs b/src/Tingle.Extensions.Http/HttpApiResponseException.cs
index 670d126..0fb232e 100644
--- a/src/Tingle.Extensions.Http/HttpApiResponseException.cs
+++ b/src/Tingle.Extensions.Http/HttpApiResponseException.cs
@@ -1,5 +1,4 @@
using System.Net;
-using System.Runtime.Serialization;
namespace Tingle.Extensions.Http;
@@ -18,9 +17,6 @@ public HttpApiResponseException(string message) : base(message) { }
/// Creates an instance of .
public HttpApiResponseException(string message, Exception inner) : base(message, inner) { }
- /// Creates an instance of .
- protected HttpApiResponseException(SerializationInfo info, StreamingContext context) : base(info, context) { }
-
/// Creates an instance of .
public HttpApiResponseException(string message,
HttpResponseMessage response,
diff --git a/src/Tingle.Extensions.Http/IServiceCollectionExtensions.cs b/src/Tingle.Extensions.Http/IServiceCollectionExtensions.cs
index 9b50333..531caec 100644
--- a/src/Tingle.Extensions.Http/IServiceCollectionExtensions.cs
+++ b/src/Tingle.Extensions.Http/IServiceCollectionExtensions.cs
@@ -1,4 +1,5 @@
-using System.Net.Http.Headers;
+using System.Diagnostics.CodeAnalysis;
+using System.Net.Http.Headers;
using Tingle.Extensions.Http;
namespace Microsoft.Extensions.DependencyInjection;
@@ -14,8 +15,9 @@ public static class IServiceCollectionExtensions
/// The client type. The type specified will be registered in the service collection as a transient service.
/// The options type.
/// An that can be used to configure the client.
- public static IHttpClientBuilder AddHttpApiClient(this IServiceCollection services,
- Action? configure = null)
+ public static IHttpClientBuilder AddHttpApiClient<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TClient, TOptions>(
+ this IServiceCollection services,
+ Action? configure = null)
where TClient : AbstractHttpApiClient
where TOptions : AbstractHttpApiClientOptions, new()
{
@@ -40,8 +42,9 @@ public static IHttpClientBuilder AddHttpApiClient(this IServi
/// The client implementation type. The type specified will be registered in the service collection as a transient service.
/// The options type.
/// An that can be used to configure the client.
- public static IHttpClientBuilder AddHttpApiClient(this IServiceCollection services,
- Action? configure = null)
+ public static IHttpClientBuilder AddHttpApiClient(
+ this IServiceCollection services,
+ Action? configure = null)
where TClient : class
where TImplementation : AbstractHttpApiClient, TClient
where TOptions : AbstractHttpApiClientOptions, new()
diff --git a/src/Tingle.Extensions.Http/Tingle.Extensions.Http.csproj b/src/Tingle.Extensions.Http/Tingle.Extensions.Http.csproj
index 79dd566..d98632e 100644
--- a/src/Tingle.Extensions.Http/Tingle.Extensions.Http.csproj
+++ b/src/Tingle.Extensions.Http/Tingle.Extensions.Http.csproj
@@ -9,8 +9,8 @@
-
-
+
+
diff --git a/src/Tingle.Extensions.JsonPatch/Tingle.Extensions.JsonPatch.csproj b/src/Tingle.Extensions.JsonPatch/Tingle.Extensions.JsonPatch.csproj
index db8713b..aa5ea18 100644
--- a/src/Tingle.Extensions.JsonPatch/Tingle.Extensions.JsonPatch.csproj
+++ b/src/Tingle.Extensions.JsonPatch/Tingle.Extensions.JsonPatch.csproj
@@ -27,8 +27,8 @@
$(PackageTags);jsonpatch;patch;json
-
-
+
+
diff --git a/src/Tingle.Extensions.PhoneValidators/Tingle.Extensions.PhoneValidators.csproj b/src/Tingle.Extensions.PhoneValidators/Tingle.Extensions.PhoneValidators.csproj
index e0046e4..6fafc0a 100644
--- a/src/Tingle.Extensions.PhoneValidators/Tingle.Extensions.PhoneValidators.csproj
+++ b/src/Tingle.Extensions.PhoneValidators/Tingle.Extensions.PhoneValidators.csproj
@@ -8,12 +8,12 @@
$(PackageTags);validation;dataannotations;phonevalidators;phones
-
+
-
+
diff --git a/src/Tingle.Extensions.PushNotifications/Apple/Models/ApnsErrorReason.cs b/src/Tingle.Extensions.PushNotifications/Apple/Models/ApnsErrorReason.cs
index 44a320f..35bca15 100644
--- a/src/Tingle.Extensions.PushNotifications/Apple/Models/ApnsErrorReason.cs
+++ b/src/Tingle.Extensions.PushNotifications/Apple/Models/ApnsErrorReason.cs
@@ -5,7 +5,7 @@ namespace Tingle.Extensions.PushNotifications.Apple.Models;
///
/// Represents a reason why an APNs request failed
///
-[JsonConverter(typeof(JsonStringEnumConverter))]
+[JsonConverter(typeof(JsonStringEnumConverter))]
public enum ApnsErrorReason
{
///
diff --git a/src/Tingle.Extensions.PushNotifications/FcmLegacy/Models/FcmLegacyErrorCode.cs b/src/Tingle.Extensions.PushNotifications/FcmLegacy/Models/FcmLegacyErrorCode.cs
index 94c9802..3d9806d 100644
--- a/src/Tingle.Extensions.PushNotifications/FcmLegacy/Models/FcmLegacyErrorCode.cs
+++ b/src/Tingle.Extensions.PushNotifications/FcmLegacy/Models/FcmLegacyErrorCode.cs
@@ -5,7 +5,7 @@ namespace Tingle.Extensions.PushNotifications.FcmLegacy.Models;
///
/// Represents a reason why an FCM request failed in the legacy HTTP API.
///
-[JsonConverter(typeof(JsonStringEnumConverter))]
+[JsonConverter(typeof(JsonStringEnumConverter))]
public enum FcmLegacyErrorCode
{
///
diff --git a/src/Tingle.Extensions.PushNotifications/FcmLegacy/Models/FcmLegacyPriority.cs b/src/Tingle.Extensions.PushNotifications/FcmLegacy/Models/FcmLegacyPriority.cs
index dc6a3dc..53e45ae 100644
--- a/src/Tingle.Extensions.PushNotifications/FcmLegacy/Models/FcmLegacyPriority.cs
+++ b/src/Tingle.Extensions.PushNotifications/FcmLegacy/Models/FcmLegacyPriority.cs
@@ -5,7 +5,7 @@ namespace Tingle.Extensions.PushNotifications.FcmLegacy.Models;
///
/// Represents the priority of an FCM request in the legacy HTTP API.
///
-[JsonConverter(typeof(JsonStringEnumConverter))]
+[JsonConverter(typeof(JsonStringEnumConverter))]
public enum FcmLegacyPriority
{
///
diff --git a/src/Tingle.Extensions.PushNotifications/Firebase/Models/FirebaseErrorCode.cs b/src/Tingle.Extensions.PushNotifications/Firebase/Models/FirebaseErrorCode.cs
index 1979a8f..e816a44 100644
--- a/src/Tingle.Extensions.PushNotifications/Firebase/Models/FirebaseErrorCode.cs
+++ b/src/Tingle.Extensions.PushNotifications/Firebase/Models/FirebaseErrorCode.cs
@@ -5,7 +5,7 @@ namespace Tingle.Extensions.PushNotifications.FcmLegacy.Models;
///
/// Represents a reason why an FCM request failed.
///
-[JsonConverter(typeof(JsonStringEnumConverter))]
+[JsonConverter(typeof(JsonStringEnumConverter))]
public enum FirebaseErrorCode
{
///
diff --git a/src/Tingle.Extensions.PushNotifications/Firebase/Models/FirebaseMessageAndroidNotificationPriority.cs b/src/Tingle.Extensions.PushNotifications/Firebase/Models/FirebaseMessageAndroidNotificationPriority.cs
index 073594c..56d6c97 100644
--- a/src/Tingle.Extensions.PushNotifications/Firebase/Models/FirebaseMessageAndroidNotificationPriority.cs
+++ b/src/Tingle.Extensions.PushNotifications/Firebase/Models/FirebaseMessageAndroidNotificationPriority.cs
@@ -3,7 +3,7 @@
namespace Tingle.Extensions.PushNotifications.Firebase.Models;
///
-[JsonConverter(typeof(JsonStringEnumConverter))]
+[JsonConverter(typeof(JsonStringEnumConverter))]
public enum FirebaseMessageAndroidNotificationPriority
{
///
diff --git a/src/Tingle.Extensions.PushNotifications/Firebase/Models/FirebaseMessageAndroidPriority.cs b/src/Tingle.Extensions.PushNotifications/Firebase/Models/FirebaseMessageAndroidPriority.cs
index 853008d..83d3253 100644
--- a/src/Tingle.Extensions.PushNotifications/Firebase/Models/FirebaseMessageAndroidPriority.cs
+++ b/src/Tingle.Extensions.PushNotifications/Firebase/Models/FirebaseMessageAndroidPriority.cs
@@ -3,7 +3,7 @@
namespace Tingle.Extensions.PushNotifications.Firebase.Models;
///
-[JsonConverter(typeof(JsonStringEnumConverter))]
+[JsonConverter(typeof(JsonStringEnumConverter))]
public enum FirebaseMessageAndroidPriority
{
///
diff --git a/src/Tingle.Extensions.PushNotifications/Firebase/Models/FirebaseMessageAndroidVisibility.cs b/src/Tingle.Extensions.PushNotifications/Firebase/Models/FirebaseMessageAndroidVisibility.cs
index d171d12..977c86e 100644
--- a/src/Tingle.Extensions.PushNotifications/Firebase/Models/FirebaseMessageAndroidVisibility.cs
+++ b/src/Tingle.Extensions.PushNotifications/Firebase/Models/FirebaseMessageAndroidVisibility.cs
@@ -3,7 +3,7 @@
namespace Tingle.Extensions.PushNotifications.Firebase.Models;
///
-[JsonConverter(typeof(JsonStringEnumConverter))]
+[JsonConverter(typeof(JsonStringEnumConverter))]
public enum FirebaseMessageAndroidVisibility
{
///
diff --git a/src/Tingle.Extensions.PushNotifications/Tingle.Extensions.PushNotifications.csproj b/src/Tingle.Extensions.PushNotifications/Tingle.Extensions.PushNotifications.csproj
index b7d338a..3fba5a8 100644
--- a/src/Tingle.Extensions.PushNotifications/Tingle.Extensions.PushNotifications.csproj
+++ b/src/Tingle.Extensions.PushNotifications/Tingle.Extensions.PushNotifications.csproj
@@ -14,7 +14,7 @@
-
+
diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props
index 58bf8ce..7f5a969 100644
--- a/tests/Directory.Build.props
+++ b/tests/Directory.Build.props
@@ -19,8 +19,4 @@
-
-
-
-
diff --git a/tests/Tingle.AspNetCore.Authentication.Tests/SharedAuthenticationTests.cs b/tests/Tingle.AspNetCore.Authentication.Tests/SharedAuthenticationTests.cs
index 10315fc..c28a356 100644
--- a/tests/Tingle.AspNetCore.Authentication.Tests/SharedAuthenticationTests.cs
+++ b/tests/Tingle.AspNetCore.Authentication.Tests/SharedAuthenticationTests.cs
@@ -9,8 +9,6 @@ namespace Tingle.AspNetCore.Authentication.Tests;
public abstract class SharedAuthenticationTests where TOptions : AuthenticationSchemeOptions
{
- protected TestClock Clock { get; } = new TestClock();
-
protected abstract string DefaultScheme { get; }
protected virtual string DisplayName { get; }
protected abstract Type HandlerType { get; }
diff --git a/tests/Tingle.AspNetCore.Authentication.Tests/TestAuthHandler.cs b/tests/Tingle.AspNetCore.Authentication.Tests/TestAuthHandler.cs
index eeb35d8..3c3d799 100644
--- a/tests/Tingle.AspNetCore.Authentication.Tests/TestAuthHandler.cs
+++ b/tests/Tingle.AspNetCore.Authentication.Tests/TestAuthHandler.cs
@@ -11,8 +11,12 @@ namespace Tingle.AspNetCore.Authentication.Tests;
public class TestAuthHandler : AuthenticationHandler, IAuthenticationSignInHandler
{
- public TestAuthHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
- { }
+#if NET8_0_OR_GREATER
+ public TestAuthHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder) : base(options, logger, encoder) { }
+#else
+ [Obsolete("ISystemClock is obsolete, use TimeProvider on AuthenticationSchemeOptions instead.")]
+ public TestAuthHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) { }
+#endif
public int SignInCount { get; set; }
public int SignOutCount { get; set; }
diff --git a/tests/Tingle.AspNetCore.Authentication.Tests/TestClock.cs b/tests/Tingle.AspNetCore.Authentication.Tests/TestClock.cs
deleted file mode 100644
index 6eff40f..0000000
--- a/tests/Tingle.AspNetCore.Authentication.Tests/TestClock.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using Microsoft.AspNetCore.Authentication;
-
-namespace Tingle.AspNetCore.Authentication.Tests;
-
-public class TestClock : ISystemClock
-{
- public TestClock()
- {
- UtcNow = new DateTimeOffset(2013, 6, 11, 12, 34, 56, 789, TimeSpan.Zero);
- }
-
- public DateTimeOffset UtcNow { get; set; }
-
- public void Add(TimeSpan timeSpan)
- {
- UtcNow = UtcNow + timeSpan;
- }
-}
diff --git a/tests/Tingle.AspNetCore.Authentication.Tests/Tingle.AspNetCore.Authentication.Tests.csproj b/tests/Tingle.AspNetCore.Authentication.Tests/Tingle.AspNetCore.Authentication.Tests.csproj
index 8f5d227..849e8da 100644
--- a/tests/Tingle.AspNetCore.Authentication.Tests/Tingle.AspNetCore.Authentication.Tests.csproj
+++ b/tests/Tingle.AspNetCore.Authentication.Tests/Tingle.AspNetCore.Authentication.Tests.csproj
@@ -1,6 +1,9 @@
-
+
+
+
+
diff --git a/tests/Tingle.AspNetCore.Authorization.Tests/ApprovedIPNetworksTests.cs b/tests/Tingle.AspNetCore.Authorization.Tests/ApprovedIPNetworksTests.cs
index 656600b..641a426 100644
--- a/tests/Tingle.AspNetCore.Authorization.Tests/ApprovedIPNetworksTests.cs
+++ b/tests/Tingle.AspNetCore.Authorization.Tests/ApprovedIPNetworksTests.cs
@@ -12,13 +12,16 @@ public class ApprovedIPNetworksTests
[InlineData(false, "127.0.1.1", "127.0.0.1/32,::1/128")]
[InlineData(false, "127.0.1.1", "192.201.214.0/24,::1/128")]
[InlineData(false, "30.0.0.21", "192.201.214.0/24")]
- [InlineData(false, "2001:0000:0000:1234:abcd:ffff:c0a8:0101", "2002::1234:abcd:ffff:c0a8:101/64")]
[InlineData(true, "207.154.225.144", "207.154.225.144/32")]
[InlineData(true, "196.201.214.94", "196.201.214.0/24")]
[InlineData(true, "196.201.214.94", "196.201.214.0/24,30.0.0.0/27")]
[InlineData(true, "30.0.0.21", "196.201.214.0/24,30.0.0.0/27")]
[InlineData(true, "::ffff:196.201.214.127", "196.201.214.0/24")] // IPv4 mapped to IPv6
+ // TODO: remove this once the inbuilt implementation support IPv6
+#if !NET8_0_OR_GREATER
+ [InlineData(false, "2001:0000:0000:1234:abcd:ffff:c0a8:0101", "2002::1234:abcd:ffff:c0a8:101/64")]
[InlineData(true, "2002:0000:0000:1234:abcd:ffff:c0a8:0101", "2002::1234:abcd:ffff:c0a8:101/64")]
+#endif
public void IsApproved_Works(bool expected, string test, string networks)
{
var builder = new AuthorizationPolicyBuilder();
diff --git a/tests/Tingle.Extensions.DataAnnotations.Tests/AllowedValuesAttributeTests.cs b/tests/Tingle.Extensions.DataAnnotations.Tests/AllowedValuesAttributeTests.cs
index ca07fad..c5fa211 100644
--- a/tests/Tingle.Extensions.DataAnnotations.Tests/AllowedValuesAttributeTests.cs
+++ b/tests/Tingle.Extensions.DataAnnotations.Tests/AllowedValuesAttributeTests.cs
@@ -1,4 +1,5 @@
-using System.ComponentModel.DataAnnotations;
+#if !NET8_0_OR_GREATER
+using System.ComponentModel.DataAnnotations;
namespace Tingle.Extensions.DataAnnotations.Tests;
@@ -159,3 +160,4 @@ record TestModel6([property: AllowedValues(1, 2, 3, 4, 5)] int? SomeIntValue,
[property: AllowedValues("blue", "green", "yellow")] string? SomeStringValue,
[property: AllowedValues("blue", "green", "yellow")] List? SomeStringValues);
}
+#endif
diff --git a/tests/Tingle.Extensions.Http.Authentication.Tests/Tingle.Extensions.Http.Authentication.Tests.csproj b/tests/Tingle.Extensions.Http.Authentication.Tests/Tingle.Extensions.Http.Authentication.Tests.csproj
index c213683..0976e58 100644
--- a/tests/Tingle.Extensions.Http.Authentication.Tests/Tingle.Extensions.Http.Authentication.Tests.csproj
+++ b/tests/Tingle.Extensions.Http.Authentication.Tests/Tingle.Extensions.Http.Authentication.Tests.csproj
@@ -1,7 +1,7 @@
-
+
diff --git a/tests/Tingle.Extensions.PhoneValidators.Tests/Tingle.Extensions.PhoneValidators.Tests.csproj b/tests/Tingle.Extensions.PhoneValidators.Tests/Tingle.Extensions.PhoneValidators.Tests.csproj
index 8146dd5..7027216 100644
--- a/tests/Tingle.Extensions.PhoneValidators.Tests/Tingle.Extensions.PhoneValidators.Tests.csproj
+++ b/tests/Tingle.Extensions.PhoneValidators.Tests/Tingle.Extensions.PhoneValidators.Tests.csproj
@@ -1,7 +1,7 @@
-
+
diff --git a/tests/Tingle.Extensions.PushNotifications.Tests/Tingle.Extensions.PushNotifications.Tests.csproj b/tests/Tingle.Extensions.PushNotifications.Tests/Tingle.Extensions.PushNotifications.Tests.csproj
index 0935524..c43842c 100644
--- a/tests/Tingle.Extensions.PushNotifications.Tests/Tingle.Extensions.PushNotifications.Tests.csproj
+++ b/tests/Tingle.Extensions.PushNotifications.Tests/Tingle.Extensions.PushNotifications.Tests.csproj
@@ -5,10 +5,10 @@
-
-
-
-
+
+
+
+