We strive to eliminate as much boilerplate as possible by offering out-of-the-box features such as sorting, filtering and pagination.
++ The ultimate goal of this library is to eliminate as much boilerplate as possible by offering out-of-the-box features, such as sorting, filtering, pagination, sparse fieldset selection, and side-loading related resources. +
Order resources on one or multiple attributes using the sort
query string parameter
Order resources on multiple attributes using the sort
query string parameter
-#nullable enable
+#nullable enable
public class Article : Identifiable<long>
{
@@ -213,7 +215,7 @@ Resource
Request
- GET /articles?filter=contains(summary,'web')&sort=-lastModifiedAt&fields[articles]=title,summary&include=author HTTP/1.1
+ GET /articles?filter=contains(summary,'web')&sort=-lastModifiedAt&fields[articles]=title,summary&include=author HTTP/1.1
-{
+{
"meta": {
"totalResources": 1
},
"links": {
- "self": "/articles?filter=contains(summary,'web')&sort=-lastModifiedAt&fields%5Barticles%5D=title,summary&include=author",
- "first": "/articles?filter=contains(summary,'web')&sort=-lastModifiedAt&fields%5Barticles%5D=title,summary&include=author",
- "last": "/articles?filter=contains(summary,'web')&sort=-lastModifiedAt&fields%5Barticles%5D=title,summary&include=author"
+ "self": "/articles?filter=contains(summary,'web')&sort=-lastModifiedAt&fields%5Barticles%5D=title,summary&include=author",
+ "first": "/articles?filter=contains(summary,'web')&sort=-lastModifiedAt&fields%5Barticles%5D=title,summary&include=author",
+ "last": "/articles?filter=contains(summary,'web')&sort=-lastModifiedAt&fields%5Barticles%5D=title,summary&include=author"
},
"data": [
{
diff --git a/docs/usage/meta.md b/docs/usage/meta.md
index a115e25740..674d39413b 100644
--- a/docs/usage/meta.md
+++ b/docs/usage/meta.md
@@ -60,7 +60,7 @@ public class PersonDefinition : JsonApiResourceDefinition
{
return new Dictionary
{
- ["notice"] = "Check our intranet at http://www.example.com/employees/" +
+ ["notice"] = "Check our intranet at https://www.example.com/employees/" +
$"{person.StringId} for personal details."
};
}
@@ -80,7 +80,7 @@ public class PersonDefinition : JsonApiResourceDefinition
...
},
"meta": {
- "notice": "Check our intranet at http://www.example.com/employees/1 for personal details."
+ "notice": "Check our intranet at https://www.example.com/employees/1 for personal details."
}
}
]
diff --git a/docs/usage/openapi-client.md b/docs/usage/openapi-client.md
index c0717d47ca..58b9ca87e9 100644
--- a/docs/usage/openapi-client.md
+++ b/docs/usage/openapi-client.md
@@ -19,7 +19,7 @@ For C# clients, we provide an additional package that provides workarounds for b
To add it to your project, run the following command:
```
-dotnet add package JsonApiDotNetCore.OpenApi.Client.NSwag
+dotnet add package JsonApiDotNetCore.OpenApi.Client.NSwag --prerelease
```
# [Kiota](#tab/kiota)
@@ -28,7 +28,7 @@ For C# clients, we provide an additional package that provides workarounds for b
To add it to your project, run the following command:
```
-dotnet add package JsonApiDotNetCore.OpenApi.Client.Kiota
+dotnet add package JsonApiDotNetCore.OpenApi.Client.Kiota --prerelease
```
---
@@ -60,7 +60,7 @@ The following steps describe how to generate and use a JSON:API client in C#, co
1. Add our client package to your project:
```
- dotnet add package JsonApiDotNetCore.OpenApi.Client.NSwag
+ dotnet add package JsonApiDotNetCore.OpenApi.Client.NSwag --prerelease
```
1. Add code that calls one of your JSON:API endpoints.
diff --git a/docs/usage/openapi.md b/docs/usage/openapi.md
index e49f120a14..83f3ce8a3b 100644
--- a/docs/usage/openapi.md
+++ b/docs/usage/openapi.md
@@ -15,13 +15,9 @@ provides OpenAPI support for JSON:API by integrating with [Swashbuckle](https://
1. Install the `JsonApiDotNetCore.OpenApi.Swashbuckle` NuGet package:
```
- dotnet add package JsonApiDotNetCore.OpenApi.Swashbuckle
+ dotnet add package JsonApiDotNetCore.OpenApi.Swashbuckle --prerelease
```
- > [!NOTE]
- > Because this package is still experimental, it's not yet available on NuGet.
- > Use the steps [here](https://github.com/json-api-dotnet/JsonApiDotNetCore?tab=readme-ov-file#trying-out-the-latest-build) to install.
-
2. Add the JSON:API support to your `Program.cs` file.
```c#
diff --git a/src/Examples/DapperExample/Properties/launchSettings.json b/src/Examples/DapperExample/Properties/launchSettings.json
index 137620d860..0d86e8f61a 100644
--- a/src/Examples/DapperExample/Properties/launchSettings.json
+++ b/src/Examples/DapperExample/Properties/launchSettings.json
@@ -1,5 +1,5 @@
{
- "$schema": "http://json.schemastore.org/launchsettings.json",
+ "$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
diff --git a/src/Examples/DatabasePerTenantExample/Properties/launchSettings.json b/src/Examples/DatabasePerTenantExample/Properties/launchSettings.json
index 1ab75296f7..43ae84e51e 100644
--- a/src/Examples/DatabasePerTenantExample/Properties/launchSettings.json
+++ b/src/Examples/DatabasePerTenantExample/Properties/launchSettings.json
@@ -1,5 +1,5 @@
{
- "$schema": "http://json.schemastore.org/launchsettings.json",
+ "$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
diff --git a/src/Examples/GettingStarted/Properties/launchSettings.json b/src/Examples/GettingStarted/Properties/launchSettings.json
index d806502bcd..304c377082 100644
--- a/src/Examples/GettingStarted/Properties/launchSettings.json
+++ b/src/Examples/GettingStarted/Properties/launchSettings.json
@@ -1,5 +1,5 @@
{
- "$schema": "http://json.schemastore.org/launchsettings.json",
+ "$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
diff --git a/src/Examples/GettingStarted/README.md b/src/Examples/GettingStarted/README.md
index 8d8da60bc8..4d94ffd825 100644
--- a/src/Examples/GettingStarted/README.md
+++ b/src/Examples/GettingStarted/README.md
@@ -7,8 +7,7 @@
You can verify the project is running by checking this endpoint:
`localhost:14141/api/people`
-For further documentation and implementation of a JsonApiDotNetCore Application see the documentation or GitHub page:
+For further documentation and implementation of a JsonApiDotNetCore application, see the documentation or GitHub page:
Repository: https://github.com/json-api-dotnet/JsonApiDotNetCore
-
Documentation: https://www.jsonapi.net
diff --git a/src/Examples/JsonApiDotNetCoreExample/Program.cs b/src/Examples/JsonApiDotNetCoreExample/Program.cs
index d2677ea781..56448b271e 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Program.cs
+++ b/src/Examples/JsonApiDotNetCoreExample/Program.cs
@@ -79,9 +79,7 @@ static void ConfigureServices(WebApplicationBuilder builder)
using (CodeTimingSessionManager.Current.Measure("AddOpenApiForJsonApi()"))
{
-#pragma warning disable JADNC_OA_001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
builder.Services.AddOpenApiForJsonApi(options => options.DocumentFilter());
-#pragma warning restore JADNC_OA_001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
}
}
diff --git a/src/Examples/JsonApiDotNetCoreExample/Properties/launchSettings.json b/src/Examples/JsonApiDotNetCoreExample/Properties/launchSettings.json
index 82b89e1843..7c4189f272 100644
--- a/src/Examples/JsonApiDotNetCoreExample/Properties/launchSettings.json
+++ b/src/Examples/JsonApiDotNetCoreExample/Properties/launchSettings.json
@@ -1,5 +1,5 @@
{
- "$schema": "http://json.schemastore.org/launchsettings.json",
+ "$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
diff --git a/src/Examples/MultiDbContextExample/Properties/launchSettings.json b/src/Examples/MultiDbContextExample/Properties/launchSettings.json
index 9d3467265f..2cb2d59cae 100644
--- a/src/Examples/MultiDbContextExample/Properties/launchSettings.json
+++ b/src/Examples/MultiDbContextExample/Properties/launchSettings.json
@@ -1,5 +1,5 @@
{
- "$schema": "http://json.schemastore.org/launchsettings.json",
+ "$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
diff --git a/src/Examples/NoEntityFrameworkExample/Properties/launchSettings.json b/src/Examples/NoEntityFrameworkExample/Properties/launchSettings.json
index d1e2e0ca67..e5d1b8837c 100644
--- a/src/Examples/NoEntityFrameworkExample/Properties/launchSettings.json
+++ b/src/Examples/NoEntityFrameworkExample/Properties/launchSettings.json
@@ -1,5 +1,5 @@
{
- "$schema": "http://json.schemastore.org/launchsettings.json",
+ "$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
diff --git a/src/Examples/OpenApiKiotaClientExample/Properties/launchSettings.json b/src/Examples/OpenApiKiotaClientExample/Properties/launchSettings.json
index afb5e5dac4..142f412e8a 100644
--- a/src/Examples/OpenApiKiotaClientExample/Properties/launchSettings.json
+++ b/src/Examples/OpenApiKiotaClientExample/Properties/launchSettings.json
@@ -1,5 +1,5 @@
{
- "$schema": "http://json.schemastore.org/launchsettings.json",
+ "$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"Kestrel": {
"commandName": "Project",
diff --git a/src/Examples/OpenApiNSwagClientExample/Properties/launchSettings.json b/src/Examples/OpenApiNSwagClientExample/Properties/launchSettings.json
index afb5e5dac4..142f412e8a 100644
--- a/src/Examples/OpenApiNSwagClientExample/Properties/launchSettings.json
+++ b/src/Examples/OpenApiNSwagClientExample/Properties/launchSettings.json
@@ -1,5 +1,5 @@
{
- "$schema": "http://json.schemastore.org/launchsettings.json",
+ "$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"Kestrel": {
"commandName": "Project",
diff --git a/src/Examples/ReportsExample/Properties/launchSettings.json b/src/Examples/ReportsExample/Properties/launchSettings.json
index 7add074ef2..83e6baea4c 100644
--- a/src/Examples/ReportsExample/Properties/launchSettings.json
+++ b/src/Examples/ReportsExample/Properties/launchSettings.json
@@ -1,5 +1,5 @@
{
- "$schema": "http://json.schemastore.org/launchsettings.json",
+ "$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
diff --git a/src/JsonApiDotNetCore.Annotations/CollectionConverter.cs b/src/JsonApiDotNetCore.Annotations/CollectionConverter.cs
index cbf834b630..683e34764b 100644
--- a/src/JsonApiDotNetCore.Annotations/CollectionConverter.cs
+++ b/src/JsonApiDotNetCore.Annotations/CollectionConverter.cs
@@ -104,17 +104,26 @@ public IReadOnlyCollection ExtractResources(object? value)
///
public Type? FindCollectionElementType(Type? type)
{
- if (type is { IsGenericType: true, GenericTypeArguments.Length: 1 })
+ if (type != null)
{
- if (type.IsOrImplementsInterface())
+ Type? enumerableClosedType = IsEnumerableClosedType(type) ? type : null;
+ enumerableClosedType ??= type.GetInterfaces().FirstOrDefault(IsEnumerableClosedType);
+
+ if (enumerableClosedType != null)
{
- return type.GenericTypeArguments[0];
+ return enumerableClosedType.GenericTypeArguments[0];
}
}
return null;
}
+ private static bool IsEnumerableClosedType(Type type)
+ {
+ bool isClosedType = type is { IsGenericType: true, ContainsGenericParameters: false };
+ return isClosedType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>);
+ }
+
///
/// Indicates whether a instance can be assigned to the specified type, for example:
///
jsonapidotnetcore;jsonapi;json:api;dotnet;asp.net;rest;web-api
- Annotations for JsonApiDotNetCore, a framework for building JSON:API compliant REST APIs using ASP.NET and Entity Framework Core.
+ Annotations for JsonApiDotNetCore, which is a framework for building JSON:API compliant REST APIs using ASP.NET Core and Entity Framework Core.
json-api-dotnet
https://www.jsonapi.net/
MIT
diff --git a/src/JsonApiDotNetCore.OpenApi.Client.Kiota/Build/JsonApiDotNetCore.OpenApi.Client.Kiota.targets b/src/JsonApiDotNetCore.OpenApi.Client.Kiota/Build/JsonApiDotNetCore.OpenApi.Client.Kiota.targets
index 72b32aa7a5..44586a10ae 100644
--- a/src/JsonApiDotNetCore.OpenApi.Client.Kiota/Build/JsonApiDotNetCore.OpenApi.Client.Kiota.targets
+++ b/src/JsonApiDotNetCore.OpenApi.Client.Kiota/Build/JsonApiDotNetCore.OpenApi.Client.Kiota.targets
@@ -149,8 +149,8 @@
-
+
<_WildcardGroup Include="%2A%2A/%2A.cs">
%(KiotaReference._NonEmptyOutputPath)
diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiDotNetCore.OpenApi.Swashbuckle.csproj b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiDotNetCore.OpenApi.Swashbuckle.csproj
index 89822ff4b3..4a57ca1c85 100644
--- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiDotNetCore.OpenApi.Swashbuckle.csproj
+++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/JsonApiDotNetCore.OpenApi.Swashbuckle.csproj
@@ -11,7 +11,7 @@
$(VersionPrefix)-preview.$(OpenApiPreviewNumber)
jsonapidotnetcore;jsonapi;json:api;dotnet;asp.net;rest;web-api;openapi;swagger;swaggerui;swashbuckle
- A Swashbuckle integration that enables you to describe a JsonApiDotNetCore API with an OpenAPI specification.
+ Provides OpenAPI document generation for JsonApiDotNetCore APIs by using Swashbuckle.
json-api-dotnet
https://www.jsonapi.net/
MIT
diff --git a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ServiceCollectionExtensions.cs b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ServiceCollectionExtensions.cs
index df5247d9de..3b421c31db 100644
--- a/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ServiceCollectionExtensions.cs
+++ b/src/JsonApiDotNetCore.OpenApi.Swashbuckle/ServiceCollectionExtensions.cs
@@ -1,4 +1,3 @@
-using System.Diagnostics.CodeAnalysis;
using JsonApiDotNetCore.Configuration;
using JsonApiDotNetCore.Middleware;
using JsonApiDotNetCore.OpenApi.Swashbuckle.JsonApiMetadata;
@@ -21,7 +20,6 @@ public static class ServiceCollectionExtensions
///
/// Configures OpenAPI for JsonApiDotNetCore using Swashbuckle.
///
- [Experimental("JADNC_OA_001", UrlFormat = "https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/docs/usage/openapi.md")]
public static void AddOpenApiForJsonApi(this IServiceCollection services, Action? configureSwaggerGenOptions = null)
{
ArgumentNullException.ThrowIfNull(services);
diff --git a/src/JsonApiDotNetCore.SourceGenerators/JsonApiDotNetCore.SourceGenerators.csproj b/src/JsonApiDotNetCore.SourceGenerators/JsonApiDotNetCore.SourceGenerators.csproj
index 8f9e397df3..db6f039bd1 100644
--- a/src/JsonApiDotNetCore.SourceGenerators/JsonApiDotNetCore.SourceGenerators.csproj
+++ b/src/JsonApiDotNetCore.SourceGenerators/JsonApiDotNetCore.SourceGenerators.csproj
@@ -12,7 +12,7 @@
jsonapidotnetcore;jsonapi;json:api;dotnet;asp.net;rest;web-api
- Source generators for JsonApiDotNetCore, a framework for building JSON:API compliant REST APIs using ASP.NET and Entity Framework Core.
+ Source generators for JsonApiDotNetCore, which is a framework for building JSON:API compliant REST APIs using ASP.NET Core and Entity Framework Core.
json-api-dotnet
https://www.jsonapi.net/
MIT
diff --git a/src/JsonApiDotNetCore/Configuration/ResourceGraphBuilder.cs b/src/JsonApiDotNetCore/Configuration/ResourceGraphBuilder.cs
index 7cdf04404b..fcf18f97a1 100644
--- a/src/JsonApiDotNetCore/Configuration/ResourceGraphBuilder.cs
+++ b/src/JsonApiDotNetCore/Configuration/ResourceGraphBuilder.cs
@@ -396,8 +396,8 @@ private ReadOnlyCollection GetEagerLoads(Type resourceClrTyp
continue;
}
- Type innerType = TypeOrElementType(property.PropertyType);
- eagerLoad.Children = GetEagerLoads(innerType, recursionDepth + 1);
+ Type rightType = CollectionConverter.Instance.FindCollectionElementType(property.PropertyType) ?? property.PropertyType;
+ eagerLoad.Children = GetEagerLoads(rightType, recursionDepth + 1);
eagerLoad.Property = property;
eagerLoads.Add(eagerLoad);
@@ -459,14 +459,6 @@ private static void AssertNoInfiniteRecursion(int recursionDepth)
}
}
- private Type TypeOrElementType(Type type)
- {
- Type[] interfaces = type.GetInterfaces().Where(@interface => @interface.IsGenericType && @interface.GetGenericTypeDefinition() == typeof(IEnumerable<>))
- .ToArray();
-
- return interfaces.Length == 1 ? interfaces.Single().GenericTypeArguments[0] : type;
- }
-
private string FormatResourceName(Type resourceClrType)
{
var formatter = new ResourceNameFormatter(_options.SerializerOptions.PropertyNamingPolicy);
diff --git a/src/JsonApiDotNetCore/Configuration/TypeLocator.cs b/src/JsonApiDotNetCore/Configuration/TypeLocator.cs
index 6b8c545744..768f94a98d 100644
--- a/src/JsonApiDotNetCore/Configuration/TypeLocator.cs
+++ b/src/JsonApiDotNetCore/Configuration/TypeLocator.cs
@@ -82,8 +82,16 @@ internal sealed class TypeLocator
$"instead of {interfaceTypeArguments.Length}.", nameof(interfaceTypeArguments));
}
- return assembly.GetTypes().Select(type => GetContainerRegistrationFromType(type, unboundInterface, interfaceTypeArguments))
+ // @formatter:wrap_chained_method_calls chop_always
+ // @formatter:wrap_before_first_method_call true
+
+ return assembly
+ .GetTypes()
+ .Select(type => GetContainerRegistrationFromType(type, unboundInterface, interfaceTypeArguments))
.FirstOrDefault(result => result != null);
+
+ // @formatter:wrap_before_first_method_call restore
+ // @formatter:wrap_chained_method_calls restore
}
private static (Type implementationType, Type serviceInterface)? GetContainerRegistrationFromType(Type nextType, Type unboundInterface,
diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
index 1c1ba7ab7f..d36600e878 100644
--- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
+++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj
@@ -9,7 +9,7 @@
jsonapidotnetcore;jsonapi;json:api;dotnet;asp.net;rest;web-api
- A framework for building JSON:API compliant REST APIs using ASP.NET and Entity Framework Core. Includes support for Atomic Operations. The ultimate goal of this library is to eliminate as much boilerplate as possible by offering out-of-the-box features such as sorting, filtering and pagination. You just need to focus on defining the resources and implementing your custom business logic. This library has been designed around dependency injection making extensibility incredibly easy.
+ A framework for building JSON:API compliant REST APIs using ASP.NET Core and Entity Framework Core. Includes support for the Atomic Operations extension. The ultimate goal of this library is to eliminate as much boilerplate as possible by offering out-of-the-box features, such as sorting, filtering, pagination, sparse fieldset selection, and side-loading related resources. You just need to focus on defining the resources and implementing your custom business logic. This library has been designed around dependency injection, making extensibility incredibly easy.
json-api-dotnet
https://www.jsonapi.net/
MIT
diff --git a/src/JsonApiDotNetCore/Queries/Parsing/QueryTokenizer.cs b/src/JsonApiDotNetCore/Queries/Parsing/QueryTokenizer.cs
index 0c5f634375..0e1e7660a2 100644
--- a/src/JsonApiDotNetCore/Queries/Parsing/QueryTokenizer.cs
+++ b/src/JsonApiDotNetCore/Queries/Parsing/QueryTokenizer.cs
@@ -1,3 +1,4 @@
+using System.Collections.ObjectModel;
using System.Text;
using JetBrains.Annotations;
@@ -6,17 +7,18 @@ namespace JsonApiDotNetCore.Queries.Parsing;
[PublicAPI]
public sealed class QueryTokenizer
{
- public static readonly Dictionary SingleCharacterToTokenKinds = new()
- {
- ['('] = TokenKind.OpenParen,
- [')'] = TokenKind.CloseParen,
- ['['] = TokenKind.OpenBracket,
- [']'] = TokenKind.CloseBracket,
- ['.'] = TokenKind.Period,
- [','] = TokenKind.Comma,
- [':'] = TokenKind.Colon,
- ['-'] = TokenKind.Minus
- };
+ public static readonly IReadOnlyDictionary SingleCharacterToTokenKinds = new ReadOnlyDictionary(
+ new Dictionary
+ {
+ ['('] = TokenKind.OpenParen,
+ [')'] = TokenKind.CloseParen,
+ ['['] = TokenKind.OpenBracket,
+ [']'] = TokenKind.CloseBracket,
+ ['.'] = TokenKind.Period,
+ [','] = TokenKind.Comma,
+ [':'] = TokenKind.Colon,
+ ['-'] = TokenKind.Minus
+ });
private readonly string _source;
private readonly StringBuilder _textBuffer = new();
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Playlist.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Playlist.cs
index e8baf731d0..0d6409e761 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Playlist.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Playlist.cs
@@ -12,8 +12,8 @@ public sealed class Playlist : Identifiable
[Attr]
public string Name { get; set; } = null!;
- [NotMapped]
[Attr]
+ [NotMapped]
public bool IsArchived => false;
[HasMany]
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarCompositeKeyAwareRepository.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarCompositeKeyAwareRepository.cs
index 089f487908..d320c65d0f 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarCompositeKeyAwareRepository.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/CompositeKeys/CarCompositeKeyAwareRepository.cs
@@ -39,11 +39,21 @@ private void RecursiveRewriteFilterInLayer(QueryLayer queryLayer)
if (queryLayer.Selection is { IsEmpty: false })
{
- foreach (QueryLayer? nextLayer in queryLayer.Selection.GetResourceTypes().Select(queryLayer.Selection.GetOrCreateSelectors)
- .SelectMany(selectors => selectors.Select(selector => selector.Value).Where(layer => layer != null)))
+ // @formatter:wrap_chained_method_calls chop_always
+ // @formatter:keep_existing_linebreaks true
+
+ foreach (QueryLayer? nextLayer in queryLayer.Selection
+ .GetResourceTypes()
+ .Select(queryLayer.Selection.GetOrCreateSelectors)
+ .SelectMany(selectors => selectors
+ .Select(selector => selector.Value)
+ .Where(layer => layer != null)))
{
RecursiveRewriteFilterInLayer(nextLayer!);
}
+
+ // @formatter:keep_existing_linebreaks restore
+ // @formatter:wrap_chained_method_calls restore
}
}
}
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/Building.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/Building.cs
index ea3805cb22..78ab514636 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/Building.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/Building.cs
@@ -14,12 +14,12 @@ public sealed class Building : Identifiable
[Attr]
public string Number { get; set; } = null!;
- [NotMapped]
[Attr]
+ [NotMapped]
public int WindowCount => Windows.Count;
- [NotMapped]
[Attr(Capabilities = AttrCapabilities.AllowView | AttrCapabilities.AllowChange)]
+ [NotMapped]
public string PrimaryDoorColor
{
get
@@ -50,8 +50,8 @@ public string PrimaryDoorColor
}
}
- [NotMapped]
[Attr(Capabilities = AttrCapabilities.AllowView)]
+ [NotMapped]
public string? SecondaryDoorColor => SecondaryDoor?.Color;
[EagerLoad]
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/Street.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/Street.cs
index db440ad85d..263bb6cfd4 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/Street.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/Street.cs
@@ -12,16 +12,16 @@ public sealed class Street : Identifiable
[Attr]
public string Name { get; set; } = null!;
- [NotMapped]
[Attr(Capabilities = AttrCapabilities.AllowView)]
+ [NotMapped]
public int BuildingCount => Buildings.Count;
- [NotMapped]
[Attr(Capabilities = AttrCapabilities.AllowView)]
+ [NotMapped]
public int DoorTotalCount => Buildings.Sum(building => building.SecondaryDoor == null ? 1 : 2);
- [NotMapped]
[Attr(Capabilities = AttrCapabilities.AllowView)]
+ [NotMapped]
public int WindowTotalCount => Buildings.Sum(building => building.WindowCount);
[EagerLoad]
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/TopLevelCountTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/TopLevelCountTests.cs
index 5a72d4af80..aa4eb06598 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/TopLevelCountTests.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/Meta/TopLevelCountTests.cs
@@ -83,10 +83,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext =>
public async Task Renders_resource_count_for_empty_collection()
{
// Arrange
- await _testContext.RunOnDatabaseAsync(async dbContext =>
- {
- await dbContext.ClearTableAsync();
- });
+ await _testContext.RunOnDatabaseAsync(async dbContext => await dbContext.ClearTableAsync());
const string route = "/supportTickets";
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/WorkItem.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/WorkItem.cs
index c722592e83..baf2da12cf 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/WorkItem.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/WorkItem.cs
@@ -18,8 +18,8 @@ public sealed class WorkItem : Identifiable
[Attr]
public WorkItemPriority Priority { get; set; }
- [NotMapped]
[Attr(Capabilities = AttrCapabilities.All & ~(AttrCapabilities.AllowCreate | AttrCapabilities.AllowChange))]
+ [NotMapped]
public bool IsImportant
{
get => Priority == WorkItemPriority.High;
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/WorkItemGroup.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/WorkItemGroup.cs
index 7f132c8994..b5b94258f2 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/WorkItemGroup.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ReadWrite/WorkItemGroup.cs
@@ -15,8 +15,8 @@ public sealed class WorkItemGroup : Identifiable
[Attr]
public bool IsPublic { get; set; }
- [NotMapped]
[Attr]
+ [NotMapped]
public bool IsDeprecated => !string.IsNullOrEmpty(Name) && Name.StartsWith("DEPRECATED:", StringComparison.OrdinalIgnoreCase);
[HasOne]
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/Models/AlwaysMovingTandem.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/Models/AlwaysMovingTandem.cs
index 590e053339..c90aad6ade 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/Models/AlwaysMovingTandem.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ResourceInheritance/Models/AlwaysMovingTandem.cs
@@ -9,8 +9,8 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance.Models;
[Resource(ControllerNamespace = "JsonApiDotNetCoreTests.IntegrationTests.ResourceInheritance", GenerateControllerEndpoints = JsonApiEndpoints.None)]
public sealed class AlwaysMovingTandem : Bike
{
- [NotMapped]
[Attr]
+ [NotMapped]
public Guid LocationToken
{
get => Guid.NewGuid();
diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/Game.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/Game.cs
index 55372d4b0f..a983c66d7b 100644
--- a/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/Game.cs
+++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ZeroKeys/Game.cs
@@ -13,8 +13,8 @@ public sealed class Game : Identifiable
[Attr]
public string Title { get; set; } = null!;
- [NotMapped]
[Attr]
+ [NotMapped]
public Guid SessionToken => Guid.NewGuid();
[HasOne]
diff --git a/test/JsonApiDotNetCoreTests/UnitTests/TypeConversion/CollectionConverterTests.cs b/test/JsonApiDotNetCoreTests/UnitTests/TypeConversion/CollectionConverterTests.cs
new file mode 100644
index 0000000000..1f679912ba
--- /dev/null
+++ b/test/JsonApiDotNetCoreTests/UnitTests/TypeConversion/CollectionConverterTests.cs
@@ -0,0 +1,104 @@
+using FluentAssertions;
+using JsonApiDotNetCore;
+using Xunit;
+
+namespace JsonApiDotNetCoreTests.UnitTests.TypeConversion;
+
+public sealed class CollectionConverterTests
+{
+ [Fact]
+ public void Finds_element_type_for_generic_list()
+ {
+ // Arrange
+ Type sourceType = typeof(List);
+
+ // Act
+ Type? elementType = CollectionConverter.Instance.FindCollectionElementType(sourceType);
+
+ // Assert
+ elementType.Should().Be();
+ }
+
+ [Fact]
+ public void Finds_element_type_for_generic_enumerable()
+ {
+ // Arrange
+ Type sourceType = typeof(IEnumerable);
+
+ // Act
+ Type? elementType = CollectionConverter.Instance.FindCollectionElementType(sourceType);
+
+ // Assert
+ elementType.Should().Be();
+ }
+
+ [Fact]
+ public void Finds_element_type_for_custom_generic_collection_with_multiple_type_parameters()
+ {
+ // Arrange
+ Type sourceType = typeof(CustomCollection);
+
+ // Act
+ Type? elementType = CollectionConverter.Instance.FindCollectionElementType(sourceType);
+
+ // Assert
+ elementType.Should().Be();
+ }
+
+ [Fact]
+ public void Finds_element_type_for_custom_non_generic_collection()
+ {
+ // Arrange
+ Type sourceType = typeof(CustomCollectionOfIntString);
+
+ // Act
+ Type? elementType = CollectionConverter.Instance.FindCollectionElementType(sourceType);
+
+ // Assert
+ elementType.Should().Be();
+ }
+
+ [Fact]
+ public void Finds_no_element_type_for_non_generic_type()
+ {
+ // Arrange
+ Type sourceType = typeof(int);
+
+ // Act
+ Type? elementType = CollectionConverter.Instance.FindCollectionElementType(sourceType);
+
+ // Assert
+ elementType.Should().BeNull();
+ }
+
+ [Fact]
+ public void Finds_no_element_type_for_non_collection_generic_type()
+ {
+ // Arrange
+ Type sourceType = typeof(Tuple);
+
+ // Act
+ Type? elementType = CollectionConverter.Instance.FindCollectionElementType(sourceType);
+
+ // Assert
+ elementType.Should().BeNull();
+ }
+
+ [Fact]
+ public void Finds_no_element_type_for_unbound_generic_type()
+ {
+ // Arrange
+ Type sourceType = typeof(List<>);
+
+ // Act
+ Type? elementType = CollectionConverter.Instance.FindCollectionElementType(sourceType);
+
+ // Assert
+ elementType.Should().BeNull();
+ }
+
+ // ReSharper disable once UnusedTypeParameter
+ private class CustomCollection : List;
+
+ private sealed class CustomCollectionOfIntString : CustomCollection;
+}
diff --git a/test/OpenApiTests/OpenApiStartup.cs b/test/OpenApiTests/OpenApiStartup.cs
index ba0a5256ca..e8ee0fdb20 100644
--- a/test/OpenApiTests/OpenApiStartup.cs
+++ b/test/OpenApiTests/OpenApiStartup.cs
@@ -14,10 +14,7 @@ public class OpenApiStartup : TestableStartup
public override void ConfigureServices(IServiceCollection services)
{
base.ConfigureServices(services);
-
-#pragma warning disable JADNC_OA_001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
services.AddOpenApiForJsonApi(SetupSwaggerGenAction);
-#pragma warning restore JADNC_OA_001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
}
protected override void SetJsonApiOptions(JsonApiOptions options)
diff --git a/test/TestBuildingBlocks/ServiceCollectionExtensions.cs b/test/TestBuildingBlocks/ServiceCollectionExtensions.cs
index 8e5102fa23..886a5f0fb4 100644
--- a/test/TestBuildingBlocks/ServiceCollectionExtensions.cs
+++ b/test/TestBuildingBlocks/ServiceCollectionExtensions.cs
@@ -10,6 +10,7 @@ internal static class ServiceCollectionExtensions
public static void ReplaceControllers(this IServiceCollection services, TestControllerProvider provider)
{
ArgumentNullException.ThrowIfNull(services);
+ ArgumentNullException.ThrowIfNull(provider);
services.AddMvcCore().ConfigureApplicationPartManager(manager =>
{
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: