diff --git a/.gitignore b/.gitignore index cd9f35a530..6630942ad5 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ *.user .couscous/ docs/Template-Dark/ -.idea/ \ No newline at end of file +.idea/ +**/_site/ +log.txt diff --git a/Build.ps1 b/Build.ps1 index e51473adf2..bfbd989415 100644 --- a/Build.ps1 +++ b/Build.ps1 @@ -32,6 +32,9 @@ CheckLastExitCode dotnet test ./test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj CheckLastExitCode +dotnet test ./test/OperationsExampleTests/OperationsExampleTests.csproj +CheckLastExitCode + dotnet build .\src\JsonApiDotNetCore -c Release CheckLastExitCode @@ -57,4 +60,4 @@ Else { Write-Output "RUNNING dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=alpha1-$revision" dotnet pack .\src\JsonApiDotNetCore -c Release -o .\artifacts --version-suffix=alpha1-$revision CheckLastExitCode -} \ No newline at end of file +} diff --git a/Directory.Build.props b/Directory.Build.props index cc81f65974..346835dd6c 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - + netcoreapp2.0 netstandard2.0 @@ -10,7 +10,6 @@ 2.0.0 2.0.0 - 2.0.1 2.0.1 @@ -19,8 +18,8 @@ 4.4.0 - - + + 15.3.0-preview-20170427-09 1.1.2 @@ -28,5 +27,5 @@ 15.0.3 4.7.99 - + diff --git a/JsonApiDotnetCore.sln b/JsonApiDotnetCore.sln index d62f8db6af..4b7cf5ea47 100644 --- a/JsonApiDotnetCore.sln +++ b/JsonApiDotnetCore.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.27004.2009 +VisualStudioVersion = 15.0.27130.2010 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore", "src\JsonApiDotNetCore\JsonApiDotNetCore.csproj", "{C0EC9E70-EB2E-436F-9D94-FA16FA774123}" EndProject @@ -15,6 +15,11 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C5B4D998-CECB-454D-9F32-085A897577BE}" ProjectSection(SolutionItems) = preProject .gitignore = .gitignore + .travis.yml = .travis.yml + appveyor.yml = appveyor.yml + Build.ps1 = Build.ps1 + build.sh = build.sh + Directory.Build.props = Directory.Build.props README.md = README.md EndProjectSection EndProject @@ -32,9 +37,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks", "benchmarks\Benchmarks.csproj", "{1F604666-BB0F-413E-922D-9D37C6073285}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OperationsExample", "src\Examples\OperationsExample\OperationsExample.csproj", "{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OperationsExample", "src\Examples\OperationsExample\OperationsExample.csproj", "{CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OperationsExampleTests", "test\OperationsExampleTests\OperationsExampleTests.csproj", "{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OperationsExampleTests", "test\OperationsExampleTests\OperationsExampleTests.csproj", "{9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -114,34 +119,10 @@ Global {FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Debug|x86.Build.0 = Debug|Any CPU {FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|Any CPU.ActiveCfg = Release|Any CPU {FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|Any CPU.Build.0 = Release|Any CPU - {FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x64.ActiveCfg = Release|x64 - {FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x64.Build.0 = Release|x64 - {FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x86.ActiveCfg = Release|x86 - {FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x86.Build.0 = Release|x86 - {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|x64.ActiveCfg = Debug|x64 - {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|x64.Build.0 = Debug|x64 - {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|x86.ActiveCfg = Debug|x86 - {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|x86.Build.0 = Debug|x86 - {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|Any CPU.Build.0 = Release|Any CPU - {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x64.ActiveCfg = Release|x64 - {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x64.Build.0 = Release|x64 - {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x86.ActiveCfg = Release|x86 - {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x86.Build.0 = Release|x86 - {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|x64.ActiveCfg = Debug|x64 - {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|x64.Build.0 = Debug|x64 - {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|x86.ActiveCfg = Debug|x86 - {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|x86.Build.0 = Debug|x86 - {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|Any CPU.Build.0 = Release|Any CPU - {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|x64.ActiveCfg = Release|x64 - {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|x64.Build.0 = Release|x64 - {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|x86.ActiveCfg = Release|x86 - {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|x86.Build.0 = Release|x86 + {FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x64.ActiveCfg = Release|Any CPU + {FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x64.Build.0 = Release|Any CPU + {FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x86.ActiveCfg = Release|Any CPU + {FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D}.Release|x86.Build.0 = Release|Any CPU {1F604666-BB0F-413E-922D-9D37C6073285}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1F604666-BB0F-413E-922D-9D37C6073285}.Debug|Any CPU.Build.0 = Debug|Any CPU {1F604666-BB0F-413E-922D-9D37C6073285}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -154,22 +135,46 @@ Global {1F604666-BB0F-413E-922D-9D37C6073285}.Release|x64.Build.0 = Release|Any CPU {1F604666-BB0F-413E-922D-9D37C6073285}.Release|x86.ActiveCfg = Release|Any CPU {1F604666-BB0F-413E-922D-9D37C6073285}.Release|x86.Build.0 = Release|Any CPU + {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|x64.ActiveCfg = Debug|Any CPU + {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|x64.Build.0 = Debug|Any CPU + {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|x86.ActiveCfg = Debug|Any CPU + {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Debug|x86.Build.0 = Debug|Any CPU + {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|Any CPU.Build.0 = Release|Any CPU + {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x64.ActiveCfg = Release|Any CPU + {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x64.Build.0 = Release|Any CPU + {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x86.ActiveCfg = Release|Any CPU + {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D}.Release|x86.Build.0 = Release|Any CPU + {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|x64.ActiveCfg = Debug|Any CPU + {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|x64.Build.0 = Debug|Any CPU + {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|x86.ActiveCfg = Debug|Any CPU + {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Debug|x86.Build.0 = Debug|Any CPU + {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|Any CPU.Build.0 = Release|Any CPU + {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|x64.ActiveCfg = Release|Any CPU + {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|x64.Build.0 = Release|Any CPU + {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|x86.ActiveCfg = Release|Any CPU + {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {C0EC9E70-EB2E-436F-9D94-FA16FA774123} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} - {97EE048B-16C0-43F6-BDA9-4E762B2F579F} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} + {97EE048B-16C0-43F6-BDA9-4E762B2F579F} = {026FBC6C-AF76-4568-9B87-EC73457899FD} {0B959765-40D2-43B5-87EE-FE2FEF9DBED5} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} - {570165EC-62B5-4684-A139-8D2A30DD4475} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} + {570165EC-62B5-4684-A139-8D2A30DD4475} = {026FBC6C-AF76-4568-9B87-EC73457899FD} {73DA578D-A63F-4956-83ED-6D7102E09140} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} {6D4BD85A-A262-44C6-8572-FE3A30410BF3} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} {026FBC6C-AF76-4568-9B87-EC73457899FD} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} {FBFB0B0B-EA86-4B41-AB2A-E0249F70C86D} = {026FBC6C-AF76-4568-9B87-EC73457899FD} + {1F604666-BB0F-413E-922D-9D37C6073285} = {076E1AE4-FD25-4684-B826-CAAE37FEA0AA} {CF2C1EB6-8449-4B35-B8C7-F43D6D90632D} = {026FBC6C-AF76-4568-9B87-EC73457899FD} {9CD2C116-D133-4FE4-97DA-A9FEAFF045F1} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} - {1F604666-BB0F-413E-922D-9D37C6073285} = {076E1AE4-FD25-4684-B826-CAAE37FEA0AA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {A2421882-8F0A-4905-928F-B550B192F9A4} diff --git a/README.md b/README.md index 1acbbbf799..f396be824b 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@ [![Build status](https://ci.appveyor.com/api/projects/status/9fvgeoxdikwkom10?svg=true)](https://ci.appveyor.com/project/jaredcnance/jsonapidotnetcore) [![Travis](https://travis-ci.org/json-api-dotnet/JsonApiDotNetCore.svg?branch=master)](https://travis-ci.org/json-api-dotnet/JsonApiDotNetCore) [![NuGet](https://img.shields.io/nuget/v/JsonApiDotNetCore.svg)](https://www.nuget.org/packages/JsonApiDotNetCore/) -[![MyGet CI](https://img.shields.io/myget/research-institute/vpre/JsonApiDotNetCore.svg)](https://www.myget.org/feed/research-institute/package/nuget/JsonApiDotNetCore) [![Join the chat at https://gitter.im/json-api-dotnet-core/Lobby](https://badges.gitter.im/json-api-dotnet-core/Lobby.svg)](https://gitter.im/json-api-dotnet-core/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![FIRST-TIMERS](https://img.shields.io/badge/first--timers--only-friendly-blue.svg)](http://www.firsttimersonly.com/) diff --git a/build.sh b/build.sh index 441470e65d..50f2ab9c99 100755 --- a/build.sh +++ b/build.sh @@ -7,4 +7,5 @@ dotnet restore dotnet test ./test/UnitTests/UnitTests.csproj dotnet test ./test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj -dotnet test ./test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj \ No newline at end of file +dotnet test ./test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj +dotnet test ./test/OperationsExampleTests/OperationsExampleTests.csproj diff --git a/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs b/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs index ccdf8e8d9f..4266ca9741 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs @@ -1,4 +1,4 @@ -using JsonApiDotNetCoreExample.Models; +using JsonApiDotNetCoreExample.Models; using JsonApiDotNetCore.Models; using Microsoft.EntityFrameworkCore; @@ -14,12 +14,12 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity() .Property(t => t.CreatedDate).HasDefaultValueSql("CURRENT_TIMESTAMP").IsRequired(); - + modelBuilder.Entity() .HasOne(t => t.Assignee) .WithMany(p => p.AssignedTodoItems) .HasForeignKey(t => t.AssigneeId); - + modelBuilder.Entity() .HasOne(t => t.Owner) .WithMany(p => p.TodoItems) @@ -34,5 +34,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) [Resource("camelCasedModels")] public DbSet CamelCasedModels { get; set; } + + public DbSet
Articles { get; set; } + public DbSet Authors { get; set; } } } diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170315140127_initial.Designer.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20170315140127_initial.Designer.cs deleted file mode 100644 index be31f0ccae..0000000000 --- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170315140127_initial.Designer.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using JsonApiDotNetCoreExample.Data; - -namespace JsonApiDotNetCoreExample.Migrations -{ - [DbContext(typeof(AppDbContext))] - [Migration("20170315140127_initial")] - partial class initial - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { - modelBuilder - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) - .HasAnnotation("ProductVersion", "1.1.1"); - - modelBuilder.Entity("JsonApiDotNetCoreExample.Models.Person", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("FirstName"); - - b.Property("LastName"); - - b.HasKey("Id"); - - b.ToTable("People"); - }); - - modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("CollectionId"); - - b.Property("Description"); - - b.Property("Ordinal"); - - b.Property("OwnerId"); - - b.HasKey("Id"); - - b.HasIndex("CollectionId"); - - b.HasIndex("OwnerId"); - - b.ToTable("TodoItems"); - }); - - modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItemCollection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Name"); - - b.Property("OwnerId"); - - b.HasKey("Id"); - - b.HasIndex("OwnerId"); - - b.ToTable("TodoItemCollections"); - }); - - modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItem", b => - { - b.HasOne("JsonApiDotNetCoreExample.Models.TodoItemCollection", "Collection") - .WithMany("TodoItems") - .HasForeignKey("CollectionId"); - - b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Owner") - .WithMany("TodoItems") - .HasForeignKey("OwnerId"); - }); - - modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItemCollection", b => - { - b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Owner") - .WithMany("TodoItemCollections") - .HasForeignKey("OwnerId") - .OnDelete(DeleteBehavior.Cascade); - }); - } - } -} diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330020650_AddAssignedTodoItems.Designer.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330020650_AddAssignedTodoItems.Designer.cs deleted file mode 100755 index 52b60adbcb..0000000000 --- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330020650_AddAssignedTodoItems.Designer.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using JsonApiDotNetCoreExample.Data; - -namespace JsonApiDotNetCoreExample.Migrations -{ - [DbContext(typeof(AppDbContext))] - [Migration("20170330020650_AddAssignedTodoItems")] - partial class AddAssignedTodoItems - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { - modelBuilder - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) - .HasAnnotation("ProductVersion", "1.1.1"); - - modelBuilder.Entity("JsonApiDotNetCoreExample.Models.Person", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("FirstName"); - - b.Property("LastName"); - - b.HasKey("Id"); - - b.ToTable("People"); - }); - - modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AssigneeId"); - - b.Property("CollectionId"); - - b.Property("Description"); - - b.Property("Ordinal"); - - b.Property("OwnerId"); - - b.HasKey("Id"); - - b.HasIndex("AssigneeId"); - - b.HasIndex("CollectionId"); - - b.HasIndex("OwnerId"); - - b.ToTable("TodoItems"); - }); - - modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItemCollection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Name"); - - b.Property("OwnerId"); - - b.HasKey("Id"); - - b.HasIndex("OwnerId"); - - b.ToTable("TodoItemCollections"); - }); - - modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItem", b => - { - b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Assignee") - .WithMany("AssignedTodoItems") - .HasForeignKey("AssigneeId"); - - b.HasOne("JsonApiDotNetCoreExample.Models.TodoItemCollection", "Collection") - .WithMany("TodoItems") - .HasForeignKey("CollectionId"); - - b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Owner") - .WithMany("TodoItems") - .HasForeignKey("OwnerId"); - }); - - modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItemCollection", b => - { - b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Owner") - .WithMany("TodoItemCollections") - .HasForeignKey("OwnerId") - .OnDelete(DeleteBehavior.Cascade); - }); - } - } -} diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330020650_AddAssignedTodoItems.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330020650_AddAssignedTodoItems.cs deleted file mode 100755 index 8a1810a9d8..0000000000 --- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330020650_AddAssignedTodoItems.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -namespace JsonApiDotNetCoreExample.Migrations -{ - public partial class AddAssignedTodoItems : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "AssigneeId", - table: "TodoItems", - nullable: true); - - migrationBuilder.CreateIndex( - name: "IX_TodoItems_AssigneeId", - table: "TodoItems", - column: "AssigneeId"); - - migrationBuilder.AddForeignKey( - name: "FK_TodoItems_People_AssigneeId", - table: "TodoItems", - column: "AssigneeId", - principalTable: "People", - principalColumn: "Id", - onDelete: ReferentialAction.Restrict); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_TodoItems_People_AssigneeId", - table: "TodoItems"); - - migrationBuilder.DropIndex( - name: "IX_TodoItems_AssigneeId", - table: "TodoItems"); - - migrationBuilder.DropColumn( - name: "AssigneeId", - table: "TodoItems"); - } - } -} diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330234539_AddGuidProperty.Designer.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330234539_AddGuidProperty.Designer.cs deleted file mode 100755 index ded5d1b160..0000000000 --- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330234539_AddGuidProperty.Designer.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using JsonApiDotNetCoreExample.Data; - -namespace JsonApiDotNetCoreExample.Migrations -{ - [DbContext(typeof(AppDbContext))] - [Migration("20170330234539_AddGuidProperty")] - partial class AddGuidProperty - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { - modelBuilder - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) - .HasAnnotation("ProductVersion", "1.1.1"); - - modelBuilder.Entity("JsonApiDotNetCoreExample.Models.Person", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("FirstName"); - - b.Property("LastName"); - - b.HasKey("Id"); - - b.ToTable("People"); - }); - - modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AssigneeId"); - - b.Property("CollectionId"); - - b.Property("Description"); - - b.Property("GuidProperty"); - - b.Property("Ordinal"); - - b.Property("OwnerId"); - - b.HasKey("Id"); - - b.HasIndex("AssigneeId"); - - b.HasIndex("CollectionId"); - - b.HasIndex("OwnerId"); - - b.ToTable("TodoItems"); - }); - - modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItemCollection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Name"); - - b.Property("OwnerId"); - - b.HasKey("Id"); - - b.HasIndex("OwnerId"); - - b.ToTable("TodoItemCollections"); - }); - - modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItem", b => - { - b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Assignee") - .WithMany("AssignedTodoItems") - .HasForeignKey("AssigneeId"); - - b.HasOne("JsonApiDotNetCoreExample.Models.TodoItemCollection", "Collection") - .WithMany("TodoItems") - .HasForeignKey("CollectionId"); - - b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Owner") - .WithMany("TodoItems") - .HasForeignKey("OwnerId"); - }); - - modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItemCollection", b => - { - b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Owner") - .WithMany("TodoItemCollections") - .HasForeignKey("OwnerId") - .OnDelete(DeleteBehavior.Cascade); - }); - } - } -} diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330234539_AddGuidProperty.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330234539_AddGuidProperty.cs deleted file mode 100755 index 27815ce504..0000000000 --- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170330234539_AddGuidProperty.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace JsonApiDotNetCoreExample.Migrations -{ - public partial class AddGuidProperty : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "GuidProperty", - table: "TodoItems", - nullable: false, - defaultValue: new Guid("00000000-0000-0000-0000-000000000000")); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "GuidProperty", - table: "TodoItems"); - } - } -} diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170424180950_AddCreatesAndAchievedDates.Designer.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20170424180950_AddCreatesAndAchievedDates.Designer.cs deleted file mode 100755 index 537b3b043a..0000000000 --- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170424180950_AddCreatesAndAchievedDates.Designer.cs +++ /dev/null @@ -1,108 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using JsonApiDotNetCoreExample.Data; - -namespace JsonApiDotNetCoreExample.Migrations -{ - [DbContext(typeof(AppDbContext))] - [Migration("20170424180950_AddCreatesAndAchievedDates")] - partial class AddCreatesAndAchievedDates - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { - modelBuilder - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) - .HasAnnotation("ProductVersion", "1.1.1"); - - modelBuilder.Entity("JsonApiDotNetCoreExample.Models.Person", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("FirstName"); - - b.Property("LastName"); - - b.HasKey("Id"); - - b.ToTable("People"); - }); - - modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AchievedDate"); - - b.Property("AssigneeId"); - - b.Property("CollectionId"); - - b.Property("CreatedDate") - .ValueGeneratedOnAdd() - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.Property("Description"); - - b.Property("GuidProperty"); - - b.Property("Ordinal"); - - b.Property("OwnerId"); - - b.HasKey("Id"); - - b.HasIndex("AssigneeId"); - - b.HasIndex("CollectionId"); - - b.HasIndex("OwnerId"); - - b.ToTable("TodoItems"); - }); - - modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItemCollection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Name"); - - b.Property("OwnerId"); - - b.HasKey("Id"); - - b.HasIndex("OwnerId"); - - b.ToTable("TodoItemCollections"); - }); - - modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItem", b => - { - b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Assignee") - .WithMany("AssignedTodoItems") - .HasForeignKey("AssigneeId"); - - b.HasOne("JsonApiDotNetCoreExample.Models.TodoItemCollection", "Collection") - .WithMany("TodoItems") - .HasForeignKey("CollectionId"); - - b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Owner") - .WithMany("TodoItems") - .HasForeignKey("OwnerId"); - }); - - modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItemCollection", b => - { - b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Owner") - .WithMany("TodoItemCollections") - .HasForeignKey("OwnerId") - .OnDelete(DeleteBehavior.Cascade); - }); - } - } -} diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170424180950_AddCreatesAndAchievedDates.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20170424180950_AddCreatesAndAchievedDates.cs deleted file mode 100755 index 1c36034fe3..0000000000 --- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170424180950_AddCreatesAndAchievedDates.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace JsonApiDotNetCoreExample.Migrations -{ - public partial class AddCreatesAndAchievedDates : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "AchievedDate", - table: "TodoItems", - nullable: true); - - migrationBuilder.AddColumn( - name: "CreatedDate", - table: "TodoItems", - nullable: false, - defaultValueSql: "CURRENT_TIMESTAMP"); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "AchievedDate", - table: "TodoItems"); - - migrationBuilder.DropColumn( - name: "CreatedDate", - table: "TodoItems"); - } - } -} diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170426232509_AddCamelCasedModel.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20170426232509_AddCamelCasedModel.cs deleted file mode 100755 index fbec5e0a79..0000000000 --- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170426232509_AddCamelCasedModel.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Metadata; - -namespace JsonApiDotNetCoreExample.Migrations -{ - public partial class AddCamelCasedModel : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "CamelCasedModels", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn), - CompoundAttr = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_CamelCasedModels", x => x.Id); - }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "CamelCasedModels"); - } - } -} diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170426232509_AddCamelCasedModel.Designer.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.Designer.cs old mode 100755 new mode 100644 similarity index 72% rename from src/Examples/JsonApiDotNetCoreExample/Migrations/20170426232509_AddCamelCasedModel.Designer.cs rename to src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.Designer.cs index e43d2afc1f..c86425b00c --- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170426232509_AddCamelCasedModel.Designer.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.Designer.cs @@ -1,21 +1,53 @@ -using System; +// +using JsonApiDotNetCoreExample.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; -using JsonApiDotNetCoreExample.Data; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using System; namespace JsonApiDotNetCoreExample.Migrations { [DbContext(typeof(AppDbContext))] - [Migration("20170426232509_AddCamelCasedModel")] - partial class AddCamelCasedModel + [Migration("20180327120810_initial")] + partial class initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) { +#pragma warning disable 612, 618 modelBuilder .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) - .HasAnnotation("ProductVersion", "1.1.1"); + .HasAnnotation("ProductVersion", "2.0.1-rtm-125"); + + modelBuilder.Entity("JsonApiDotNetCoreExample.Models.Article", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuthorId"); + + b.Property("Name"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.ToTable("Articles"); + }); + + modelBuilder.Entity("JsonApiDotNetCoreExample.Models.Author", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Name"); + + b.HasKey("Id"); + + b.ToTable("Authors"); + }); modelBuilder.Entity("JsonApiDotNetCoreExample.Models.CamelCasedModel", b => { @@ -93,6 +125,14 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("TodoItemCollections"); }); + modelBuilder.Entity("JsonApiDotNetCoreExample.Models.Article", b => + { + b.HasOne("JsonApiDotNetCoreExample.Models.Author", "Author") + .WithMany("Articles") + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade); + }); + modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItem", b => { b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Assignee") @@ -115,6 +155,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasForeignKey("OwnerId") .OnDelete(DeleteBehavior.Cascade); }); +#pragma warning restore 612, 618 } } } diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170315140127_initial.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.cs similarity index 54% rename from src/Examples/JsonApiDotNetCoreExample/Migrations/20170315140127_initial.cs rename to src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.cs index e0b4e3b40b..ba19b62ef6 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Migrations/20170315140127_initial.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Migrations/20180327120810_initial.cs @@ -1,6 +1,7 @@ -using System; +using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Metadata; +using System; +using System.Collections.Generic; namespace JsonApiDotNetCoreExample.Migrations { @@ -8,6 +9,32 @@ public partial class initial : Migration { protected override void Up(MigrationBuilder migrationBuilder) { + migrationBuilder.CreateTable( + name: "Authors", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn), + Name = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Authors", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "CamelCasedModels", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn), + CompoundAttr = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_CamelCasedModels", x => x.Id); + }); + migrationBuilder.CreateTable( name: "People", columns: table => new @@ -22,6 +49,26 @@ protected override void Up(MigrationBuilder migrationBuilder) table.PrimaryKey("PK_People", x => x.Id); }); + migrationBuilder.CreateTable( + name: "Articles", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn), + AuthorId = table.Column(nullable: false), + Name = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Articles", x => x.Id); + table.ForeignKey( + name: "FK_Articles_Authors_AuthorId", + column: x => x.AuthorId, + principalTable: "Authors", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateTable( name: "TodoItemCollections", columns: table => new @@ -47,14 +94,24 @@ protected override void Up(MigrationBuilder migrationBuilder) { Id = table.Column(nullable: false) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn), + AchievedDate = table.Column(nullable: true), + AssigneeId = table.Column(nullable: true), CollectionId = table.Column(nullable: true), + CreatedDate = table.Column(nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), Description = table.Column(nullable: true), + GuidProperty = table.Column(nullable: false), Ordinal = table.Column(nullable: false), OwnerId = table.Column(nullable: true) }, constraints: table => { table.PrimaryKey("PK_TodoItems", x => x.Id); + table.ForeignKey( + name: "FK_TodoItems_People_AssigneeId", + column: x => x.AssigneeId, + principalTable: "People", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); table.ForeignKey( name: "FK_TodoItems_TodoItemCollections_CollectionId", column: x => x.CollectionId, @@ -69,6 +126,21 @@ protected override void Up(MigrationBuilder migrationBuilder) onDelete: ReferentialAction.Restrict); }); + migrationBuilder.CreateIndex( + name: "IX_Articles_AuthorId", + table: "Articles", + column: "AuthorId"); + + migrationBuilder.CreateIndex( + name: "IX_TodoItemCollections_OwnerId", + table: "TodoItemCollections", + column: "OwnerId"); + + migrationBuilder.CreateIndex( + name: "IX_TodoItems_AssigneeId", + table: "TodoItems", + column: "AssigneeId"); + migrationBuilder.CreateIndex( name: "IX_TodoItems_CollectionId", table: "TodoItems", @@ -78,18 +150,22 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "IX_TodoItems_OwnerId", table: "TodoItems", column: "OwnerId"); - - migrationBuilder.CreateIndex( - name: "IX_TodoItemCollections_OwnerId", - table: "TodoItemCollections", - column: "OwnerId"); } protected override void Down(MigrationBuilder migrationBuilder) { + migrationBuilder.DropTable( + name: "Articles"); + + migrationBuilder.DropTable( + name: "CamelCasedModels"); + migrationBuilder.DropTable( name: "TodoItems"); + migrationBuilder.DropTable( + name: "Authors"); + migrationBuilder.DropTable( name: "TodoItemCollections"); diff --git a/src/Examples/JsonApiDotNetCoreExample/Migrations/AppDbContextModelSnapshot.cs b/src/Examples/JsonApiDotNetCoreExample/Migrations/AppDbContextModelSnapshot.cs index 5de99f5078..c0794103fe 100755 --- a/src/Examples/JsonApiDotNetCoreExample/Migrations/AppDbContextModelSnapshot.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Migrations/AppDbContextModelSnapshot.cs @@ -1,8 +1,12 @@ -using System; +// +using JsonApiDotNetCoreExample.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; -using JsonApiDotNetCoreExample.Data; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using System; namespace JsonApiDotNetCoreExample.Migrations { @@ -11,9 +15,38 @@ partial class AppDbContextModelSnapshot : ModelSnapshot { protected override void BuildModel(ModelBuilder modelBuilder) { +#pragma warning disable 612, 618 modelBuilder .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) - .HasAnnotation("ProductVersion", "1.1.1"); + .HasAnnotation("ProductVersion", "2.0.1-rtm-125"); + + modelBuilder.Entity("JsonApiDotNetCoreExample.Models.Article", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuthorId"); + + b.Property("Name"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.ToTable("Articles"); + }); + + modelBuilder.Entity("JsonApiDotNetCoreExample.Models.Author", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Name"); + + b.HasKey("Id"); + + b.ToTable("Authors"); + }); modelBuilder.Entity("JsonApiDotNetCoreExample.Models.CamelCasedModel", b => { @@ -91,6 +124,14 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("TodoItemCollections"); }); + modelBuilder.Entity("JsonApiDotNetCoreExample.Models.Article", b => + { + b.HasOne("JsonApiDotNetCoreExample.Models.Author", "Author") + .WithMany("Articles") + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade); + }); + modelBuilder.Entity("JsonApiDotNetCoreExample.Models.TodoItem", b => { b.HasOne("JsonApiDotNetCoreExample.Models.Person", "Assignee") @@ -113,6 +154,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasForeignKey("OwnerId") .OnDelete(DeleteBehavior.Cascade); }); +#pragma warning restore 612, 618 } } } diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/Article.cs b/src/Examples/JsonApiDotNetCoreExample/Models/Article.cs new file mode 100644 index 0000000000..c633d58bdd --- /dev/null +++ b/src/Examples/JsonApiDotNetCoreExample/Models/Article.cs @@ -0,0 +1,14 @@ +using JsonApiDotNetCore.Models; + +namespace JsonApiDotNetCoreExample.Models +{ + public class Article : Identifiable + { + [Attr("name")] + public string Name { get; set; } + + [HasOne("author")] + public Author Author { get; set; } + public int AuthorId { get; set; } + } +} diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/Author.cs b/src/Examples/JsonApiDotNetCoreExample/Models/Author.cs new file mode 100644 index 0000000000..c77ad007c8 --- /dev/null +++ b/src/Examples/JsonApiDotNetCoreExample/Models/Author.cs @@ -0,0 +1,14 @@ +using JsonApiDotNetCore.Models; +using System.Collections.Generic; + +namespace JsonApiDotNetCoreExample.Models +{ + public class Author : Identifiable + { + [Attr("name")] + public string Name { get; set; } + + [HasMany("articles")] + public List
Articles { get; set; } + } +} diff --git a/src/Examples/JsonApiDotNetCoreExample/Program.cs b/src/Examples/JsonApiDotNetCoreExample/Program.cs index e4e3fe355e..b9bbe37b6a 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Program.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Program.cs @@ -5,10 +5,7 @@ namespace JsonApiDotNetCoreExample { public class Program { - public static void Main(string[] args) - { - BuildWebHost(args).Run(); - } + public static void Main(string[] args) => BuildWebHost(args).Run(); public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) diff --git a/src/Examples/JsonApiDotNetCoreExample/appsettings.json b/src/Examples/JsonApiDotNetCoreExample/appsettings.json index ceb4a1ed73..578225ef14 100755 --- a/src/Examples/JsonApiDotNetCoreExample/appsettings.json +++ b/src/Examples/JsonApiDotNetCoreExample/appsettings.json @@ -1,14 +1,13 @@ { - "Data": { - "DefaultConnection": - "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password=password" - }, - "Logging": { - "IncludeScopes": false, - "LogLevel": { - "Default": "Trace", - "System": "Trace", - "Microsoft": "Trace" + "Data": { + "DefaultConnection": "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password=postgres" + }, + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Trace", + "System": "Trace", + "Microsoft": "Trace" + } } - } } diff --git a/src/Examples/NoEntityFrameworkExample/Startup.cs b/src/Examples/NoEntityFrameworkExample/Startup.cs index 81f743aa5f..dfba27ddd9 100755 --- a/src/Examples/NoEntityFrameworkExample/Startup.cs +++ b/src/Examples/NoEntityFrameworkExample/Startup.cs @@ -9,6 +9,7 @@ using Microsoft.Extensions.Logging; using NoEntityFrameworkExample.Services; using Microsoft.EntityFrameworkCore; +using System; namespace NoEntityFrameworkExample { @@ -27,7 +28,7 @@ public Startup(IHostingEnvironment env) public IConfigurationRoot Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) + public virtual IServiceProvider ConfigureServices(IServiceCollection services) { // Add framework services. var mvcBuilder = services.AddMvc(); @@ -46,6 +47,8 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(Configuration); services.AddSingleton>(optionsBuilder.Options); services.AddScoped(); + + return services.BuildServiceProvider(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/src/Examples/OperationsExample/Data/AppDbContext.cs b/src/Examples/OperationsExample/Data/AppDbContext.cs deleted file mode 100644 index d00bfe4765..0000000000 --- a/src/Examples/OperationsExample/Data/AppDbContext.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using OperationsExample.Models; - -namespace OperationsExample.Data -{ - public class AppDbContext : DbContext - { - public AppDbContext(DbContextOptions options) - : base(options) - { } - - public DbSet
Articles { get; set; } - } -} diff --git a/src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.Designer.cs b/src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.Designer.cs deleted file mode 100755 index 10f16d49cd..0000000000 --- a/src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.Designer.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using OperationsExample.Data; - -namespace OperationsExample.Migrations -{ - [DbContext(typeof(AppDbContext))] - [Migration("20170827234334_AddArticles")] - partial class AddArticles - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { - modelBuilder - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) - .HasAnnotation("ProductVersion", "1.1.2"); - - modelBuilder.Entity("OperationsExample.Models.Article", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Name"); - - b.HasKey("Id"); - - b.ToTable("Articles"); - }); - } - } -} diff --git a/src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.cs b/src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.cs deleted file mode 100755 index 308e6f78f5..0000000000 --- a/src/Examples/OperationsExample/Migrations/20170827234334_AddArticles.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Metadata; - -namespace OperationsExample.Migrations -{ - public partial class AddArticles : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "Articles", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn), - Name = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Articles", x => x.Id); - }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "Articles"); - } - } -} diff --git a/src/Examples/OperationsExample/Migrations/AppDbContextModelSnapshot.cs b/src/Examples/OperationsExample/Migrations/AppDbContextModelSnapshot.cs deleted file mode 100755 index 547bbbf2cf..0000000000 --- a/src/Examples/OperationsExample/Migrations/AppDbContextModelSnapshot.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using OperationsExample.Data; - -namespace OperationsExample.Migrations -{ - [DbContext(typeof(AppDbContext))] - partial class AppDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { - modelBuilder - .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn) - .HasAnnotation("ProductVersion", "1.1.2"); - - modelBuilder.Entity("OperationsExample.Models.Article", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Name"); - - b.HasKey("Id"); - - b.ToTable("Articles"); - }); - } - } -} diff --git a/src/Examples/OperationsExample/Models/Article.cs b/src/Examples/OperationsExample/Models/Article.cs deleted file mode 100644 index fc4b5d6647..0000000000 --- a/src/Examples/OperationsExample/Models/Article.cs +++ /dev/null @@ -1,10 +0,0 @@ -using JsonApiDotNetCore.Models; - -namespace OperationsExample.Models -{ - public class Article : Identifiable - { - [Attr("name")] - public string Name { get; set; } - } -} diff --git a/src/Examples/OperationsExample/OperationsExample.csproj b/src/Examples/OperationsExample/OperationsExample.csproj index 48c2654722..69ad5653ce 100644 --- a/src/Examples/OperationsExample/OperationsExample.csproj +++ b/src/Examples/OperationsExample/OperationsExample.csproj @@ -8,9 +8,11 @@ + + diff --git a/src/Examples/OperationsExample/Program.cs b/src/Examples/OperationsExample/Program.cs index b528f47d15..1c2b6b267a 100644 --- a/src/Examples/OperationsExample/Program.cs +++ b/src/Examples/OperationsExample/Program.cs @@ -1,26 +1,15 @@ -using System.IO; +using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; namespace OperationsExample { public class Program - { - public static void Main(string[] args) - { - var config = new ConfigurationBuilder() - .AddCommandLine(args) - .AddEnvironmentVariables(prefix: "ASPNETCORE_") - .Build(); + { + public static void Main(string[] args) => BuildWebHost(args).Run(); - var host = new WebHostBuilder() - .UseConfiguration(config) - .UseKestrel() - .UseContentRoot(Directory.GetCurrentDirectory()) + public static IWebHost BuildWebHost(string[] args) => + WebHost.CreateDefaultBuilder(args) .UseStartup() .Build(); - - host.Run(); - } } } diff --git a/src/Examples/OperationsExample/Properties/launchSettings.json b/src/Examples/OperationsExample/Properties/launchSettings.json new file mode 100644 index 0000000000..b0d8e5bd4b --- /dev/null +++ b/src/Examples/OperationsExample/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:53656/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "OperationsExample": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:53657/" + } + } +} \ No newline at end of file diff --git a/src/Examples/OperationsExample/Startup.cs b/src/Examples/OperationsExample/Startup.cs index 1ffedf9116..c11a3e9d26 100644 --- a/src/Examples/OperationsExample/Startup.cs +++ b/src/Examples/OperationsExample/Startup.cs @@ -1,60 +1,56 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.EntityFrameworkCore; -using JsonApiDotNetCore.Extensions; -using System; -using OperationsExample.Data; -using JsonApiDotNetCore.Models; - -namespace OperationsExample -{ - public class Startup - { - public readonly IConfiguration Config; - - public Startup(IHostingEnvironment env) - { - var builder = new ConfigurationBuilder() - .SetBasePath(env.ContentRootPath) - .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) - .AddEnvironmentVariables(); - - Config = builder.Build(); - } - - public virtual IServiceProvider ConfigureServices(IServiceCollection services) - { - var loggerFactory = new LoggerFactory(); - loggerFactory - .AddConsole(LogLevel.Trace); - services.AddSingleton(loggerFactory); - - services.AddDbContext(options => - { - options.UseNpgsql(GetDbConnectionString()); - }, ServiceLifetime.Transient); - - services.AddJsonApi(opt => opt.EnableExtension(JsonApiExtension.Operations)); - - return services.BuildServiceProvider(); - } - - public virtual void Configure( - IApplicationBuilder app, - IHostingEnvironment env, - ILoggerFactory loggerFactory, - AppDbContext context) - { - context.Database.EnsureCreated(); - - loggerFactory.AddConsole(Config.GetSection("Logging")); - loggerFactory.AddDebug(); - app.UseJsonApi(); - } - - public string GetDbConnectionString() => Config["Data:DefaultConnection"]; - } -} \ No newline at end of file +using System; +using JsonApiDotNetCore.Extensions; +using JsonApiDotNetCoreExample.Data; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace OperationsExample +{ + public class Startup + { + public readonly IConfiguration Config; + + public Startup(IHostingEnvironment env) + { + var builder = new ConfigurationBuilder() + .SetBasePath(env.ContentRootPath) + .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) + .AddEnvironmentVariables(); + + Config = builder.Build(); + } + + public virtual IServiceProvider ConfigureServices(IServiceCollection services) + { + var loggerFactory = new LoggerFactory(); + loggerFactory.AddConsole(LogLevel.Trace); + + services.AddSingleton(loggerFactory); + + services.AddDbContext(options => options.UseNpgsql(GetDbConnectionString()), ServiceLifetime.Scoped); + + services.AddJsonApi(opt => opt.EnableOperations = true); + + return services.BuildServiceProvider(); + } + + public virtual void Configure( + IApplicationBuilder app, + IHostingEnvironment env, + ILoggerFactory loggerFactory, + AppDbContext context) + { + context.Database.EnsureCreated(); + + loggerFactory.AddConsole(Config.GetSection("Logging")); + loggerFactory.AddDebug(); + app.UseJsonApi(); + } + + public string GetDbConnectionString() => Config["Data:DefaultConnection"]; + } +} diff --git a/src/Examples/OperationsExample/appsettings.json b/src/Examples/OperationsExample/appsettings.json index c1061281cc..0d77cd40f2 100644 --- a/src/Examples/OperationsExample/appsettings.json +++ b/src/Examples/OperationsExample/appsettings.json @@ -1,13 +1,13 @@ -{ - "Data": { - "DefaultConnection": "Host=localhost;Port=5432;Database=OperationsExample;User ID=postgres;Password=password" - }, - "Logging": { - "IncludeScopes": false, - "LogLevel": { - "Default": "Trace", - "System": "Trace", - "Microsoft": "Trace" +{ + "Data": { + "DefaultConnection": "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password=postgres" + }, + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Trace", + "System": "Trace", + "Microsoft": "Trace" + } } - } } diff --git a/src/Examples/ReportsExample/Startup.cs b/src/Examples/ReportsExample/Startup.cs index fed3707789..72710681b9 100644 --- a/src/Examples/ReportsExample/Startup.cs +++ b/src/Examples/ReportsExample/Startup.cs @@ -1,7 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using JsonApiDotNetCore.Extensions; using JsonApiDotNetCore.Services; using Microsoft.AspNetCore.Builder; @@ -9,7 +5,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; namespace ReportsExample { @@ -28,12 +23,13 @@ public Startup(IHostingEnvironment env) Config = builder.Build(); } - public void ConfigureServices(IServiceCollection services) + public virtual void ConfigureServices(IServiceCollection services) { var mvcBuilder = services.AddMvc(); services.AddJsonApi(opt => { - opt.BuildContextGraph(builder => { + opt.BuildContextGraph(builder => + { builder.AddResource("reports"); }); opt.Namespace = "api"; diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilderOptions.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilderOptions.cs index ec19977313..0596d8ce3c 100644 --- a/src/JsonApiDotNetCore/Builders/DocumentBuilderOptions.cs +++ b/src/JsonApiDotNetCore/Builders/DocumentBuilderOptions.cs @@ -1,10 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Text; - namespace JsonApiDotNetCore.Builders { - public struct DocumentBuilderOptions + public struct DocumentBuilderOptions { public DocumentBuilderOptions(bool omitNullValuedAttributes = false) { diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilderOptionsProvider.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilderOptionsProvider.cs index af7fb78d7c..37c5d51273 100644 --- a/src/JsonApiDotNetCore/Builders/DocumentBuilderOptionsProvider.cs +++ b/src/JsonApiDotNetCore/Builders/DocumentBuilderOptionsProvider.cs @@ -1,6 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Text; using JsonApiDotNetCore.Services; using Microsoft.AspNetCore.Http; diff --git a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs index e61c5cd429..502d678f0d 100644 --- a/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs +++ b/src/JsonApiDotNetCore/Configuration/JsonApiOptions.cs @@ -10,17 +10,121 @@ namespace JsonApiDotNetCore.Configuration { + /// + /// Global options. + /// https://json-api-dotnet.github.io/#/global-options + /// public class JsonApiOptions { + /// + /// Whether or not stack traces should be serialized in Error objects + /// + public static bool DisableErrorStackTraces { get; set; } + + /// + /// Whether or not source URLs should be serialized in Error objects + /// + public static bool DisableErrorSource { get; set; } + + /// + /// The base URL Namespace + /// + /// + /// options.Namespace = "api/v1"; + /// public string Namespace { get; set; } + + /// + /// The default page size for all resources + /// + /// + /// options.DefaultPageSize = 10; + /// public int DefaultPageSize { get; set; } + + /// + /// Whether or not the total-record count should be included in all document + /// level meta objects. + /// Defaults to false. + /// + /// + /// options.IncludeTotalRecordCount = true; + /// public bool IncludeTotalRecordCount { get; set; } + + /// + /// Whether or not clients can provide ids when creating resources. + /// Defaults to false. When disabled the application will respond + /// with a 403 Forbidden respponse if a client attempts to create a + /// resource with a defined id. + /// + /// + /// options.AllowClientGeneratedIds = true; + /// public bool AllowClientGeneratedIds { get; set; } + + /// + /// The graph of all resources exposed by this application. + /// public IContextGraph ContextGraph { get; set; } + + /// + /// Use relative links for all resources. + /// + /// + /// + /// options.RelativeLinks = true; + /// + /// + /// { + /// "type": "articles", + /// "id": "4309", + /// "relationships": { + /// "author": { + /// "links": { + /// "self": "/api/v1/articles/4309/relationships/author", + /// "related": "/api/v1/articles/4309/author" + /// } + /// } + /// } + /// } + /// + /// public bool RelativeLinks { get; set; } + + /// + /// Whether or not to allow all custom query parameters. + /// + /// + /// + /// options.AllowCustomQueryParameters = true; + /// + /// public bool AllowCustomQueryParameters { get; set; } + + /// + /// The default behavior for serializing null attributes. + /// + /// + /// + /// options.NullAttributeResponseBehavior = new NullAttributeResponseBehavior { + /// // ... + ///}; + /// + /// public NullAttributeResponseBehavior NullAttributeResponseBehavior { get; set; } + /// + /// Whether or not to allow json:api v1.1 operation requests. + /// This is a beta feature and there may be breaking changes + /// in subsequent releases. For now, it should be considered + /// experimental. + /// + /// + /// This will be enabled by default in a subsequent patch JsonApiDotNetCore v2.2.x + /// + public bool EnableOperations { get; set; } + [Obsolete("JsonContract resolver can now be set on SerializerSettings.")] public IContractResolver JsonContractResolver { @@ -33,9 +137,6 @@ public IContractResolver JsonContractResolver ContractResolver = new DasherizedResolver() }; - internal IContextGraphBuilder ContextGraphBuilder { get; } = new ContextGraphBuilder(); - internal List EnabledExtensions { get; set; } = new List(); - public void BuildContextGraph(Action builder) where TContext : DbContext { BuildContextGraph(builder); @@ -55,10 +156,9 @@ public void BuildContextGraph(Action builder) } public void EnableExtension(JsonApiExtension extension) - { - EnabledExtensions.Add(extension); - } - } + => EnabledExtensions.Add(extension); - + internal IContextGraphBuilder ContextGraphBuilder { get; } = new ContextGraphBuilder(); + internal List EnabledExtensions { get; set; } = new List(); + } } diff --git a/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs b/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs index 8785eb2266..760f8f8d56 100644 --- a/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs +++ b/src/JsonApiDotNetCore/Controllers/BaseJsonApiController.cs @@ -104,7 +104,7 @@ public BaseJsonApiController( public virtual async Task GetAsync() { - if (_getAll == null) throw new JsonApiException(405, "Get requests are not supported"); + if (_getAll == null) throw Exceptions.UnSupportedRequestMethod; var entities = await _getAll.GetAsync(); @@ -113,7 +113,7 @@ public virtual async Task GetAsync() public virtual async Task GetAsync(TId id) { - if (_getById == null) throw new JsonApiException(405, "Get by Id requests are not supported"); + if (_getById == null) throw Exceptions.UnSupportedRequestMethod; var entity = await _getById.GetAsync(id); @@ -125,7 +125,7 @@ public virtual async Task GetAsync(TId id) public virtual async Task GetRelationshipsAsync(TId id, string relationshipName) { - if (_getRelationships == null) throw new JsonApiException(405, "Get Relationships requests are not supported"); + if (_getRelationships == null) throw Exceptions.UnSupportedRequestMethod; var relationship = await _getRelationships.GetRelationshipsAsync(id, relationshipName); if (relationship == null) @@ -136,7 +136,7 @@ public virtual async Task GetRelationshipsAsync(TId id, string re public virtual async Task GetRelationshipAsync(TId id, string relationshipName) { - if (_getRelationship == null) throw new JsonApiException(405, "Get Relationship requests are not supported"); + if (_getRelationship == null) throw Exceptions.UnSupportedRequestMethod; var relationship = await _getRelationship.GetRelationshipAsync(id, relationshipName); @@ -145,7 +145,7 @@ public virtual async Task GetRelationshipAsync(TId id, string rel public virtual async Task PostAsync([FromBody] T entity) { - if (_create == null) throw new JsonApiException(405, "Post requests are not supported"); + if (_create == null) throw Exceptions.UnSupportedRequestMethod; if (entity == null) return UnprocessableEntity(); @@ -160,7 +160,7 @@ public virtual async Task PostAsync([FromBody] T entity) public virtual async Task PatchAsync(TId id, [FromBody] T entity) { - if (_update == null) throw new JsonApiException(405, "Patch requests are not supported"); + if (_update == null) throw Exceptions.UnSupportedRequestMethod; if (entity == null) return UnprocessableEntity(); @@ -175,7 +175,7 @@ public virtual async Task PatchAsync(TId id, [FromBody] T entity) public virtual async Task PatchRelationshipsAsync(TId id, string relationshipName, [FromBody] List relationships) { - if (_updateRelationships == null) throw new JsonApiException(405, "Relationship Patch requests are not supported"); + if (_updateRelationships == null) throw Exceptions.UnSupportedRequestMethod; await _updateRelationships.UpdateRelationshipsAsync(id, relationshipName, relationships); @@ -184,7 +184,7 @@ public virtual async Task PatchRelationshipsAsync(TId id, string public virtual async Task DeleteAsync(TId id) { - if (_delete == null) throw new JsonApiException(405, "Delete requests are not supported"); + if (_delete == null) throw Exceptions.UnSupportedRequestMethod; var wasDeleted = await _delete.DeleteAsync(id); diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiControllerMixin.cs b/src/JsonApiDotNetCore/Controllers/JsonApiControllerMixin.cs index fafc70f161..6fff3a22c8 100644 --- a/src/JsonApiDotNetCore/Controllers/JsonApiControllerMixin.cs +++ b/src/JsonApiDotNetCore/Controllers/JsonApiControllerMixin.cs @@ -19,7 +19,8 @@ protected IActionResult Forbidden() protected IActionResult Error(Error error) { - var errorCollection = new ErrorCollection { + var errorCollection = new ErrorCollection + { Errors = new List { error } }; var result = new ObjectResult(errorCollection); @@ -36,16 +37,16 @@ protected IActionResult Errors(ErrorCollection errors) return result; } - private int GetErrorStatusCode(ErrorCollection errors) + private int GetErrorStatusCode(ErrorCollection errors) { var statusCodes = errors.Errors .Select(e => e.StatusCode) .Distinct() .ToList(); - if(statusCodes.Count == 1) + if (statusCodes.Count == 1) return statusCodes[0]; - + return int.Parse(statusCodes.Max().ToString()[0] + "00"); } } diff --git a/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs b/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs index f3d0b6651d..c3b667bc7d 100644 --- a/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs +++ b/src/JsonApiDotNetCore/Controllers/JsonApiOperationsController.cs @@ -5,19 +5,53 @@ namespace JsonApiDotNetCore.Controllers { + /// + /// A controller to be used for bulk operations as defined in the json:api 1.1 specification + /// public class JsonApiOperationsController : Controller { private readonly IOperationsProcessor _operationsProcessor; - public JsonApiOperationsController( - IOperationsProcessor operationsProcessor) + /// + /// The processor to handle bulk operations. + /// + public JsonApiOperationsController(IOperationsProcessor operationsProcessor) { _operationsProcessor = operationsProcessor; } + /// + /// Bulk endpoint for json:api operations + /// + /// + /// A json:api operations request document + /// + /// + /// + /// PATCH /api/bulk HTTP/1.1 + /// Content-Type: application/vnd.api+json + /// + /// { + /// "operations": [{ + /// "op": "add", + /// "ref": { + /// "type": "authors" + /// }, + /// "data": { + /// "type": "authors", + /// "attributes": { + /// "name": "jaredcnance" + /// } + /// } + /// }] + /// } + /// + /// [HttpPatch] - public async Task PatchAsync([FromBody] OperationsDocument doc) + public virtual async Task PatchAsync([FromBody] OperationsDocument doc) { + if (doc == null) return new StatusCodeResult(422); + var results = await _operationsProcessor.ProcessAsync(doc.Operations); return Ok(new OperationsDocument(results)); diff --git a/src/JsonApiDotNetCore/Data/DbContextResolver.cs b/src/JsonApiDotNetCore/Data/DbContextResolver.cs index 7cfe0a4278..e681e660bb 100644 --- a/src/JsonApiDotNetCore/Data/DbContextResolver.cs +++ b/src/JsonApiDotNetCore/Data/DbContextResolver.cs @@ -3,7 +3,7 @@ namespace JsonApiDotNetCore.Data { - public class DbContextResolver : IDbContextResolver + public class DbContextResolver : IDbContextResolver where TContext : DbContext { private readonly TContext _context; diff --git a/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs b/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs index e8b4e3d601..2606342e29 100644 --- a/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs +++ b/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs @@ -1,5 +1,4 @@ using Microsoft.EntityFrameworkCore; -using System.Reflection; using System; namespace JsonApiDotNetCore.Extensions diff --git a/src/JsonApiDotNetCore/Extensions/IApplicationBuilderExtensions.cs b/src/JsonApiDotNetCore/Extensions/IApplicationBuilderExtensions.cs index c3d7ba2ee7..651fbb44aa 100644 --- a/src/JsonApiDotNetCore/Extensions/IApplicationBuilderExtensions.cs +++ b/src/JsonApiDotNetCore/Extensions/IApplicationBuilderExtensions.cs @@ -1,5 +1,7 @@ +using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Middleware; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; namespace JsonApiDotNetCore.Extensions { @@ -8,6 +10,14 @@ public static class IApplicationBuilderExtensions { public static IApplicationBuilder UseJsonApi(this IApplicationBuilder app, bool useMvc = true) { + var environment = (IHostingEnvironment)app.ApplicationServices.GetService(typeof(IHostingEnvironment)); + + if(environment.IsProduction()) + { + JsonApiOptions.DisableErrorStackTraces = true; + JsonApiOptions.DisableErrorSource = true; + } + app.UseMiddleware(); if (useMvc) diff --git a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs index 1f2a71e20b..807d21c018 100644 --- a/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs +++ b/src/JsonApiDotNetCore/Extensions/IServiceCollectionExtensions.cs @@ -6,7 +6,6 @@ using JsonApiDotNetCore.Internal; using JsonApiDotNetCore.Internal.Generics; using JsonApiDotNetCore.Middleware; -using JsonApiDotNetCore.Models; using JsonApiDotNetCore.Serialization; using JsonApiDotNetCore.Services; using JsonApiDotNetCore.Services.Operations; @@ -89,13 +88,13 @@ public static void AddJsonApiInternals( this IServiceCollection services, JsonApiOptions jsonApiOptions) { - if (!jsonApiOptions.ContextGraph.UsesDbContext) + if (jsonApiOptions.ContextGraph.UsesDbContext == false) { services.AddScoped(); services.AddSingleton(new DbContextOptionsBuilder().Options); } - if (jsonApiOptions.EnabledExtensions.Contains(JsonApiExtension.Operations)) + if (jsonApiOptions.EnableOperations) AddOperationServices(services); services.AddScoped(typeof(IEntityRepository<>), typeof(DefaultEntityRepository<>)); @@ -110,6 +109,9 @@ public static void AddJsonApiInternals( services.AddScoped(typeof(IGetByIdService<>), typeof(EntityResourceService<>)); services.AddScoped(typeof(IGetByIdService<,>), typeof(EntityResourceService<,>)); + services.AddScoped(typeof(IGetRelationshipService<,>), typeof(EntityResourceService<>)); + services.AddScoped(typeof(IGetRelationshipService<,>), typeof(EntityResourceService<,>)); + services.AddScoped(typeof(IUpdateService<>), typeof(EntityResourceService<>)); services.AddScoped(typeof(IUpdateService<,>), typeof(EntityResourceService<,>)); @@ -122,6 +124,7 @@ public static void AddJsonApiInternals( services.AddSingleton(jsonApiOptions.ContextGraph); services.AddScoped(); services.AddSingleton(); + services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); @@ -148,12 +151,12 @@ private static void AddOperationServices(IServiceCollection services) services.AddScoped(typeof(IGetOpProcessor<>), typeof(GetOpProcessor<>)); services.AddScoped(typeof(IGetOpProcessor<,>), typeof(GetOpProcessor<,>)); - services.AddScoped(typeof(IReplaceOpProcessor<>), typeof(ReplaceOpProcessor<>)); - services.AddScoped(typeof(IReplaceOpProcessor<,>), typeof(ReplaceOpProcessor<,>)); - services.AddScoped(typeof(IRemoveOpProcessor<>), typeof(RemoveOpProcessor<>)); services.AddScoped(typeof(IRemoveOpProcessor<,>), typeof(RemoveOpProcessor<,>)); + services.AddScoped(typeof(IUpdateOpProcessor<>), typeof(UpdateOpProcessor<>)); + services.AddScoped(typeof(IUpdateOpProcessor<,>), typeof(UpdateOpProcessor<,>)); + services.AddSingleton(); services.AddSingleton(); } diff --git a/src/JsonApiDotNetCore/Extensions/JObjectExtensions.cs b/src/JsonApiDotNetCore/Extensions/JObjectExtensions.cs deleted file mode 100644 index 70aa070fc6..0000000000 --- a/src/JsonApiDotNetCore/Extensions/JObjectExtensions.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Newtonsoft.Json.Linq; -using Newtonsoft.Json.Schema; -using JsonApiDotNetCore.Models.Pointers; - -namespace JsonApiDotNetCore.Extensions -{ - public static class JObjectExtensions - { - public static bool TryParse(this JObject obj, JSchema schema, out Pointer pointer) - where TPointer : Pointer, new() - { - if (obj.IsValid(schema)) - { - pointer = obj.ToObject(); - return true; - } - - pointer = null; - return false; - } - } -} \ No newline at end of file diff --git a/src/JsonApiDotNetCore/Formatters/JsonApiWriter.cs b/src/JsonApiDotNetCore/Formatters/JsonApiWriter.cs index d644def66d..fcf0ac7850 100644 --- a/src/JsonApiDotNetCore/Formatters/JsonApiWriter.cs +++ b/src/JsonApiDotNetCore/Formatters/JsonApiWriter.cs @@ -26,8 +26,6 @@ public async Task WriteAsync(OutputFormatterWriteContext context) if (context == null) throw new ArgumentNullException(nameof(context)); - _logger?.LogInformation("Formatting response as JSONAPI"); - var response = context.HttpContext.Response; using (var writer = context.WriterFactory(response.Body, Encoding.UTF8)) { @@ -40,9 +38,7 @@ public async Task WriteAsync(OutputFormatterWriteContext context) catch (Exception e) { _logger?.LogError(new EventId(), e, "An error ocurred while formatting the response"); - var errors = new ErrorCollection(); - errors.Add(new Error("400", e.Message)); - responseContent = errors.GetJson(); + responseContent = GetErrorResponse(e); response.StatusCode = 400; } @@ -51,9 +47,12 @@ public async Task WriteAsync(OutputFormatterWriteContext context) } } - private string GetResponseBody(object responseObject) + private string GetResponseBody(object responseObject) => _serializer.Serialize(responseObject); + private string GetErrorResponse(Exception e) { - return _serializer.Serialize(responseObject); - } + var errors = new ErrorCollection(); + errors.Add(new Error(400, e.Message, ErrorMeta.FromException(e))); + return errors.GetJson(); + } } } diff --git a/src/JsonApiDotNetCore/Internal/ContextGraph.cs b/src/JsonApiDotNetCore/Internal/ContextGraph.cs index bc3f037bf2..d21231f067 100644 --- a/src/JsonApiDotNetCore/Internal/ContextGraph.cs +++ b/src/JsonApiDotNetCore/Internal/ContextGraph.cs @@ -9,8 +9,8 @@ public class ContextGraph : IContextGraph private List _entities; public ContextGraph() { } - - public ContextGraph(List entities, bool usesDbContext) + + public ContextGraph(List entities, bool usesDbContext) { _entities = entities; UsesDbContext = usesDbContext; @@ -42,9 +42,9 @@ public string GetRelationshipName(string relationshipName) { var entityType = typeof(TParent); return _entities - .SingleOrDefault(e => e.EntityType == entityType) + .SingleOrDefault(e => e.EntityType == entityType) ?.Relationships - .SingleOrDefault(r => string.Equals(r.PublicRelationshipName, relationshipName, StringComparison.OrdinalIgnoreCase)) + .SingleOrDefault(r => r.Is(relationshipName)) ?.InternalRelationshipName; } } diff --git a/src/JsonApiDotNetCore/Internal/Error.cs b/src/JsonApiDotNetCore/Internal/Error.cs index 0443e1edb7..999611d79e 100644 --- a/src/JsonApiDotNetCore/Internal/Error.cs +++ b/src/JsonApiDotNetCore/Internal/Error.cs @@ -1,4 +1,6 @@ using System; +using System.Diagnostics; +using JsonApiDotNetCore.Configuration; using Newtonsoft.Json; namespace JsonApiDotNetCore.Internal @@ -8,30 +10,40 @@ public class Error public Error() { } - public Error(string status, string title) + [Obsolete("Use Error constructors with int typed status")] + public Error(string status, string title, ErrorMeta meta = null, string source = null) { Status = status; Title = title; + Meta = meta; + Source = source; } - public Error(int status, string title) + public Error(int status, string title, ErrorMeta meta = null, string source = null) { Status = status.ToString(); Title = title; + Meta = meta; + Source = source; } - public Error(string status, string title, string detail) + [Obsolete("Use Error constructors with int typed status")] + public Error(string status, string title, string detail, ErrorMeta meta = null, string source = null) { Status = status; Title = title; Detail = detail; + Meta = meta; + Source = source; } - public Error(int status, string title, string detail) + public Error(int status, string title, string detail, ErrorMeta meta = null, string source = null) { Status = status.ToString(); Title = title; Detail = detail; + Meta = meta; + Source = source; } [JsonProperty("title")] @@ -45,5 +57,25 @@ public Error(int status, string title, string detail) [JsonIgnore] public int StatusCode => int.Parse(Status); + + [JsonProperty("source")] + public string Source { get; set; } + + [JsonProperty("meta")] + public ErrorMeta Meta { get; set; } + + public bool ShouldSerializeMeta() => (JsonApiOptions.DisableErrorStackTraces == false); + public bool ShouldSerializeSource() => (JsonApiOptions.DisableErrorSource == false); + } + + public class ErrorMeta + { + [JsonProperty("stackTrace")] + public string[] StackTrace { get; set; } + + public static ErrorMeta FromException(Exception e) + => new ErrorMeta { + StackTrace = e.Demystify().ToString().Split(new[] { "\n"}, int.MaxValue, StringSplitOptions.RemoveEmptyEntries) + }; } } diff --git a/src/JsonApiDotNetCore/Internal/Exceptions.cs b/src/JsonApiDotNetCore/Internal/Exceptions.cs new file mode 100644 index 0000000000..6c510e562b --- /dev/null +++ b/src/JsonApiDotNetCore/Internal/Exceptions.cs @@ -0,0 +1,11 @@ +namespace JsonApiDotNetCore.Internal +{ + internal static class Exceptions + { + private const string DOCUMENTATION_URL = "https://json-api-dotnet.github.io/#/errors/"; + private static string BuildUrl(string title) => DOCUMENTATION_URL + title; + + public static JsonApiException UnSupportedRequestMethod { get; } + = new JsonApiException(405, "Request method is not supported.", BuildUrl(nameof(UnSupportedRequestMethod))); + } +} diff --git a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs index 3f88010e0a..08cba58dd1 100644 --- a/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs +++ b/src/JsonApiDotNetCore/Internal/Generics/GenericProcessorFactory.cs @@ -1,3 +1,5 @@ +using JsonApiDotNetCore.Services; +using Microsoft.AspNetCore.Http; using System; namespace JsonApiDotNetCore.Internal.Generics @@ -13,7 +15,9 @@ public interface IGenericProcessorFactory /// Constructs the generic type and locates the service, then casts to TInterface /// /// + /// /// GetProcessor<IGenericProcessor>(typeof(GenericProcessor<>), typeof(TResource)); + /// /// TInterface GetProcessor(Type openGenericType, Type resourceType); @@ -21,7 +25,9 @@ public interface IGenericProcessorFactory /// Constructs the generic type and locates the service, then casts to TInterface /// /// + /// /// GetProcessor<IGenericProcessor>(typeof(GenericProcessor<,>), typeof(TResource), typeof(TId)); + /// /// TInterface GetProcessor(Type openGenericType, Type resourceType, Type keyType); } @@ -30,7 +36,7 @@ public class GenericProcessorFactory : IGenericProcessorFactory { private readonly IServiceProvider _serviceProvider; - public GenericProcessorFactory(IServiceProvider serviceProvider) + public GenericProcessorFactory(IScopedServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } diff --git a/src/JsonApiDotNetCore/Internal/JsonApiException.cs b/src/JsonApiDotNetCore/Internal/JsonApiException.cs index aa5faf3f73..8918d07c6c 100644 --- a/src/JsonApiDotNetCore/Internal/JsonApiException.cs +++ b/src/JsonApiDotNetCore/Internal/JsonApiException.cs @@ -13,30 +13,29 @@ public JsonApiException(ErrorCollection errorCollection) } public JsonApiException(Error error) - : base(error.Title) - => _errors.Add(error); + : base(error.Title) => _errors.Add(error); [Obsolete("Use int statusCode overload instead")] - public JsonApiException(string statusCode, string message) + public JsonApiException(string statusCode, string message, string source = null) : base(message) - => _errors.Add(new Error(statusCode, message, null)); + => _errors.Add(new Error(statusCode, message, null, GetMeta(), source)); [Obsolete("Use int statusCode overload instead")] - public JsonApiException(string statusCode, string message, string detail) + public JsonApiException(string statusCode, string message, string detail, string source = null) : base(message) - => _errors.Add(new Error(statusCode, message, detail)); + => _errors.Add(new Error(statusCode, message, detail, GetMeta(), source)); - public JsonApiException(int statusCode, string message) + public JsonApiException(int statusCode, string message, string source = null) : base(message) - => _errors.Add(new Error(statusCode, message, null)); + => _errors.Add(new Error(statusCode, message, null, GetMeta(), source)); - public JsonApiException(int statusCode, string message, string detail) + public JsonApiException(int statusCode, string message, string detail, string source = null) : base(message) - => _errors.Add(new Error(statusCode, message, detail)); + => _errors.Add(new Error(statusCode, message, detail, GetMeta(), source)); public JsonApiException(int statusCode, string message, Exception innerException) : base(message, innerException) - => _errors.Add(new Error(statusCode, message, innerException.Message)); + => _errors.Add(new Error(statusCode, message, innerException.Message, GetMeta(innerException))); public ErrorCollection GetError() => _errors; @@ -53,5 +52,8 @@ public int GetStatusCode() return 500; } + + private ErrorMeta GetMeta() => ErrorMeta.FromException(this); + private ErrorMeta GetMeta(Exception e) => ErrorMeta.FromException(e); } } diff --git a/src/JsonApiDotNetCore/Internal/JsonApiExceptionFactory.cs b/src/JsonApiDotNetCore/Internal/JsonApiExceptionFactory.cs index 36b4969b1d..159c9abc70 100644 --- a/src/JsonApiDotNetCore/Internal/JsonApiExceptionFactory.cs +++ b/src/JsonApiDotNetCore/Internal/JsonApiExceptionFactory.cs @@ -1,36 +1,25 @@ using System; -using System.Linq; namespace JsonApiDotNetCore.Internal { public static class JsonApiExceptionFactory { - private const string JsonApiException = nameof(JsonApiException); - private const string InvalidCastException = nameof(InvalidCastException); - public static JsonApiException GetException(Exception exception) { - var exceptionType = exception.GetType().ToString().Split('.').Last(); - switch(exceptionType) - { - case JsonApiException: - return (JsonApiException)exception; - case InvalidCastException: - return new JsonApiException(409, exception.Message); - default: - return new JsonApiException(500, exception.Message, GetExceptionDetail(exception.InnerException)); - } - } + var exceptionType = exception.GetType(); - private static string GetExceptionDetail(Exception exception) - { - string detail = null; - while(exception != null) - { - detail = $"{detail}{exception.Message}; "; - exception = exception.InnerException; - } - return detail; + if (exceptionType == typeof(JsonApiException)) + return (JsonApiException)exception; + + // TODO: this is for mismatching type requests (e.g. posting an author to articles endpoint) + // however, we can't actually guarantee that this is the source of this exception + // we should probably use an action filter or when we improve the ContextGraph + // we might be able to skip most of deserialization entirely by checking the JToken + // directly + if (exceptionType == typeof(InvalidCastException)) + return new JsonApiException(409, exception.Message, exception); + + return new JsonApiException(500, exceptionType.Name, exception); } } } diff --git a/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs b/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs index e94f872b54..59bb3f0f83 100644 --- a/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs +++ b/src/JsonApiDotNetCore/Internal/Query/AttrFilterQuery.cs @@ -17,10 +17,10 @@ public AttrFilterQuery( var attribute = GetAttribute(filterQuery.Attribute); - if(attribute == null) + if (attribute == null) throw new JsonApiException(400, $"'{filterQuery.Attribute}' is not a valid attribute."); - if(attribute.IsFilterable == false) + if (attribute.IsFilterable == false) throw new JsonApiException(400, $"Filter is not allowed for attribute '{attribute.PublicAttributeName}'."); FilteredAttribute = attribute; @@ -32,9 +32,7 @@ public AttrFilterQuery( public string PropertyValue { get; } public FilterOperations FilterOperation { get; } - private AttrAttribute GetAttribute(string attribute) => - _jsonApiContext.RequestEntity.Attributes.FirstOrDefault( - attr => string.Equals(attr.PublicAttributeName, attribute, StringComparison.OrdinalIgnoreCase) - ); + private AttrAttribute GetAttribute(string attribute) => + _jsonApiContext.RequestEntity.Attributes.FirstOrDefault(attr => attr.Is(attribute)); } } diff --git a/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs b/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs index 52d7c66f41..5ec658873d 100644 --- a/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs +++ b/src/JsonApiDotNetCore/Internal/Query/RelatedAttrFilterQuery.cs @@ -22,11 +22,11 @@ public RelatedAttrFilterQuery( throw new JsonApiException(400, $"{relationshipArray[1]} is not a valid relationship on {relationshipArray[0]}."); var attribute = GetAttribute(relationship, relationshipArray[1]); - - if(attribute == null) + + if (attribute == null) throw new JsonApiException(400, $"'{filterQuery.Attribute}' is not a valid attribute."); - if(attribute.IsFilterable == false) + if (attribute.IsFilterable == false) throw new JsonApiException(400, $"Filter is not allowed for attribute '{attribute.PublicAttributeName}'."); FilteredRelationship = relationship; @@ -41,16 +41,13 @@ public RelatedAttrFilterQuery( public RelationshipAttribute FilteredRelationship { get; } private RelationshipAttribute GetRelationship(string propertyName) - { - return _jsonApiContext.RequestEntity.Relationships - .FirstOrDefault(r => string.Equals(r.PublicRelationshipName, propertyName, StringComparison.OrdinalIgnoreCase)); - } + => _jsonApiContext.RequestEntity.Relationships.FirstOrDefault(r => r.Is(propertyName)); private AttrAttribute GetAttribute(RelationshipAttribute relationship, string attribute) { var relatedContextExntity = _jsonApiContext.ContextGraph.GetContextEntity(relationship.Type); return relatedContextExntity.Attributes - .FirstOrDefault(a => string.Equals(a.PublicAttributeName, attribute, StringComparison.OrdinalIgnoreCase)); + .FirstOrDefault(a => a.Is(attribute)); } } } diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj index 9fe109011b..5aa6b6b897 100755 --- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj +++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj @@ -5,6 +5,7 @@ JsonApiDotNetCore JsonApiDotNetCore + jsonapi;dotnet core;emberjs;ember https://github.com/json-api-dotnet/JsonApiDotNetCore @@ -13,13 +14,25 @@ git https://github.com/json-api-dotnet/JsonApiDotNetCore + + - - + + + true + + + bin\Release\netstandard2.0\JsonApiDotNetCore.xml + + + + + + \ No newline at end of file diff --git a/src/JsonApiDotNetCore/Models/AttrAttribute.cs b/src/JsonApiDotNetCore/Models/AttrAttribute.cs index 5be036636d..db61cb56ea 100644 --- a/src/JsonApiDotNetCore/Models/AttrAttribute.cs +++ b/src/JsonApiDotNetCore/Models/AttrAttribute.cs @@ -47,5 +47,11 @@ public void SetValue(object entity, object newValue) propertyInfo.SetValue(entity, convertedValue); } } + + /// + /// Whether or not the provided exposed name is equivalent to the one defined in on the model + /// + public virtual bool Is(string publicRelationshipName) + => string.Equals(publicRelationshipName, PublicAttributeName, StringComparison.OrdinalIgnoreCase); } } diff --git a/src/JsonApiDotNetCore/Models/Operations/OperationCode.cs b/src/JsonApiDotNetCore/Models/Operations/OperationCode.cs index ffe3310985..6b6905cd59 100644 --- a/src/JsonApiDotNetCore/Models/Operations/OperationCode.cs +++ b/src/JsonApiDotNetCore/Models/Operations/OperationCode.cs @@ -1,10 +1,14 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; + namespace JsonApiDotNetCore.Models.Operations { + [JsonConverter(typeof(StringEnumConverter))] public enum OperationCode { get = 1, add = 2, - replace = 3, + update = 3, remove = 4 } } diff --git a/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs b/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs deleted file mode 100644 index 0df8f64e72..0000000000 --- a/src/JsonApiDotNetCore/Models/Pointers/OperationsPointer.cs +++ /dev/null @@ -1,108 +0,0 @@ -using System; -using System.Collections.Generic; -using JsonApiDotNetCore.Internal; -using JsonApiDotNetCore.Models.Operations; - -namespace JsonApiDotNetCore.Models.Pointers -{ - public class OperationsPointer : Pointer - { - /// - /// - /// - /// - public override object GetValue(object root) - { - if (root == null) throw new ArgumentNullException(nameof(root)); - if (PointerAddress == null) throw new InvalidOperationException("Cannot get pointer value from null PointerAddress"); - - if (root is List operations) - return GetValueFromRoot(operations); - - throw new ArgumentException(nameof(root)); - } - - private object GetValueFromRoot(List operations) - { - var pathSegments = PointerAddress.ToLower().Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); - - if (pathSegments.Length < 4) - throw BadRequestException("number of segments", pathSegments.Length); - - if (pathSegments[0] != "operations") - throw BadRequestException("prefix", pathSegments[0]); - - // /operations/{operationIndex} → operations = [...] - if (int.TryParse(pathSegments[1], out int operationIndex)) - return GetValueFromOperation(operations[operationIndex], pathSegments); - else - throw BadRequestException("operation index", operationIndex); - } - - private object GetValueFromOperation(Operation operation, string[] pathSegments) - { - var operationPropertyName = pathSegments[2]; - - // /operations/0/ref → ref = {...} - if (operationPropertyName == "ref") - return GetValueFromRef(operation.Ref, pathSegments); - - // /operations/0/data → data = {...} - if (operation.DataIsList == false) - return GetValueFromData(operation.DataObject, pathSegments, segementStartIndex: 3); - - // /operations/0/data/{dataIndex} → data = [...] - if (int.TryParse(pathSegments[3], out int dataIndex)) - { - if (operation.DataList.Count >= dataIndex - 1) - return GetValueFromData(operation.DataList[dataIndex], pathSegments, segementStartIndex: 4); - throw BadRequestException("data index", dataIndex, "Pointer references an index in the data array that cannot be found at the specified position."); - } - else - { - throw BadRequestException("data index", dataIndex, "Pointer segement should provide array index but could not be parsed to an integer."); - } - } - - private object GetValueFromRef(ResourceReference reference, string[] pathSegments) - { - const int segementStartIndex = 3; - - // /operations/0/ref/{dataPropertyName} - if (pathSegments.Length <= segementStartIndex) - throw BadRequestException("length", pathSegments.Length, "Pointer does not contain enough segments to locate ref property."); - - var dataPropertyName = pathSegments[segementStartIndex]; - switch (dataPropertyName) - { - case "id": - return reference.Id; - case "type": - return reference.Type; - default: - throw BadRequestException("ref property name", dataPropertyName, "Only 'id' and 'type' pointers are supported."); - } - } - - private object GetValueFromData(DocumentData data, string[] pathSegments, int segementStartIndex) - { - // /operations/0/data/{dataPropertyName} - if (pathSegments.Length <= segementStartIndex) - throw BadRequestException("length", pathSegments.Length, "Pointer does not contain enough segments to locate data property."); - - var dataPropertyName = pathSegments[segementStartIndex]; - switch (dataPropertyName) - { - case "id": - return data.Id; - case "type": - return data.Type; - default: - throw BadRequestException("data property name", dataPropertyName, "Only 'id' and 'type' pointers are supported."); - } - } - - private JsonApiException BadRequestException(string condition, object value, string extraDetail = null) - => new JsonApiException(400, $"Operations pointer has invalid {condition} '{value}' in pointer '{PointerAddress}'. {extraDetail}"); - } -} diff --git a/src/JsonApiDotNetCore/Models/Pointers/Pointer.cs b/src/JsonApiDotNetCore/Models/Pointers/Pointer.cs deleted file mode 100644 index 27f0083904..0000000000 --- a/src/JsonApiDotNetCore/Models/Pointers/Pointer.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Schema; - -namespace JsonApiDotNetCore.Models.Pointers -{ - public abstract class Pointer - { - public static JSchema JsonSchema { get; } = JSchema.Parse("{ 'pointer': {'type': 'string'} }"); - - /// - /// Location represented by the pointer - /// - /// /operations/0/data/id - [JsonProperty("pointer")] - public string PointerAddress { get; set; } - - /// - /// Get the value located at the PointerAddress in the supplied object - /// - public abstract object GetValue(object root); - } -} diff --git a/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs b/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs index 852b602bea..0dbe6a4670 100644 --- a/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs +++ b/src/JsonApiDotNetCore/Models/RelationshipAttribute.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace JsonApiDotNetCore.Models { @@ -33,5 +33,11 @@ public override bool Equals(object obj) } return IsHasMany == attr.IsHasMany && PublicRelationshipName.Equals(attr.PublicRelationshipName); } + + /// + /// Whether or not the provided exposed name is equivalent to the one defined in on the model + /// + public virtual bool Is(string publicRelationshipName) + => string.Equals(publicRelationshipName, PublicRelationshipName, StringComparison.OrdinalIgnoreCase); } } diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs index a32a40c5d4..649d6435ff 100644 --- a/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs +++ b/src/JsonApiDotNetCore/Serialization/JsonApiDeSerializer.cs @@ -29,11 +29,14 @@ public object Deserialize(string requestBody) { try { - // TODO: determine whether or not the token should be re-used rather than performing full - // deserialization again from the string var bodyJToken = JToken.Parse(requestBody); - if(bodyJToken.SelectToken("operations") != null) + + if (RequestIsOperation(bodyJToken)) { + _jsonApiContext.IsBulkOperationRequest = true; + + // TODO: determine whether or not the token should be re-used rather than performing full + // deserialization again from the string var operations = JsonConvert.DeserializeObject(requestBody); if (operations == null) throw new JsonApiException(400, "Failed to deserialize operations request."); @@ -53,6 +56,10 @@ public object Deserialize(string requestBody) } } + private bool RequestIsOperation(JToken bodyJToken) + => _jsonApiContext.Options.EnableOperations + && (bodyJToken.SelectToken("operations") != null); + public TEntity Deserialize(string requestBody) => (TEntity)Deserialize(requestBody); public object DeserializeRelationship(string requestBody) @@ -77,7 +84,7 @@ public List DeserializeList(string requestBody) try { var documents = JsonConvert.DeserializeObject(requestBody); - + var deserializedList = new List(); foreach (var data in documents.Data) { @@ -191,7 +198,7 @@ private object SetHasOneRelationship(object entity, if (relationshipAttr == null) throw new JsonApiException(400, $"{_jsonApiContext.RequestEntity.EntityName} does not contain a relationship '{relationshipName}'"); - var rio = (ResourceIdentifierObject) relationshipData.ExposedData; + var rio = (ResourceIdentifierObject)relationshipData.ExposedData; if (rio == null) return entity; diff --git a/src/JsonApiDotNetCore/Serialization/JsonApiSerializer.cs b/src/JsonApiDotNetCore/Serialization/JsonApiSerializer.cs index 8e94835266..20d119ff07 100644 --- a/src/JsonApiDotNetCore/Serialization/JsonApiSerializer.cs +++ b/src/JsonApiDotNetCore/Serialization/JsonApiSerializer.cs @@ -37,9 +37,12 @@ public string Serialize(object entity) if (entity == null) return GetNullDataResponse(); - if (entity.GetType() == typeof(ErrorCollection) || _jsonApiContext.RequestEntity == null) + if (entity.GetType() == typeof(ErrorCollection) || (_jsonApiContext.RequestEntity == null && _jsonApiContext.IsBulkOperationRequest == false)) return GetErrorJson(entity, _logger); + if (_jsonApiContext.IsBulkOperationRequest) + return _serialize(entity); + if (entity is IEnumerable) return SerializeDocuments(entity); @@ -86,4 +89,4 @@ private string _serialize(object obj) return JsonConvert.SerializeObject(obj, _jsonApiContext.Options.SerializerSettings); } } -} \ No newline at end of file +} diff --git a/src/JsonApiDotNetCore/Services/EntityResourceService.cs b/src/JsonApiDotNetCore/Services/EntityResourceService.cs index af86692166..91eabb9cfd 100644 --- a/src/JsonApiDotNetCore/Services/EntityResourceService.cs +++ b/src/JsonApiDotNetCore/Services/EntityResourceService.cs @@ -96,6 +96,8 @@ public virtual async Task GetRelationshipAsync(TId id, string relationsh _logger.LogTrace($"Looking up '{relationshipName}'..."); var entity = await _entities.GetAndIncludeAsync(id, relationshipName); + // TODO: it would be better if we could distinguish whether or not the relationship was not found, + // vs the relationship not being set on the instance of T if (entity == null) throw new JsonApiException(404, $"Relationship {relationshipName} not found."); diff --git a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs index c16da81cfa..a73f0eb53a 100644 --- a/src/JsonApiDotNetCore/Services/IJsonApiContext.cs +++ b/src/JsonApiDotNetCore/Services/IJsonApiContext.cs @@ -27,6 +27,7 @@ public interface IJsonApiContext Dictionary RelationshipsToUpdate { get; set; } Type ControllerType { get; set; } Dictionary DocumentMeta { get; set; } + bool IsBulkOperationRequest { get; set; } TAttribute GetControllerAttribute() where TAttribute : Attribute; } diff --git a/src/JsonApiDotNetCore/Services/JsonApiContext.cs b/src/JsonApiDotNetCore/Services/JsonApiContext.cs index 66dfb46f8e..1ebf5aeea1 100644 --- a/src/JsonApiDotNetCore/Services/JsonApiContext.cs +++ b/src/JsonApiDotNetCore/Services/JsonApiContext.cs @@ -51,6 +51,7 @@ public JsonApiContext( public Dictionary RelationshipsToUpdate { get; set; } = new Dictionary(); public Type ControllerType { get; set; } public Dictionary DocumentMeta { get; set; } + public bool IsBulkOperationRequest { get; set; } public IJsonApiContext ApplyContext(object controller) { diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs b/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs index eeadc38e22..4215507bc2 100644 --- a/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs +++ b/src/JsonApiDotNetCore/Services/Operations/OperationProcessorResolver.cs @@ -1,30 +1,42 @@ -using System.Collections.Concurrent; using JsonApiDotNetCore.Internal.Generics; using JsonApiDotNetCore.Models.Operations; using JsonApiDotNetCore.Services.Operations.Processors; namespace JsonApiDotNetCore.Services.Operations { + /// + /// Used to resolve at runtime based on the required operation + /// public interface IOperationProcessorResolver { + /// + /// Locates the correct + /// IOpProcessor LocateCreateService(Operation operation); + + /// + /// Locates the correct + /// IOpProcessor LocateGetService(Operation operation); - IOpProcessor LocateReplaceService(Operation operation); + + /// + /// Locates the correct + /// IOpProcessor LocateRemoveService(Operation operation); + + /// + /// Locates the correct + /// + IOpProcessor LocateUpdateService(Operation operation); } + /// public class OperationProcessorResolver : IOperationProcessorResolver { private readonly IGenericProcessorFactory _processorFactory; private readonly IJsonApiContext _context; - // processor caches -- since there is some associated cost with creating the processors, we store them in memory - // to reduce the cost of subsequent requests. in the future, this may be moved into setup code run at startup - private ConcurrentDictionary _createOpProcessors = new ConcurrentDictionary(); - private ConcurrentDictionary _getOpProcessors = new ConcurrentDictionary(); - private ConcurrentDictionary _replaceOpProcessors = new ConcurrentDictionary(); - private ConcurrentDictionary _removeOpProcessors = new ConcurrentDictionary(); - + /// public OperationProcessorResolver( IGenericProcessorFactory processorFactory, IJsonApiContext context) @@ -33,73 +45,55 @@ public OperationProcessorResolver( _context = context; } - // TODO: there may be some optimizations here around the cache such as not caching processors - // if the request only contains a single op + /// public IOpProcessor LocateCreateService(Operation operation) { var resource = operation.GetResourceTypeName(); - if (_createOpProcessors.TryGetValue(resource, out IOpProcessor cachedProcessor)) - return cachedProcessor; - var contextEntity = _context.ContextGraph.GetContextEntity(resource); var processor = _processorFactory.GetProcessor( typeof(ICreateOpProcessor<,>), contextEntity.EntityType, contextEntity.IdentityType ); - _createOpProcessors[resource] = processor; - return processor; } + /// public IOpProcessor LocateGetService(Operation operation) { var resource = operation.GetResourceTypeName(); - if (_getOpProcessors.TryGetValue(resource, out IOpProcessor cachedProcessor)) - return cachedProcessor; - var contextEntity = _context.ContextGraph.GetContextEntity(resource); var processor = _processorFactory.GetProcessor( typeof(IGetOpProcessor<,>), contextEntity.EntityType, contextEntity.IdentityType ); - _getOpProcessors[resource] = processor; - return processor; } - public IOpProcessor LocateReplaceService(Operation operation) + /// + public IOpProcessor LocateRemoveService(Operation operation) { var resource = operation.GetResourceTypeName(); - if (_replaceOpProcessors.TryGetValue(resource, out IOpProcessor cachedProcessor)) - return cachedProcessor; - var contextEntity = _context.ContextGraph.GetContextEntity(resource); var processor = _processorFactory.GetProcessor( - typeof(IReplaceOpProcessor<,>), contextEntity.EntityType, contextEntity.IdentityType + typeof(IRemoveOpProcessor<,>), contextEntity.EntityType, contextEntity.IdentityType ); - _replaceOpProcessors[resource] = processor; - return processor; } - public IOpProcessor LocateRemoveService(Operation operation) + /// + public IOpProcessor LocateUpdateService(Operation operation) { var resource = operation.GetResourceTypeName(); - if (_removeOpProcessors.TryGetValue(resource, out IOpProcessor cachedProcessor)) - return cachedProcessor; - var contextEntity = _context.ContextGraph.GetContextEntity(resource); var processor = _processorFactory.GetProcessor( - typeof(IRemoveOpProcessor<,>), contextEntity.EntityType, contextEntity.IdentityType + typeof(IUpdateOpProcessor<,>), contextEntity.EntityType, contextEntity.IdentityType ); - _removeOpProcessors[resource] = processor; - return processor; } } diff --git a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs index b687f1498f..7cb9765606 100644 --- a/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs +++ b/src/JsonApiDotNetCore/Services/Operations/OperationsProcessor.cs @@ -6,7 +6,6 @@ using JsonApiDotNetCore.Internal; using JsonApiDotNetCore.Models; using JsonApiDotNetCore.Models.Operations; -using JsonApiDotNetCore.Models.Pointers; using Microsoft.EntityFrameworkCore; namespace JsonApiDotNetCore.Services.Operations @@ -33,6 +32,7 @@ public async Task> ProcessAsync(List inputOps) { var outputOps = new List(); var opIndex = 0; + OperationCode? lastAttemptedOperation = null; // used for error messages only using (var transaction = await _dbContext.Database.BeginTransactionAsync()) { @@ -40,30 +40,29 @@ public async Task> ProcessAsync(List inputOps) { foreach (var op in inputOps) { + lastAttemptedOperation = op.Op; await ProcessOperation(op, outputOps); opIndex++; } transaction.Commit(); + return outputOps; } catch (JsonApiException e) { - outputOps = new List(); - throw new JsonApiException(e.GetStatusCode(), $"Transaction failed on operation[{opIndex}].", e); + transaction.Rollback(); + throw new JsonApiException(e.GetStatusCode(), $"Transaction failed on operation[{opIndex}] ({lastAttemptedOperation}).", e); } catch (Exception e) { - throw new JsonApiException(500, $"Transaction failed on operation[{opIndex}] for an unexpected reason.", e); + transaction.Rollback(); + throw new JsonApiException(500, $"Transaction failed on operation[{opIndex}] ({lastAttemptedOperation}) for an unexpected reason.", e); } } - - return outputOps; } private async Task ProcessOperation(Operation op, List outputOps) { - var operationsPointer = new OperationsPointer(); - ReplaceLocalIdsInResourceObject(op.DataObject, outputOps); ReplaceLocalIdsInRef(op.Ref, outputOps); @@ -88,39 +87,39 @@ private void ReplaceLocalIdsInResourceObject(ResourceObject resourceObject, List // if(HasLocalId(resourceObject)) // resourceObject.Id = GetIdFromLocalId(outputOps, resourceObject.LocalId); - if (resourceObject.Relationships != null) - { - foreach (var relationshipDictionary in resourceObject.Relationships) - { - if (relationshipDictionary.Value.IsHasMany) - { - foreach (var relationship in relationshipDictionary.Value.ManyData) - if(HasLocalId(relationship)) + if (resourceObject.Relationships != null) + { + foreach (var relationshipDictionary in resourceObject.Relationships) + { + if (relationshipDictionary.Value.IsHasMany) + { + foreach (var relationship in relationshipDictionary.Value.ManyData) + if (HasLocalId(relationship)) relationship.Id = GetIdFromLocalId(outputOps, relationship.LocalId); - } + } else { var relationship = relationshipDictionary.Value.SingleData; - if(HasLocalId(relationship)) + if (HasLocalId(relationship)) relationship.Id = GetIdFromLocalId(outputOps, relationship.LocalId); } - } + } } } - private void ReplaceLocalIdsInRef(ResourceReference resourceRef, List outputOps) - { + private void ReplaceLocalIdsInRef(ResourceReference resourceRef, List outputOps) + { if (resourceRef == null) return; - if(HasLocalId(resourceRef)) + if (HasLocalId(resourceRef)) resourceRef.Id = GetIdFromLocalId(outputOps, resourceRef.LocalId); } private bool HasLocalId(ResourceIdentifierObject rio) => string.IsNullOrEmpty(rio.LocalId) == false; - private string GetIdFromLocalId(List outputOps, string localId) + private string GetIdFromLocalId(List outputOps, string localId) { var referencedOp = outputOps.FirstOrDefault(o => o.DataObject.LocalId == localId); - if(referencedOp == null) throw new JsonApiException(400, $"Could not locate lid '{localId}' in document."); + if (referencedOp == null) throw new JsonApiException(400, $"Could not locate lid '{localId}' in document."); return referencedOp.DataObject.Id; } @@ -132,10 +131,10 @@ private IOpProcessor GetOperationsProcessor(Operation op) return _processorResolver.LocateCreateService(op); case OperationCode.get: return _processorResolver.LocateGetService(op); - case OperationCode.replace: - return _processorResolver.LocateReplaceService(op); case OperationCode.remove: return _processorResolver.LocateRemoveService(op); + case OperationCode.update: + return _processorResolver.LocateUpdateService(op); default: throw new JsonApiException(400, $"'{op.Op}' is not a valid operation code"); } diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs index 251b81a5d6..4f50bbf4da 100644 --- a/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs +++ b/src/JsonApiDotNetCore/Services/Operations/Processors/CreateOpProcessor.cs @@ -61,6 +61,10 @@ public async Task ProcessAsync(Operation operation) _contextGraph.GetContextEntity(operation.GetResourceTypeName()), result); + // we need to persist the original request localId so that subsequent operations + // can locate the result of this operation by its localId + operationResult.DataObject.LocalId = operation.DataObject.LocalId; + return operationResult; } } diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs index 8bd5b2b0f4..d8793d016c 100644 --- a/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs +++ b/src/JsonApiDotNetCore/Services/Operations/Processors/GetOpProcessor.cs @@ -1,4 +1,6 @@ +using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using JsonApiDotNetCore.Builders; using JsonApiDotNetCore.Internal; @@ -8,41 +10,57 @@ namespace JsonApiDotNetCore.Services.Operations.Processors { + /// + /// Handles all "" operations + /// + /// The resource type public interface IGetOpProcessor : IOpProcessor where T : class, IIdentifiable { } + /// + /// Handles all "" operations + /// + /// The resource type + /// The resource identifier type public interface IGetOpProcessor : IOpProcessor where T : class, IIdentifiable { } + /// public class GetOpProcessor : GetOpProcessor where T : class, IIdentifiable { + /// public GetOpProcessor( IGetAllService getAll, IGetByIdService getById, + IGetRelationshipService getRelationship, IJsonApiDeSerializer deSerializer, IDocumentBuilder documentBuilder, IContextGraph contextGraph, IJsonApiContext jsonApiContext - ) : base(getAll, getById, deSerializer, documentBuilder, contextGraph, jsonApiContext) + ) : base(getAll, getById, getRelationship, deSerializer, documentBuilder, contextGraph, jsonApiContext) { } } + /// public class GetOpProcessor : IGetOpProcessor where T : class, IIdentifiable { private readonly IGetAllService _getAll; private readonly IGetByIdService _getById; + private readonly IGetRelationshipService _getRelationship; private readonly IJsonApiDeSerializer _deSerializer; private readonly IDocumentBuilder _documentBuilder; private readonly IContextGraph _contextGraph; private readonly IJsonApiContext _jsonApiContext; + /// public GetOpProcessor( IGetAllService getAll, IGetByIdService getById, + IGetRelationshipService getRelationship, IJsonApiDeSerializer deSerializer, IDocumentBuilder documentBuilder, IContextGraph contextGraph, @@ -50,12 +68,14 @@ public GetOpProcessor( { _getAll = getAll; _getById = getById; + _getRelationship = getRelationship; _deSerializer = deSerializer; _documentBuilder = documentBuilder; _contextGraph = contextGraph; _jsonApiContext = jsonApiContext.ApplyContext(this); } + /// public async Task ProcessAsync(Operation operation) { var operationResult = new Operation @@ -63,9 +83,11 @@ public async Task ProcessAsync(Operation operation) Op = OperationCode.get }; - operationResult.Data = string.IsNullOrWhiteSpace(operation.Ref.Id?.ToString()) + operationResult.Data = string.IsNullOrWhiteSpace(operation.Ref.Id) ? await GetAllAsync(operation) - : await GetByIdAsync(operation); + : string.IsNullOrWhiteSpace(operation.Ref.Relationship) + ? await GetByIdAsync(operation) + : await GetRelationshipAsync(operation); return operationResult; } @@ -88,13 +110,39 @@ private async Task GetAllAsync(Operation operation) private async Task GetByIdAsync(Operation operation) { - var id = TypeHelper.ConvertType(operation.Ref.Id); + var id = GetReferenceId(operation); var result = await _getById.GetAsync(id); + + // this is a bit ugly but we need to bomb the entire transaction if the entity cannot be found + // in the future it would probably be better to return a result status along with the doc to + // avoid throwing exceptions on 4xx errors. + // consider response type (status, document) + if (result == null) + throw new JsonApiException(404, $"Could not find '{operation.Ref.Type}' record with id '{operation.Ref.Id}'"); + var doc = _documentBuilder.GetData( _contextGraph.GetContextEntity(operation.GetResourceTypeName()), result); return doc; } + + private async Task GetRelationshipAsync(Operation operation) + { + var id = GetReferenceId(operation); + var result = await _getRelationship.GetRelationshipAsync(id, operation.Ref.Relationship); + + // TODO: need a better way to get the ContextEntity from a relationship name + // when no generic parameter is available + var relationshipType = _contextGraph.GetContextEntity(operation.GetResourceTypeName()) + .Relationships.Single(r => r.Is(operation.Ref.Relationship)).Type; + var relatedContextEntity = _jsonApiContext.ContextGraph.GetContextEntity(relationshipType); + + var doc = _documentBuilder.GetData(relatedContextEntity, result as IIdentifiable); // TODO: if this is safe, then it should be cast in the GetRelationshipAsync call + + return doc; + } + + private TId GetReferenceId(Operation operation) => TypeHelper.ConvertType(operation.Ref.Id); } } diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/RemoveOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/RemoveOpProcessor.cs index c96af5bb37..236a76d084 100644 --- a/src/JsonApiDotNetCore/Services/Operations/Processors/RemoveOpProcessor.cs +++ b/src/JsonApiDotNetCore/Services/Operations/Processors/RemoveOpProcessor.cs @@ -1,4 +1,3 @@ -using System; using System.Threading.Tasks; using JsonApiDotNetCore.Builders; using JsonApiDotNetCore.Internal; @@ -52,14 +51,12 @@ public async Task ProcessAsync(Operation operation) { var stringId = operation.Ref?.Id?.ToString(); if (string.IsNullOrWhiteSpace(stringId)) - throw new JsonApiException(400, "The data.id parameter is required for delete operations"); + throw new JsonApiException(400, "The ref.id parameter is required for remove operations"); var id = TypeHelper.ConvertType(stringId); var result = await _service.DeleteAsync(id); - var operationResult = new Operation { }; - - return operationResult; + return null; } } } diff --git a/src/JsonApiDotNetCore/Services/Operations/Processors/ReplaceOpProcessor.cs b/src/JsonApiDotNetCore/Services/Operations/Processors/UpdateOpProcessor.cs similarity index 79% rename from src/JsonApiDotNetCore/Services/Operations/Processors/ReplaceOpProcessor.cs rename to src/JsonApiDotNetCore/Services/Operations/Processors/UpdateOpProcessor.cs index 27cf348397..b626fbe746 100644 --- a/src/JsonApiDotNetCore/Services/Operations/Processors/ReplaceOpProcessor.cs +++ b/src/JsonApiDotNetCore/Services/Operations/Processors/UpdateOpProcessor.cs @@ -7,18 +7,18 @@ namespace JsonApiDotNetCore.Services.Operations.Processors { - public interface IReplaceOpProcessor : IOpProcessor + public interface IUpdateOpProcessor : IOpProcessor where T : class, IIdentifiable { } - public interface IReplaceOpProcessor : IOpProcessor + public interface IUpdateOpProcessor : IOpProcessor where T : class, IIdentifiable { } - public class ReplaceOpProcessor : ReplaceOpProcessor + public class UpdateOpProcessor : UpdateOpProcessor where T : class, IIdentifiable { - public ReplaceOpProcessor( + public UpdateOpProcessor( IUpdateService service, IJsonApiDeSerializer deSerializer, IDocumentBuilder documentBuilder, @@ -27,7 +27,7 @@ IContextGraph contextGraph { } } - public class ReplaceOpProcessor : IReplaceOpProcessor + public class UpdateOpProcessor : ICreateOpProcessor where T : class, IIdentifiable { private readonly IUpdateService _service; @@ -35,7 +35,7 @@ public class ReplaceOpProcessor : IReplaceOpProcessor private readonly IDocumentBuilder _documentBuilder; private readonly IContextGraph _contextGraph; - public ReplaceOpProcessor( + public UpdateOpProcessor( IUpdateService service, IJsonApiDeSerializer deSerializer, IDocumentBuilder documentBuilder, @@ -49,17 +49,15 @@ public ReplaceOpProcessor( public async Task ProcessAsync(Operation operation) { - var model = (T)_deSerializer.DocumentToObject(operation.DataObject); - if (string.IsNullOrWhiteSpace(operation?.DataObject?.Id?.ToString())) throw new JsonApiException(400, "The data.id parameter is required for replace operations"); - var id = TypeHelper.ConvertType(operation.DataObject.Id); - var result = await _service.UpdateAsync(id, model); + var model = (T)_deSerializer.DocumentToObject(operation.DataObject); + var result = await _service.UpdateAsync(model.Id, model); var operationResult = new Operation { - Op = OperationCode.replace + Op = OperationCode.update }; operationResult.Data = _documentBuilder.GetData( diff --git a/src/JsonApiDotNetCore/Services/QueryParser.cs b/src/JsonApiDotNetCore/Services/QueryParser.cs index d9dfab532d..5e705f4bc9 100644 --- a/src/JsonApiDotNetCore/Services/QueryParser.cs +++ b/src/JsonApiDotNetCore/Services/QueryParser.cs @@ -8,12 +8,15 @@ using JsonApiDotNetCore.Models; using Microsoft.AspNetCore.Http; -namespace JsonApiDotNetCore.Services { - public interface IQueryParser { +namespace JsonApiDotNetCore.Services +{ + public interface IQueryParser + { QuerySet Parse(IQueryCollection query); } - public class QueryParser : IQueryParser { + public class QueryParser : IQueryParser + { private readonly IControllerContext _controllerContext; private readonly JsonApiOptions _options; @@ -30,41 +33,49 @@ public class QueryParser : IQueryParser { public QueryParser( IControllerContext controllerContext, - JsonApiOptions options) { + JsonApiOptions options) + { _controllerContext = controllerContext; _options = options; } - public virtual QuerySet Parse(IQueryCollection query) { + public virtual QuerySet Parse(IQueryCollection query) + { var querySet = new QuerySet(); - var disabledQueries = _controllerContext.GetControllerAttribute() ? .QueryParams ?? QueryParams.None; + var disabledQueries = _controllerContext.GetControllerAttribute()?.QueryParams ?? QueryParams.None; - foreach (var pair in query) { - if (pair.Key.StartsWith(FILTER)) { + foreach (var pair in query) + { + if (pair.Key.StartsWith(FILTER)) + { if (disabledQueries.HasFlag(QueryParams.Filter) == false) querySet.Filters.AddRange(ParseFilterQuery(pair.Key, pair.Value)); continue; } - if (pair.Key.StartsWith(SORT)) { + if (pair.Key.StartsWith(SORT)) + { if (disabledQueries.HasFlag(QueryParams.Sort) == false) querySet.SortParameters = ParseSortParameters(pair.Value); continue; } - if (pair.Key.StartsWith(INCLUDE)) { + if (pair.Key.StartsWith(INCLUDE)) + { if (disabledQueries.HasFlag(QueryParams.Include) == false) querySet.IncludedRelationships = ParseIncludedRelationships(pair.Value); continue; } - if (pair.Key.StartsWith(PAGE)) { + if (pair.Key.StartsWith(PAGE)) + { if (disabledQueries.HasFlag(QueryParams.Page) == false) querySet.PageQuery = ParsePageQuery(querySet.PageQuery, pair.Key, pair.Value); continue; } - if (pair.Key.StartsWith(FIELDS)) { + if (pair.Key.StartsWith(FIELDS)) + { if (disabledQueries.HasFlag(QueryParams.Fields) == false) querySet.Fields = ParseFieldsQuery(pair.Key, pair.Value); continue; @@ -77,15 +88,17 @@ public virtual QuerySet Parse(IQueryCollection query) { return querySet; } - protected virtual List ParseFilterQuery(string key, string value) { + protected virtual List ParseFilterQuery(string key, string value) + { // expected input = filter[id]=1 // expected input = filter[id]=eq:1 var queries = new List(); - var propertyName = key.Split(OPEN_BRACKET, CLOSE_BRACKET) [1]; + var propertyName = key.Split(OPEN_BRACKET, CLOSE_BRACKET)[1]; var values = value.Split(COMMA); - foreach (var val in values) { + foreach (var val in values) + { (var operation, var filterValue) = ParseFilterOperation(val); queries.Add(new FilterQuery(propertyName, filterValue, operation)); } @@ -93,7 +106,8 @@ protected virtual List ParseFilterQuery(string key, string value) { return queries; } - protected virtual(string operation, string value) ParseFilterOperation(string value) { + protected virtual (string operation, string value) ParseFilterOperation(string value) + { if (value.Length < 3) return (string.Empty, value); @@ -159,7 +173,7 @@ protected virtual List ParseSortParameters(string value) var attribute = GetAttribute(propertyName); - if(attribute.IsSortable == false) + if (attribute.IsSortable == false) throw new JsonApiException(400, $"Sort is not allowed for attribute '{attribute.PublicAttributeName}'."); sortParameters.Add(new SortQuery(direction, attribute)); @@ -168,7 +182,8 @@ protected virtual List ParseSortParameters(string value) return sortParameters; } - protected virtual List ParseIncludedRelationships(string value) { + protected virtual List ParseIncludedRelationships(string value) + { const string NESTED_DELIMITER = "."; if (value.Contains(NESTED_DELIMITER)) throw new JsonApiException(400, "Deeply nested relationships are not supported"); @@ -195,7 +210,7 @@ protected virtual List ParseFieldsQuery(string key, string value) { var attr = _controllerContext.RequestEntity .Attributes - .SingleOrDefault(a => string.Equals(a.PublicAttributeName, field, StringComparison.OrdinalIgnoreCase)); + .SingleOrDefault(a => a.Is(field)); if (attr == null) throw new JsonApiException(400, $"'{_controllerContext.RequestEntity.EntityName}' does not contain '{field}'."); @@ -213,9 +228,7 @@ protected virtual AttrAttribute GetAttribute(string propertyName) return _controllerContext .RequestEntity .Attributes - .Single(attr => - string.Equals(attr.PublicAttributeName, propertyName, StringComparison.OrdinalIgnoreCase) - ); + .Single(attr => attr.Is(propertyName)); } catch (InvalidOperationException e) { diff --git a/src/JsonApiDotNetCore/Services/ScopedServiceProvider.cs b/src/JsonApiDotNetCore/Services/ScopedServiceProvider.cs new file mode 100644 index 0000000000..38e147645f --- /dev/null +++ b/src/JsonApiDotNetCore/Services/ScopedServiceProvider.cs @@ -0,0 +1,28 @@ +using Microsoft.AspNetCore.Http; +using System; + +namespace JsonApiDotNetCore.Services +{ + /// + /// An interface used to separate the registration of the global ServiceProvider + /// from a request scoped service provider. This is useful in cases when we need to + /// manually resolve services from the request scope (e.g. operation processors) + /// + public interface IScopedServiceProvider : IServiceProvider { } + + /// + /// A service provider that uses the current HttpContext request scope + /// + public class RequestScopedServiceProvider : IScopedServiceProvider + { + private readonly IServiceProvider _serviceProvider; + + public RequestScopedServiceProvider(IHttpContextAccessor httpContextAccessor) + { + _serviceProvider = httpContextAccessor.HttpContext.RequestServices; + } + + /// + public object GetService(Type serviceType) => _serviceProvider.GetService(serviceType); + } +} diff --git a/src/JsonApiDotNetCore/api/.gitignore b/src/JsonApiDotNetCore/api/.gitignore new file mode 100644 index 0000000000..da7c71b83a --- /dev/null +++ b/src/JsonApiDotNetCore/api/.gitignore @@ -0,0 +1,4 @@ +############### +# temp file # +############### +*.yml diff --git a/src/JsonApiDotNetCore/api/.manifest b/src/JsonApiDotNetCore/api/.manifest new file mode 100644 index 0000000000..41d94c66fb --- /dev/null +++ b/src/JsonApiDotNetCore/api/.manifest @@ -0,0 +1,691 @@ +{ + "JsonApiDotNetCore.Builders": "JsonApiDotNetCore.Builders.yml", + "JsonApiDotNetCore.Builders.ContextGraphBuilder": "JsonApiDotNetCore.Builders.ContextGraphBuilder.yml", + "JsonApiDotNetCore.Builders.ContextGraphBuilder.AddDbContext``1": "JsonApiDotNetCore.Builders.ContextGraphBuilder.yml", + "JsonApiDotNetCore.Builders.ContextGraphBuilder.AddResource``1(System.String)": "JsonApiDotNetCore.Builders.ContextGraphBuilder.yml", + "JsonApiDotNetCore.Builders.ContextGraphBuilder.AddResource``2(System.String)": "JsonApiDotNetCore.Builders.ContextGraphBuilder.yml", + "JsonApiDotNetCore.Builders.ContextGraphBuilder.Build": "JsonApiDotNetCore.Builders.ContextGraphBuilder.yml", + "JsonApiDotNetCore.Builders.ContextGraphBuilder.DocumentLinks": "JsonApiDotNetCore.Builders.ContextGraphBuilder.yml", + "JsonApiDotNetCore.Builders.ContextGraphBuilder.GetAttributes(System.Type)": "JsonApiDotNetCore.Builders.ContextGraphBuilder.yml", + "JsonApiDotNetCore.Builders.ContextGraphBuilder.GetRelationships(System.Type)": "JsonApiDotNetCore.Builders.ContextGraphBuilder.yml", + "JsonApiDotNetCore.Builders.ContextGraphBuilder.GetRelationshipType(JsonApiDotNetCore.Models.RelationshipAttribute,System.Reflection.PropertyInfo)": "JsonApiDotNetCore.Builders.ContextGraphBuilder.yml", + "JsonApiDotNetCore.Builders.DocumentBuilder": "JsonApiDotNetCore.Builders.DocumentBuilder.yml", + "JsonApiDotNetCore.Builders.DocumentBuilder.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IRequestMeta,JsonApiDotNetCore.Builders.IDocumentBuilderOptionsProvider)": "JsonApiDotNetCore.Builders.DocumentBuilder.yml", + "JsonApiDotNetCore.Builders.DocumentBuilder.Build(JsonApiDotNetCore.Models.IIdentifiable)": "JsonApiDotNetCore.Builders.DocumentBuilder.yml", + "JsonApiDotNetCore.Builders.DocumentBuilder.Build(System.Collections.Generic.IEnumerable{JsonApiDotNetCore.Models.IIdentifiable})": "JsonApiDotNetCore.Builders.DocumentBuilder.yml", + "JsonApiDotNetCore.Builders.DocumentBuilder.GetData(JsonApiDotNetCore.Internal.ContextEntity,JsonApiDotNetCore.Models.IIdentifiable)": "JsonApiDotNetCore.Builders.DocumentBuilder.yml", + "JsonApiDotNetCore.Builders.DocumentBuilderOptions": "JsonApiDotNetCore.Builders.DocumentBuilderOptions.yml", + "JsonApiDotNetCore.Builders.DocumentBuilderOptions.#ctor(System.Boolean)": "JsonApiDotNetCore.Builders.DocumentBuilderOptions.yml", + "JsonApiDotNetCore.Builders.DocumentBuilderOptions.OmitNullValuedAttributes": "JsonApiDotNetCore.Builders.DocumentBuilderOptions.yml", + "JsonApiDotNetCore.Builders.DocumentBuilderOptionsProvider": "JsonApiDotNetCore.Builders.DocumentBuilderOptionsProvider.yml", + "JsonApiDotNetCore.Builders.DocumentBuilderOptionsProvider.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,Microsoft.AspNetCore.Http.IHttpContextAccessor)": "JsonApiDotNetCore.Builders.DocumentBuilderOptionsProvider.yml", + "JsonApiDotNetCore.Builders.DocumentBuilderOptionsProvider.GetDocumentBuilderOptions": "JsonApiDotNetCore.Builders.DocumentBuilderOptionsProvider.yml", + "JsonApiDotNetCore.Builders.IContextGraphBuilder": "JsonApiDotNetCore.Builders.IContextGraphBuilder.yml", + "JsonApiDotNetCore.Builders.IContextGraphBuilder.AddDbContext``1": "JsonApiDotNetCore.Builders.IContextGraphBuilder.yml", + "JsonApiDotNetCore.Builders.IContextGraphBuilder.AddResource``1(System.String)": "JsonApiDotNetCore.Builders.IContextGraphBuilder.yml", + "JsonApiDotNetCore.Builders.IContextGraphBuilder.AddResource``2(System.String)": "JsonApiDotNetCore.Builders.IContextGraphBuilder.yml", + "JsonApiDotNetCore.Builders.IContextGraphBuilder.Build": "JsonApiDotNetCore.Builders.IContextGraphBuilder.yml", + "JsonApiDotNetCore.Builders.IContextGraphBuilder.DocumentLinks": "JsonApiDotNetCore.Builders.IContextGraphBuilder.yml", + "JsonApiDotNetCore.Builders.IDocumentBuilder": "JsonApiDotNetCore.Builders.IDocumentBuilder.yml", + "JsonApiDotNetCore.Builders.IDocumentBuilder.Build(JsonApiDotNetCore.Models.IIdentifiable)": "JsonApiDotNetCore.Builders.IDocumentBuilder.yml", + "JsonApiDotNetCore.Builders.IDocumentBuilder.Build(System.Collections.Generic.IEnumerable{JsonApiDotNetCore.Models.IIdentifiable})": "JsonApiDotNetCore.Builders.IDocumentBuilder.yml", + "JsonApiDotNetCore.Builders.IDocumentBuilder.GetData(JsonApiDotNetCore.Internal.ContextEntity,JsonApiDotNetCore.Models.IIdentifiable)": "JsonApiDotNetCore.Builders.IDocumentBuilder.yml", + "JsonApiDotNetCore.Builders.IDocumentBuilderOptionsProvider": "JsonApiDotNetCore.Builders.IDocumentBuilderOptionsProvider.yml", + "JsonApiDotNetCore.Builders.IDocumentBuilderOptionsProvider.GetDocumentBuilderOptions": "JsonApiDotNetCore.Builders.IDocumentBuilderOptionsProvider.yml", + "JsonApiDotNetCore.Builders.IMetaBuilder": "JsonApiDotNetCore.Builders.IMetaBuilder.yml", + "JsonApiDotNetCore.Builders.IMetaBuilder.Add(System.Collections.Generic.Dictionary{System.String,System.Object})": "JsonApiDotNetCore.Builders.IMetaBuilder.yml", + "JsonApiDotNetCore.Builders.IMetaBuilder.Add(System.String,System.Object)": "JsonApiDotNetCore.Builders.IMetaBuilder.yml", + "JsonApiDotNetCore.Builders.IMetaBuilder.Build": "JsonApiDotNetCore.Builders.IMetaBuilder.yml", + "JsonApiDotNetCore.Builders.LinkBuilder": "JsonApiDotNetCore.Builders.LinkBuilder.yml", + "JsonApiDotNetCore.Builders.LinkBuilder.#ctor(JsonApiDotNetCore.Services.IJsonApiContext)": "JsonApiDotNetCore.Builders.LinkBuilder.yml", + "JsonApiDotNetCore.Builders.LinkBuilder.GetBasePath(Microsoft.AspNetCore.Http.HttpContext,System.String)": "JsonApiDotNetCore.Builders.LinkBuilder.yml", + "JsonApiDotNetCore.Builders.LinkBuilder.GetPageLink(System.Int32,System.Int32)": "JsonApiDotNetCore.Builders.LinkBuilder.yml", + "JsonApiDotNetCore.Builders.LinkBuilder.GetRelatedRelationLink(System.String,System.String,System.String)": "JsonApiDotNetCore.Builders.LinkBuilder.yml", + "JsonApiDotNetCore.Builders.LinkBuilder.GetSelfRelationLink(System.String,System.String,System.String)": "JsonApiDotNetCore.Builders.LinkBuilder.yml", + "JsonApiDotNetCore.Builders.MetaBuilder": "JsonApiDotNetCore.Builders.MetaBuilder.yml", + "JsonApiDotNetCore.Builders.MetaBuilder.Add(System.Collections.Generic.Dictionary{System.String,System.Object})": "JsonApiDotNetCore.Builders.MetaBuilder.yml", + "JsonApiDotNetCore.Builders.MetaBuilder.Add(System.String,System.Object)": "JsonApiDotNetCore.Builders.MetaBuilder.yml", + "JsonApiDotNetCore.Builders.MetaBuilder.Build": "JsonApiDotNetCore.Builders.MetaBuilder.yml", + "JsonApiDotNetCore.Configuration": "JsonApiDotNetCore.Configuration.yml", + "JsonApiDotNetCore.Configuration.JsonApiOptions": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml", + "JsonApiDotNetCore.Configuration.JsonApiOptions.AllowClientGeneratedIds": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml", + "JsonApiDotNetCore.Configuration.JsonApiOptions.AllowCustomQueryParameters": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml", + "JsonApiDotNetCore.Configuration.JsonApiOptions.BuildContextGraph(System.Action{JsonApiDotNetCore.Builders.IContextGraphBuilder})": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml", + "JsonApiDotNetCore.Configuration.JsonApiOptions.BuildContextGraph``1(System.Action{JsonApiDotNetCore.Builders.IContextGraphBuilder})": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml", + "JsonApiDotNetCore.Configuration.JsonApiOptions.ContextGraph": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml", + "JsonApiDotNetCore.Configuration.JsonApiOptions.DefaultPageSize": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml", + "JsonApiDotNetCore.Configuration.JsonApiOptions.DisableErrorSource": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml", + "JsonApiDotNetCore.Configuration.JsonApiOptions.DisableErrorStackTraces": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml", + "JsonApiDotNetCore.Configuration.JsonApiOptions.EnableExtension(JsonApiDotNetCore.Models.JsonApiExtension)": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml", + "JsonApiDotNetCore.Configuration.JsonApiOptions.EnableOperations": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml", + "JsonApiDotNetCore.Configuration.JsonApiOptions.IncludeTotalRecordCount": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml", + "JsonApiDotNetCore.Configuration.JsonApiOptions.JsonContractResolver": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml", + "JsonApiDotNetCore.Configuration.JsonApiOptions.Namespace": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml", + "JsonApiDotNetCore.Configuration.JsonApiOptions.NullAttributeResponseBehavior": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml", + "JsonApiDotNetCore.Configuration.JsonApiOptions.RelativeLinks": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml", + "JsonApiDotNetCore.Configuration.JsonApiOptions.SerializerSettings": "JsonApiDotNetCore.Configuration.JsonApiOptions.yml", + "JsonApiDotNetCore.Configuration.NullAttributeResponseBehavior": "JsonApiDotNetCore.Configuration.NullAttributeResponseBehavior.yml", + "JsonApiDotNetCore.Configuration.NullAttributeResponseBehavior.#ctor(System.Boolean,System.Boolean)": "JsonApiDotNetCore.Configuration.NullAttributeResponseBehavior.yml", + "JsonApiDotNetCore.Configuration.NullAttributeResponseBehavior.AllowClientOverride": "JsonApiDotNetCore.Configuration.NullAttributeResponseBehavior.yml", + "JsonApiDotNetCore.Configuration.NullAttributeResponseBehavior.OmitNullValuedAttributes": "JsonApiDotNetCore.Configuration.NullAttributeResponseBehavior.yml", + "JsonApiDotNetCore.Controllers": "JsonApiDotNetCore.Controllers.yml", + "JsonApiDotNetCore.Controllers.BaseJsonApiController`1": "JsonApiDotNetCore.Controllers.BaseJsonApiController-1.yml", + "JsonApiDotNetCore.Controllers.BaseJsonApiController`1.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IGetAllService{`0,System.Int32},JsonApiDotNetCore.Services.IGetByIdService{`0,System.Int32},JsonApiDotNetCore.Services.IGetRelationshipService{`0,System.Int32},JsonApiDotNetCore.Services.IGetRelationshipsService{`0,System.Int32},JsonApiDotNetCore.Services.ICreateService{`0,System.Int32},JsonApiDotNetCore.Services.IUpdateService{`0,System.Int32},JsonApiDotNetCore.Services.IUpdateRelationshipService{`0,System.Int32},JsonApiDotNetCore.Services.IDeleteService{`0,System.Int32})": "JsonApiDotNetCore.Controllers.BaseJsonApiController-1.yml", + "JsonApiDotNetCore.Controllers.BaseJsonApiController`1.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceQueryService{`0,System.Int32},JsonApiDotNetCore.Services.IResourceCmdService{`0,System.Int32})": "JsonApiDotNetCore.Controllers.BaseJsonApiController-1.yml", + "JsonApiDotNetCore.Controllers.BaseJsonApiController`1.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceService{`0,System.Int32})": "JsonApiDotNetCore.Controllers.BaseJsonApiController-1.yml", + "JsonApiDotNetCore.Controllers.BaseJsonApiController`2": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IGetAllService{`0,`1},JsonApiDotNetCore.Services.IGetByIdService{`0,`1},JsonApiDotNetCore.Services.IGetRelationshipService{`0,`1},JsonApiDotNetCore.Services.IGetRelationshipsService{`0,`1},JsonApiDotNetCore.Services.ICreateService{`0,`1},JsonApiDotNetCore.Services.IUpdateService{`0,`1},JsonApiDotNetCore.Services.IUpdateRelationshipService{`0,`1},JsonApiDotNetCore.Services.IDeleteService{`0,`1})": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceQueryService{`0,`1},JsonApiDotNetCore.Services.IResourceCmdService{`0,`1})": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceService{`0,`1})": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.DeleteAsync(`1)": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.GetAsync": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.GetAsync(`1)": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.GetRelationshipAsync(`1,System.String)": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.GetRelationshipsAsync(`1,System.String)": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.PatchAsync(`1,`0)": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.PatchRelationshipsAsync(`1,System.String,System.Collections.Generic.List{JsonApiDotNetCore.Models.DocumentData})": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.BaseJsonApiController`2.PostAsync(`0)": "JsonApiDotNetCore.Controllers.BaseJsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.DisableQueryAttribute": "JsonApiDotNetCore.Controllers.DisableQueryAttribute.yml", + "JsonApiDotNetCore.Controllers.DisableQueryAttribute.#ctor(JsonApiDotNetCore.Controllers.QueryParams)": "JsonApiDotNetCore.Controllers.DisableQueryAttribute.yml", + "JsonApiDotNetCore.Controllers.DisableQueryAttribute.QueryParams": "JsonApiDotNetCore.Controllers.DisableQueryAttribute.yml", + "JsonApiDotNetCore.Controllers.DisableRoutingConventionAttribute": "JsonApiDotNetCore.Controllers.DisableRoutingConventionAttribute.yml", + "JsonApiDotNetCore.Controllers.HttpReadOnlyAttribute": "JsonApiDotNetCore.Controllers.HttpReadOnlyAttribute.yml", + "JsonApiDotNetCore.Controllers.HttpReadOnlyAttribute.Methods": "JsonApiDotNetCore.Controllers.HttpReadOnlyAttribute.yml", + "JsonApiDotNetCore.Controllers.HttpRestrictAttribute": "JsonApiDotNetCore.Controllers.HttpRestrictAttribute.yml", + "JsonApiDotNetCore.Controllers.HttpRestrictAttribute.Methods": "JsonApiDotNetCore.Controllers.HttpRestrictAttribute.yml", + "JsonApiDotNetCore.Controllers.HttpRestrictAttribute.OnActionExecutionAsync(Microsoft.AspNetCore.Mvc.Filters.ActionExecutingContext,Microsoft.AspNetCore.Mvc.Filters.ActionExecutionDelegate)": "JsonApiDotNetCore.Controllers.HttpRestrictAttribute.yml", + "JsonApiDotNetCore.Controllers.JsonApiCmdController`1": "JsonApiDotNetCore.Controllers.JsonApiCmdController-1.yml", + "JsonApiDotNetCore.Controllers.JsonApiCmdController`1.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceService{`0,System.Int32})": "JsonApiDotNetCore.Controllers.JsonApiCmdController-1.yml", + "JsonApiDotNetCore.Controllers.JsonApiCmdController`2": "JsonApiDotNetCore.Controllers.JsonApiCmdController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiCmdController`2.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceService{`0,`1})": "JsonApiDotNetCore.Controllers.JsonApiCmdController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiCmdController`2.DeleteAsync(`1)": "JsonApiDotNetCore.Controllers.JsonApiCmdController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiCmdController`2.PatchAsync(`1,`0)": "JsonApiDotNetCore.Controllers.JsonApiCmdController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiCmdController`2.PatchRelationshipsAsync(`1,System.String,System.Collections.Generic.List{JsonApiDotNetCore.Models.DocumentData})": "JsonApiDotNetCore.Controllers.JsonApiCmdController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiCmdController`2.PostAsync(`0)": "JsonApiDotNetCore.Controllers.JsonApiCmdController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiController`1": "JsonApiDotNetCore.Controllers.JsonApiController-1.yml", + "JsonApiDotNetCore.Controllers.JsonApiController`1.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IGetAllService{`0,System.Int32},JsonApiDotNetCore.Services.IGetByIdService{`0,System.Int32},JsonApiDotNetCore.Services.IGetRelationshipService{`0,System.Int32},JsonApiDotNetCore.Services.IGetRelationshipsService{`0,System.Int32},JsonApiDotNetCore.Services.ICreateService{`0,System.Int32},JsonApiDotNetCore.Services.IUpdateService{`0,System.Int32},JsonApiDotNetCore.Services.IUpdateRelationshipService{`0,System.Int32},JsonApiDotNetCore.Services.IDeleteService{`0,System.Int32})": "JsonApiDotNetCore.Controllers.JsonApiController-1.yml", + "JsonApiDotNetCore.Controllers.JsonApiController`1.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceService{`0,System.Int32},Microsoft.Extensions.Logging.ILoggerFactory)": "JsonApiDotNetCore.Controllers.JsonApiController-1.yml", + "JsonApiDotNetCore.Controllers.JsonApiController`2": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiController`2.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IGetAllService{`0,`1},JsonApiDotNetCore.Services.IGetByIdService{`0,`1},JsonApiDotNetCore.Services.IGetRelationshipService{`0,`1},JsonApiDotNetCore.Services.IGetRelationshipsService{`0,`1},JsonApiDotNetCore.Services.ICreateService{`0,`1},JsonApiDotNetCore.Services.IUpdateService{`0,`1},JsonApiDotNetCore.Services.IUpdateRelationshipService{`0,`1},JsonApiDotNetCore.Services.IDeleteService{`0,`1})": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiController`2.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceService{`0,`1})": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiController`2.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceService{`0,`1},Microsoft.Extensions.Logging.ILoggerFactory)": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiController`2.DeleteAsync(`1)": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiController`2.GetAsync": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiController`2.GetAsync(`1)": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiController`2.GetRelationshipAsync(`1,System.String)": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiController`2.GetRelationshipsAsync(`1,System.String)": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiController`2.PatchAsync(`1,`0)": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiController`2.PatchRelationshipsAsync(`1,System.String,System.Collections.Generic.List{JsonApiDotNetCore.Models.DocumentData})": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiController`2.PostAsync(`0)": "JsonApiDotNetCore.Controllers.JsonApiController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiControllerMixin": "JsonApiDotNetCore.Controllers.JsonApiControllerMixin.yml", + "JsonApiDotNetCore.Controllers.JsonApiControllerMixin.Error(JsonApiDotNetCore.Internal.Error)": "JsonApiDotNetCore.Controllers.JsonApiControllerMixin.yml", + "JsonApiDotNetCore.Controllers.JsonApiControllerMixin.Errors(JsonApiDotNetCore.Internal.ErrorCollection)": "JsonApiDotNetCore.Controllers.JsonApiControllerMixin.yml", + "JsonApiDotNetCore.Controllers.JsonApiControllerMixin.Forbidden": "JsonApiDotNetCore.Controllers.JsonApiControllerMixin.yml", + "JsonApiDotNetCore.Controllers.JsonApiControllerMixin.UnprocessableEntity": "JsonApiDotNetCore.Controllers.JsonApiControllerMixin.yml", + "JsonApiDotNetCore.Controllers.JsonApiOperationsController": "JsonApiDotNetCore.Controllers.JsonApiOperationsController.yml", + "JsonApiDotNetCore.Controllers.JsonApiOperationsController.#ctor(JsonApiDotNetCore.Services.Operations.IOperationsProcessor)": "JsonApiDotNetCore.Controllers.JsonApiOperationsController.yml", + "JsonApiDotNetCore.Controllers.JsonApiOperationsController.PatchAsync(JsonApiDotNetCore.Models.Operations.OperationsDocument)": "JsonApiDotNetCore.Controllers.JsonApiOperationsController.yml", + "JsonApiDotNetCore.Controllers.JsonApiQueryController`1": "JsonApiDotNetCore.Controllers.JsonApiQueryController-1.yml", + "JsonApiDotNetCore.Controllers.JsonApiQueryController`1.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceService{`0,System.Int32})": "JsonApiDotNetCore.Controllers.JsonApiQueryController-1.yml", + "JsonApiDotNetCore.Controllers.JsonApiQueryController`2": "JsonApiDotNetCore.Controllers.JsonApiQueryController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiQueryController`2.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Services.IResourceService{`0,`1})": "JsonApiDotNetCore.Controllers.JsonApiQueryController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiQueryController`2.GetAsync": "JsonApiDotNetCore.Controllers.JsonApiQueryController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiQueryController`2.GetAsync(`1)": "JsonApiDotNetCore.Controllers.JsonApiQueryController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiQueryController`2.GetRelationshipAsync(`1,System.String)": "JsonApiDotNetCore.Controllers.JsonApiQueryController-2.yml", + "JsonApiDotNetCore.Controllers.JsonApiQueryController`2.GetRelationshipsAsync(`1,System.String)": "JsonApiDotNetCore.Controllers.JsonApiQueryController-2.yml", + "JsonApiDotNetCore.Controllers.NoHttpDeleteAttribute": "JsonApiDotNetCore.Controllers.NoHttpDeleteAttribute.yml", + "JsonApiDotNetCore.Controllers.NoHttpDeleteAttribute.Methods": "JsonApiDotNetCore.Controllers.NoHttpDeleteAttribute.yml", + "JsonApiDotNetCore.Controllers.NoHttpPatchAttribute": "JsonApiDotNetCore.Controllers.NoHttpPatchAttribute.yml", + "JsonApiDotNetCore.Controllers.NoHttpPatchAttribute.Methods": "JsonApiDotNetCore.Controllers.NoHttpPatchAttribute.yml", + "JsonApiDotNetCore.Controllers.NoHttpPostAttribute": "JsonApiDotNetCore.Controllers.NoHttpPostAttribute.yml", + "JsonApiDotNetCore.Controllers.NoHttpPostAttribute.Methods": "JsonApiDotNetCore.Controllers.NoHttpPostAttribute.yml", + "JsonApiDotNetCore.Controllers.QueryParams": "JsonApiDotNetCore.Controllers.QueryParams.yml", + "JsonApiDotNetCore.Controllers.QueryParams.All": "JsonApiDotNetCore.Controllers.QueryParams.yml", + "JsonApiDotNetCore.Controllers.QueryParams.Fields": "JsonApiDotNetCore.Controllers.QueryParams.yml", + "JsonApiDotNetCore.Controllers.QueryParams.Filter": "JsonApiDotNetCore.Controllers.QueryParams.yml", + "JsonApiDotNetCore.Controllers.QueryParams.Include": "JsonApiDotNetCore.Controllers.QueryParams.yml", + "JsonApiDotNetCore.Controllers.QueryParams.None": "JsonApiDotNetCore.Controllers.QueryParams.yml", + "JsonApiDotNetCore.Controllers.QueryParams.Page": "JsonApiDotNetCore.Controllers.QueryParams.yml", + "JsonApiDotNetCore.Controllers.QueryParams.Sort": "JsonApiDotNetCore.Controllers.QueryParams.yml", + "JsonApiDotNetCore.Data": "JsonApiDotNetCore.Data.yml", + "JsonApiDotNetCore.Data.DbContextResolver`1": "JsonApiDotNetCore.Data.DbContextResolver-1.yml", + "JsonApiDotNetCore.Data.DbContextResolver`1.#ctor(`0)": "JsonApiDotNetCore.Data.DbContextResolver-1.yml", + "JsonApiDotNetCore.Data.DbContextResolver`1.GetContext": "JsonApiDotNetCore.Data.DbContextResolver-1.yml", + "JsonApiDotNetCore.Data.DbContextResolver`1.GetDbSet``1": "JsonApiDotNetCore.Data.DbContextResolver-1.yml", + "JsonApiDotNetCore.Data.DefaultEntityRepository`1": "JsonApiDotNetCore.Data.DefaultEntityRepository-1.yml", + "JsonApiDotNetCore.Data.DefaultEntityRepository`1.#ctor(Microsoft.Extensions.Logging.ILoggerFactory,JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Data.IDbContextResolver)": "JsonApiDotNetCore.Data.DefaultEntityRepository-1.yml", + "JsonApiDotNetCore.Data.DefaultEntityRepository`2": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml", + "JsonApiDotNetCore.Data.DefaultEntityRepository`2.#ctor(Microsoft.Extensions.Logging.ILoggerFactory,JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Data.IDbContextResolver)": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml", + "JsonApiDotNetCore.Data.DefaultEntityRepository`2.CountAsync(System.Linq.IQueryable{`0})": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml", + "JsonApiDotNetCore.Data.DefaultEntityRepository`2.CreateAsync(`0)": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml", + "JsonApiDotNetCore.Data.DefaultEntityRepository`2.DeleteAsync(`1)": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml", + "JsonApiDotNetCore.Data.DefaultEntityRepository`2.Filter(System.Linq.IQueryable{`0},JsonApiDotNetCore.Internal.Query.FilterQuery)": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml", + "JsonApiDotNetCore.Data.DefaultEntityRepository`2.FirstOrDefaultAsync(System.Linq.IQueryable{`0})": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml", + "JsonApiDotNetCore.Data.DefaultEntityRepository`2.Get": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml", + "JsonApiDotNetCore.Data.DefaultEntityRepository`2.GetAndIncludeAsync(`1,System.String)": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml", + "JsonApiDotNetCore.Data.DefaultEntityRepository`2.GetAsync(`1)": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml", + "JsonApiDotNetCore.Data.DefaultEntityRepository`2.Include(System.Linq.IQueryable{`0},System.String)": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml", + "JsonApiDotNetCore.Data.DefaultEntityRepository`2.PageAsync(System.Linq.IQueryable{`0},System.Int32,System.Int32)": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml", + "JsonApiDotNetCore.Data.DefaultEntityRepository`2.Sort(System.Linq.IQueryable{`0},System.Collections.Generic.List{JsonApiDotNetCore.Internal.Query.SortQuery})": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml", + "JsonApiDotNetCore.Data.DefaultEntityRepository`2.ToListAsync(System.Linq.IQueryable{`0})": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml", + "JsonApiDotNetCore.Data.DefaultEntityRepository`2.UpdateAsync(`1,`0)": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml", + "JsonApiDotNetCore.Data.DefaultEntityRepository`2.UpdateRelationshipsAsync(System.Object,JsonApiDotNetCore.Models.RelationshipAttribute,System.Collections.Generic.IEnumerable{System.String})": "JsonApiDotNetCore.Data.DefaultEntityRepository-2.yml", + "JsonApiDotNetCore.Data.IDbContextResolver": "JsonApiDotNetCore.Data.IDbContextResolver.yml", + "JsonApiDotNetCore.Data.IDbContextResolver.GetContext": "JsonApiDotNetCore.Data.IDbContextResolver.yml", + "JsonApiDotNetCore.Data.IDbContextResolver.GetDbSet``1": "JsonApiDotNetCore.Data.IDbContextResolver.yml", + "JsonApiDotNetCore.Data.IEntityReadRepository`1": "JsonApiDotNetCore.Data.IEntityReadRepository-1.yml", + "JsonApiDotNetCore.Data.IEntityReadRepository`2": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml", + "JsonApiDotNetCore.Data.IEntityReadRepository`2.CountAsync(System.Linq.IQueryable{`0})": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml", + "JsonApiDotNetCore.Data.IEntityReadRepository`2.Filter(System.Linq.IQueryable{`0},JsonApiDotNetCore.Internal.Query.FilterQuery)": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml", + "JsonApiDotNetCore.Data.IEntityReadRepository`2.FirstOrDefaultAsync(System.Linq.IQueryable{`0})": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml", + "JsonApiDotNetCore.Data.IEntityReadRepository`2.Get": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml", + "JsonApiDotNetCore.Data.IEntityReadRepository`2.GetAndIncludeAsync(`1,System.String)": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml", + "JsonApiDotNetCore.Data.IEntityReadRepository`2.GetAsync(`1)": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml", + "JsonApiDotNetCore.Data.IEntityReadRepository`2.Include(System.Linq.IQueryable{`0},System.String)": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml", + "JsonApiDotNetCore.Data.IEntityReadRepository`2.PageAsync(System.Linq.IQueryable{`0},System.Int32,System.Int32)": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml", + "JsonApiDotNetCore.Data.IEntityReadRepository`2.Sort(System.Linq.IQueryable{`0},System.Collections.Generic.List{JsonApiDotNetCore.Internal.Query.SortQuery})": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml", + "JsonApiDotNetCore.Data.IEntityReadRepository`2.ToListAsync(System.Linq.IQueryable{`0})": "JsonApiDotNetCore.Data.IEntityReadRepository-2.yml", + "JsonApiDotNetCore.Data.IEntityRepository`1": "JsonApiDotNetCore.Data.IEntityRepository-1.yml", + "JsonApiDotNetCore.Data.IEntityRepository`2": "JsonApiDotNetCore.Data.IEntityRepository-2.yml", + "JsonApiDotNetCore.Data.IEntityWriteRepository`1": "JsonApiDotNetCore.Data.IEntityWriteRepository-1.yml", + "JsonApiDotNetCore.Data.IEntityWriteRepository`2": "JsonApiDotNetCore.Data.IEntityWriteRepository-2.yml", + "JsonApiDotNetCore.Data.IEntityWriteRepository`2.CreateAsync(`0)": "JsonApiDotNetCore.Data.IEntityWriteRepository-2.yml", + "JsonApiDotNetCore.Data.IEntityWriteRepository`2.DeleteAsync(`1)": "JsonApiDotNetCore.Data.IEntityWriteRepository-2.yml", + "JsonApiDotNetCore.Data.IEntityWriteRepository`2.UpdateAsync(`1,`0)": "JsonApiDotNetCore.Data.IEntityWriteRepository-2.yml", + "JsonApiDotNetCore.Data.IEntityWriteRepository`2.UpdateRelationshipsAsync(System.Object,JsonApiDotNetCore.Models.RelationshipAttribute,System.Collections.Generic.IEnumerable{System.String})": "JsonApiDotNetCore.Data.IEntityWriteRepository-2.yml", + "JsonApiDotNetCore.Extensions": "JsonApiDotNetCore.Extensions.yml", + "JsonApiDotNetCore.Extensions.DbContextExtensions": "JsonApiDotNetCore.Extensions.DbContextExtensions.yml", + "JsonApiDotNetCore.Extensions.DbContextExtensions.GetDbSet``1(Microsoft.EntityFrameworkCore.DbContext)": "JsonApiDotNetCore.Extensions.DbContextExtensions.yml", + "JsonApiDotNetCore.Extensions.IApplicationBuilderExtensions": "JsonApiDotNetCore.Extensions.IApplicationBuilderExtensions.yml", + "JsonApiDotNetCore.Extensions.IApplicationBuilderExtensions.UseJsonApi(Microsoft.AspNetCore.Builder.IApplicationBuilder,System.Boolean)": "JsonApiDotNetCore.Extensions.IApplicationBuilderExtensions.yml", + "JsonApiDotNetCore.Extensions.IQueryableExtensions": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml", + "JsonApiDotNetCore.Extensions.IQueryableExtensions.Filter``1(System.Linq.IQueryable{``0},JsonApiDotNetCore.Internal.Query.AttrFilterQuery)": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml", + "JsonApiDotNetCore.Extensions.IQueryableExtensions.Filter``1(System.Linq.IQueryable{``0},JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery)": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml", + "JsonApiDotNetCore.Extensions.IQueryableExtensions.Filter``1(System.Linq.IQueryable{``0},JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Internal.Query.FilterQuery)": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml", + "JsonApiDotNetCore.Extensions.IQueryableExtensions.OrderBy``1(System.Linq.IQueryable{``0},System.String)": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml", + "JsonApiDotNetCore.Extensions.IQueryableExtensions.OrderByDescending``1(System.Linq.IQueryable{``0},System.String)": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml", + "JsonApiDotNetCore.Extensions.IQueryableExtensions.PageForward``1(System.Linq.IQueryable{``0},System.Int32,System.Int32)": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml", + "JsonApiDotNetCore.Extensions.IQueryableExtensions.Select``1(System.Linq.IQueryable{``0},System.Collections.Generic.List{System.String})": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml", + "JsonApiDotNetCore.Extensions.IQueryableExtensions.Sort``1(System.Linq.IOrderedQueryable{``0},JsonApiDotNetCore.Internal.Query.SortQuery)": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml", + "JsonApiDotNetCore.Extensions.IQueryableExtensions.Sort``1(System.Linq.IQueryable{``0},JsonApiDotNetCore.Internal.Query.SortQuery)": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml", + "JsonApiDotNetCore.Extensions.IQueryableExtensions.Sort``1(System.Linq.IQueryable{``0},System.Collections.Generic.List{JsonApiDotNetCore.Internal.Query.SortQuery})": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml", + "JsonApiDotNetCore.Extensions.IQueryableExtensions.ThenBy``1(System.Linq.IOrderedQueryable{``0},System.String)": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml", + "JsonApiDotNetCore.Extensions.IQueryableExtensions.ThenByDescending``1(System.Linq.IOrderedQueryable{``0},System.String)": "JsonApiDotNetCore.Extensions.IQueryableExtensions.yml", + "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions": "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.yml", + "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.AddJsonApi(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{JsonApiDotNetCore.Configuration.JsonApiOptions},Microsoft.Extensions.DependencyInjection.IMvcBuilder)": "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.yml", + "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.AddJsonApi``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)": "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.yml", + "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.AddJsonApi``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{JsonApiDotNetCore.Configuration.JsonApiOptions})": "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.yml", + "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.AddJsonApi``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{JsonApiDotNetCore.Configuration.JsonApiOptions},Microsoft.Extensions.DependencyInjection.IMvcBuilder)": "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.yml", + "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.AddJsonApiInternals(Microsoft.Extensions.DependencyInjection.IServiceCollection,JsonApiDotNetCore.Configuration.JsonApiOptions)": "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.yml", + "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.AddJsonApiInternals``1(Microsoft.Extensions.DependencyInjection.IServiceCollection,JsonApiDotNetCore.Configuration.JsonApiOptions)": "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.yml", + "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.SerializeAsJsonApi(Microsoft.AspNetCore.Mvc.MvcOptions,JsonApiDotNetCore.Configuration.JsonApiOptions)": "JsonApiDotNetCore.Extensions.IServiceCollectionExtensions.yml", + "JsonApiDotNetCore.Extensions.StringExtensions": "JsonApiDotNetCore.Extensions.StringExtensions.yml", + "JsonApiDotNetCore.Extensions.StringExtensions.Dasherize(System.String)": "JsonApiDotNetCore.Extensions.StringExtensions.yml", + "JsonApiDotNetCore.Extensions.StringExtensions.ToProperCase(System.String)": "JsonApiDotNetCore.Extensions.StringExtensions.yml", + "JsonApiDotNetCore.Formatters": "JsonApiDotNetCore.Formatters.yml", + "JsonApiDotNetCore.Formatters.IJsonApiReader": "JsonApiDotNetCore.Formatters.IJsonApiReader.yml", + "JsonApiDotNetCore.Formatters.IJsonApiReader.ReadAsync(Microsoft.AspNetCore.Mvc.Formatters.InputFormatterContext)": "JsonApiDotNetCore.Formatters.IJsonApiReader.yml", + "JsonApiDotNetCore.Formatters.IJsonApiWriter": "JsonApiDotNetCore.Formatters.IJsonApiWriter.yml", + "JsonApiDotNetCore.Formatters.IJsonApiWriter.WriteAsync(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterWriteContext)": "JsonApiDotNetCore.Formatters.IJsonApiWriter.yml", + "JsonApiDotNetCore.Formatters.JsonApiInputFormatter": "JsonApiDotNetCore.Formatters.JsonApiInputFormatter.yml", + "JsonApiDotNetCore.Formatters.JsonApiInputFormatter.CanRead(Microsoft.AspNetCore.Mvc.Formatters.InputFormatterContext)": "JsonApiDotNetCore.Formatters.JsonApiInputFormatter.yml", + "JsonApiDotNetCore.Formatters.JsonApiInputFormatter.ReadAsync(Microsoft.AspNetCore.Mvc.Formatters.InputFormatterContext)": "JsonApiDotNetCore.Formatters.JsonApiInputFormatter.yml", + "JsonApiDotNetCore.Formatters.JsonApiOutputFormatter": "JsonApiDotNetCore.Formatters.JsonApiOutputFormatter.yml", + "JsonApiDotNetCore.Formatters.JsonApiOutputFormatter.CanWriteResult(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterCanWriteContext)": "JsonApiDotNetCore.Formatters.JsonApiOutputFormatter.yml", + "JsonApiDotNetCore.Formatters.JsonApiOutputFormatter.WriteAsync(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterWriteContext)": "JsonApiDotNetCore.Formatters.JsonApiOutputFormatter.yml", + "JsonApiDotNetCore.Formatters.JsonApiReader": "JsonApiDotNetCore.Formatters.JsonApiReader.yml", + "JsonApiDotNetCore.Formatters.JsonApiReader.#ctor(JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Services.IJsonApiContext,Microsoft.Extensions.Logging.ILoggerFactory)": "JsonApiDotNetCore.Formatters.JsonApiReader.yml", + "JsonApiDotNetCore.Formatters.JsonApiReader.ReadAsync(Microsoft.AspNetCore.Mvc.Formatters.InputFormatterContext)": "JsonApiDotNetCore.Formatters.JsonApiReader.yml", + "JsonApiDotNetCore.Formatters.JsonApiWriter": "JsonApiDotNetCore.Formatters.JsonApiWriter.yml", + "JsonApiDotNetCore.Formatters.JsonApiWriter.#ctor(JsonApiDotNetCore.Serialization.IJsonApiSerializer,Microsoft.Extensions.Logging.ILoggerFactory)": "JsonApiDotNetCore.Formatters.JsonApiWriter.yml", + "JsonApiDotNetCore.Formatters.JsonApiWriter.WriteAsync(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterWriteContext)": "JsonApiDotNetCore.Formatters.JsonApiWriter.yml", + "JsonApiDotNetCore.Internal": "JsonApiDotNetCore.Internal.yml", + "JsonApiDotNetCore.Internal.Constants": "JsonApiDotNetCore.Internal.Constants.yml", + "JsonApiDotNetCore.Internal.Constants.AcceptHeader": "JsonApiDotNetCore.Internal.Constants.yml", + "JsonApiDotNetCore.Internal.Constants.ContentType": "JsonApiDotNetCore.Internal.Constants.yml", + "JsonApiDotNetCore.Internal.ContextEntity": "JsonApiDotNetCore.Internal.ContextEntity.yml", + "JsonApiDotNetCore.Internal.ContextEntity.Attributes": "JsonApiDotNetCore.Internal.ContextEntity.yml", + "JsonApiDotNetCore.Internal.ContextEntity.EntityName": "JsonApiDotNetCore.Internal.ContextEntity.yml", + "JsonApiDotNetCore.Internal.ContextEntity.EntityType": "JsonApiDotNetCore.Internal.ContextEntity.yml", + "JsonApiDotNetCore.Internal.ContextEntity.IdentityType": "JsonApiDotNetCore.Internal.ContextEntity.yml", + "JsonApiDotNetCore.Internal.ContextEntity.Links": "JsonApiDotNetCore.Internal.ContextEntity.yml", + "JsonApiDotNetCore.Internal.ContextEntity.Relationships": "JsonApiDotNetCore.Internal.ContextEntity.yml", + "JsonApiDotNetCore.Internal.ContextGraph": "JsonApiDotNetCore.Internal.ContextGraph.yml", + "JsonApiDotNetCore.Internal.ContextGraph.#ctor": "JsonApiDotNetCore.Internal.ContextGraph.yml", + "JsonApiDotNetCore.Internal.ContextGraph.#ctor(System.Collections.Generic.List{JsonApiDotNetCore.Internal.ContextEntity},System.Boolean)": "JsonApiDotNetCore.Internal.ContextGraph.yml", + "JsonApiDotNetCore.Internal.ContextGraph.GetContextEntity(System.String)": "JsonApiDotNetCore.Internal.ContextGraph.yml", + "JsonApiDotNetCore.Internal.ContextGraph.GetContextEntity(System.Type)": "JsonApiDotNetCore.Internal.ContextGraph.yml", + "JsonApiDotNetCore.Internal.ContextGraph.GetRelationship``1(``0,System.String)": "JsonApiDotNetCore.Internal.ContextGraph.yml", + "JsonApiDotNetCore.Internal.ContextGraph.GetRelationshipName``1(System.String)": "JsonApiDotNetCore.Internal.ContextGraph.yml", + "JsonApiDotNetCore.Internal.ContextGraph.UsesDbContext": "JsonApiDotNetCore.Internal.ContextGraph.yml", + "JsonApiDotNetCore.Internal.DasherizedRoutingConvention": "JsonApiDotNetCore.Internal.DasherizedRoutingConvention.yml", + "JsonApiDotNetCore.Internal.DasherizedRoutingConvention.#ctor(System.String)": "JsonApiDotNetCore.Internal.DasherizedRoutingConvention.yml", + "JsonApiDotNetCore.Internal.DasherizedRoutingConvention.Apply(Microsoft.AspNetCore.Mvc.ApplicationModels.ApplicationModel)": "JsonApiDotNetCore.Internal.DasherizedRoutingConvention.yml", + "JsonApiDotNetCore.Internal.Error": "JsonApiDotNetCore.Internal.Error.yml", + "JsonApiDotNetCore.Internal.Error.#ctor": "JsonApiDotNetCore.Internal.Error.yml", + "JsonApiDotNetCore.Internal.Error.#ctor(System.Int32,System.String,JsonApiDotNetCore.Internal.ErrorMeta,System.String)": "JsonApiDotNetCore.Internal.Error.yml", + "JsonApiDotNetCore.Internal.Error.#ctor(System.Int32,System.String,System.String,JsonApiDotNetCore.Internal.ErrorMeta,System.String)": "JsonApiDotNetCore.Internal.Error.yml", + "JsonApiDotNetCore.Internal.Error.#ctor(System.String,System.String,JsonApiDotNetCore.Internal.ErrorMeta,System.String)": "JsonApiDotNetCore.Internal.Error.yml", + "JsonApiDotNetCore.Internal.Error.#ctor(System.String,System.String,System.String,JsonApiDotNetCore.Internal.ErrorMeta,System.String)": "JsonApiDotNetCore.Internal.Error.yml", + "JsonApiDotNetCore.Internal.Error.Detail": "JsonApiDotNetCore.Internal.Error.yml", + "JsonApiDotNetCore.Internal.Error.Meta": "JsonApiDotNetCore.Internal.Error.yml", + "JsonApiDotNetCore.Internal.Error.ShouldSerializeMeta": "JsonApiDotNetCore.Internal.Error.yml", + "JsonApiDotNetCore.Internal.Error.ShouldSerializeSource": "JsonApiDotNetCore.Internal.Error.yml", + "JsonApiDotNetCore.Internal.Error.Source": "JsonApiDotNetCore.Internal.Error.yml", + "JsonApiDotNetCore.Internal.Error.Status": "JsonApiDotNetCore.Internal.Error.yml", + "JsonApiDotNetCore.Internal.Error.StatusCode": "JsonApiDotNetCore.Internal.Error.yml", + "JsonApiDotNetCore.Internal.Error.Title": "JsonApiDotNetCore.Internal.Error.yml", + "JsonApiDotNetCore.Internal.ErrorCollection": "JsonApiDotNetCore.Internal.ErrorCollection.yml", + "JsonApiDotNetCore.Internal.ErrorCollection.#ctor": "JsonApiDotNetCore.Internal.ErrorCollection.yml", + "JsonApiDotNetCore.Internal.ErrorCollection.Add(JsonApiDotNetCore.Internal.Error)": "JsonApiDotNetCore.Internal.ErrorCollection.yml", + "JsonApiDotNetCore.Internal.ErrorCollection.Errors": "JsonApiDotNetCore.Internal.ErrorCollection.yml", + "JsonApiDotNetCore.Internal.ErrorCollection.GetJson": "JsonApiDotNetCore.Internal.ErrorCollection.yml", + "JsonApiDotNetCore.Internal.ErrorMeta": "JsonApiDotNetCore.Internal.ErrorMeta.yml", + "JsonApiDotNetCore.Internal.ErrorMeta.FromException(System.Exception)": "JsonApiDotNetCore.Internal.ErrorMeta.yml", + "JsonApiDotNetCore.Internal.ErrorMeta.StackTrace": "JsonApiDotNetCore.Internal.ErrorMeta.yml", + "JsonApiDotNetCore.Internal.Generics": "JsonApiDotNetCore.Internal.Generics.yml", + "JsonApiDotNetCore.Internal.Generics.GenericProcessor`1": "JsonApiDotNetCore.Internal.Generics.GenericProcessor-1.yml", + "JsonApiDotNetCore.Internal.Generics.GenericProcessor`1.#ctor(JsonApiDotNetCore.Data.IDbContextResolver)": "JsonApiDotNetCore.Internal.Generics.GenericProcessor-1.yml", + "JsonApiDotNetCore.Internal.Generics.GenericProcessor`2": "JsonApiDotNetCore.Internal.Generics.GenericProcessor-2.yml", + "JsonApiDotNetCore.Internal.Generics.GenericProcessor`2.#ctor(JsonApiDotNetCore.Data.IDbContextResolver)": "JsonApiDotNetCore.Internal.Generics.GenericProcessor-2.yml", + "JsonApiDotNetCore.Internal.Generics.GenericProcessor`2.SetRelationships(System.Object,JsonApiDotNetCore.Models.RelationshipAttribute,System.Collections.Generic.IEnumerable{System.String})": "JsonApiDotNetCore.Internal.Generics.GenericProcessor-2.yml", + "JsonApiDotNetCore.Internal.Generics.GenericProcessor`2.UpdateRelationshipsAsync(System.Object,JsonApiDotNetCore.Models.RelationshipAttribute,System.Collections.Generic.IEnumerable{System.String})": "JsonApiDotNetCore.Internal.Generics.GenericProcessor-2.yml", + "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory": "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.yml", + "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.#ctor(JsonApiDotNetCore.Services.IScopedServiceProvider)": "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.yml", + "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.GetProcessor``1(System.Type,System.Type)": "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.yml", + "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.GetProcessor``1(System.Type,System.Type,System.Type)": "JsonApiDotNetCore.Internal.Generics.GenericProcessorFactory.yml", + "JsonApiDotNetCore.Internal.Generics.IGenericProcessor": "JsonApiDotNetCore.Internal.Generics.IGenericProcessor.yml", + "JsonApiDotNetCore.Internal.Generics.IGenericProcessor.SetRelationships(System.Object,JsonApiDotNetCore.Models.RelationshipAttribute,System.Collections.Generic.IEnumerable{System.String})": "JsonApiDotNetCore.Internal.Generics.IGenericProcessor.yml", + "JsonApiDotNetCore.Internal.Generics.IGenericProcessor.UpdateRelationshipsAsync(System.Object,JsonApiDotNetCore.Models.RelationshipAttribute,System.Collections.Generic.IEnumerable{System.String})": "JsonApiDotNetCore.Internal.Generics.IGenericProcessor.yml", + "JsonApiDotNetCore.Internal.Generics.IGenericProcessorFactory": "JsonApiDotNetCore.Internal.Generics.IGenericProcessorFactory.yml", + "JsonApiDotNetCore.Internal.Generics.IGenericProcessorFactory.GetProcessor``1(System.Type,System.Type)": "JsonApiDotNetCore.Internal.Generics.IGenericProcessorFactory.yml", + "JsonApiDotNetCore.Internal.Generics.IGenericProcessorFactory.GetProcessor``1(System.Type,System.Type,System.Type)": "JsonApiDotNetCore.Internal.Generics.IGenericProcessorFactory.yml", + "JsonApiDotNetCore.Internal.IContextGraph": "JsonApiDotNetCore.Internal.IContextGraph.yml", + "JsonApiDotNetCore.Internal.IContextGraph.GetContextEntity(System.String)": "JsonApiDotNetCore.Internal.IContextGraph.yml", + "JsonApiDotNetCore.Internal.IContextGraph.GetContextEntity(System.Type)": "JsonApiDotNetCore.Internal.IContextGraph.yml", + "JsonApiDotNetCore.Internal.IContextGraph.GetRelationship``1(``0,System.String)": "JsonApiDotNetCore.Internal.IContextGraph.yml", + "JsonApiDotNetCore.Internal.IContextGraph.GetRelationshipName``1(System.String)": "JsonApiDotNetCore.Internal.IContextGraph.yml", + "JsonApiDotNetCore.Internal.IContextGraph.UsesDbContext": "JsonApiDotNetCore.Internal.IContextGraph.yml", + "JsonApiDotNetCore.Internal.JsonApiException": "JsonApiDotNetCore.Internal.JsonApiException.yml", + "JsonApiDotNetCore.Internal.JsonApiException.#ctor(JsonApiDotNetCore.Internal.Error)": "JsonApiDotNetCore.Internal.JsonApiException.yml", + "JsonApiDotNetCore.Internal.JsonApiException.#ctor(JsonApiDotNetCore.Internal.ErrorCollection)": "JsonApiDotNetCore.Internal.JsonApiException.yml", + "JsonApiDotNetCore.Internal.JsonApiException.#ctor(System.Int32,System.String,System.Exception)": "JsonApiDotNetCore.Internal.JsonApiException.yml", + "JsonApiDotNetCore.Internal.JsonApiException.#ctor(System.Int32,System.String,System.String)": "JsonApiDotNetCore.Internal.JsonApiException.yml", + "JsonApiDotNetCore.Internal.JsonApiException.#ctor(System.Int32,System.String,System.String,System.String)": "JsonApiDotNetCore.Internal.JsonApiException.yml", + "JsonApiDotNetCore.Internal.JsonApiException.#ctor(System.String,System.String,System.String)": "JsonApiDotNetCore.Internal.JsonApiException.yml", + "JsonApiDotNetCore.Internal.JsonApiException.#ctor(System.String,System.String,System.String,System.String)": "JsonApiDotNetCore.Internal.JsonApiException.yml", + "JsonApiDotNetCore.Internal.JsonApiException.GetError": "JsonApiDotNetCore.Internal.JsonApiException.yml", + "JsonApiDotNetCore.Internal.JsonApiException.GetStatusCode": "JsonApiDotNetCore.Internal.JsonApiException.yml", + "JsonApiDotNetCore.Internal.JsonApiExceptionFactory": "JsonApiDotNetCore.Internal.JsonApiExceptionFactory.yml", + "JsonApiDotNetCore.Internal.JsonApiExceptionFactory.GetException(System.Exception)": "JsonApiDotNetCore.Internal.JsonApiExceptionFactory.yml", + "JsonApiDotNetCore.Internal.JsonApiRouteHandler": "JsonApiDotNetCore.Internal.JsonApiRouteHandler.yml", + "JsonApiDotNetCore.Internal.JsonApiRouteHandler.#ctor(Microsoft.AspNetCore.Mvc.Infrastructure.IActionInvokerFactory,Microsoft.AspNetCore.Mvc.Infrastructure.IActionSelector)": "JsonApiDotNetCore.Internal.JsonApiRouteHandler.yml", + "JsonApiDotNetCore.Internal.JsonApiRouteHandler.#ctor(Microsoft.AspNetCore.Mvc.Infrastructure.IActionInvokerFactory,Microsoft.AspNetCore.Mvc.Infrastructure.IActionSelector,Microsoft.AspNetCore.Mvc.Infrastructure.IActionContextAccessor)": "JsonApiDotNetCore.Internal.JsonApiRouteHandler.yml", + "JsonApiDotNetCore.Internal.JsonApiRouteHandler.GetVirtualPath(Microsoft.AspNetCore.Routing.VirtualPathContext)": "JsonApiDotNetCore.Internal.JsonApiRouteHandler.yml", + "JsonApiDotNetCore.Internal.JsonApiRouteHandler.RouteAsync(Microsoft.AspNetCore.Routing.RouteContext)": "JsonApiDotNetCore.Internal.JsonApiRouteHandler.yml", + "JsonApiDotNetCore.Internal.PageManager": "JsonApiDotNetCore.Internal.PageManager.yml", + "JsonApiDotNetCore.Internal.PageManager.CurrentPage": "JsonApiDotNetCore.Internal.PageManager.yml", + "JsonApiDotNetCore.Internal.PageManager.DefaultPageSize": "JsonApiDotNetCore.Internal.PageManager.yml", + "JsonApiDotNetCore.Internal.PageManager.GetPageLinks(JsonApiDotNetCore.Builders.LinkBuilder)": "JsonApiDotNetCore.Internal.PageManager.yml", + "JsonApiDotNetCore.Internal.PageManager.IsPaginated": "JsonApiDotNetCore.Internal.PageManager.yml", + "JsonApiDotNetCore.Internal.PageManager.PageSize": "JsonApiDotNetCore.Internal.PageManager.yml", + "JsonApiDotNetCore.Internal.PageManager.TotalPages": "JsonApiDotNetCore.Internal.PageManager.yml", + "JsonApiDotNetCore.Internal.PageManager.TotalRecords": "JsonApiDotNetCore.Internal.PageManager.yml", + "JsonApiDotNetCore.Internal.Query": "JsonApiDotNetCore.Internal.Query.yml", + "JsonApiDotNetCore.Internal.Query.AttrFilterQuery": "JsonApiDotNetCore.Internal.Query.AttrFilterQuery.yml", + "JsonApiDotNetCore.Internal.Query.AttrFilterQuery.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Internal.Query.FilterQuery)": "JsonApiDotNetCore.Internal.Query.AttrFilterQuery.yml", + "JsonApiDotNetCore.Internal.Query.AttrFilterQuery.FilteredAttribute": "JsonApiDotNetCore.Internal.Query.AttrFilterQuery.yml", + "JsonApiDotNetCore.Internal.Query.AttrFilterQuery.FilterOperation": "JsonApiDotNetCore.Internal.Query.AttrFilterQuery.yml", + "JsonApiDotNetCore.Internal.Query.AttrFilterQuery.PropertyValue": "JsonApiDotNetCore.Internal.Query.AttrFilterQuery.yml", + "JsonApiDotNetCore.Internal.Query.BaseFilterQuery": "JsonApiDotNetCore.Internal.Query.BaseFilterQuery.yml", + "JsonApiDotNetCore.Internal.Query.BaseFilterQuery.GetFilterOperation(System.String)": "JsonApiDotNetCore.Internal.Query.BaseFilterQuery.yml", + "JsonApiDotNetCore.Internal.Query.FilterOperations": "JsonApiDotNetCore.Internal.Query.FilterOperations.yml", + "JsonApiDotNetCore.Internal.Query.FilterOperations.eq": "JsonApiDotNetCore.Internal.Query.FilterOperations.yml", + "JsonApiDotNetCore.Internal.Query.FilterOperations.ge": "JsonApiDotNetCore.Internal.Query.FilterOperations.yml", + "JsonApiDotNetCore.Internal.Query.FilterOperations.gt": "JsonApiDotNetCore.Internal.Query.FilterOperations.yml", + "JsonApiDotNetCore.Internal.Query.FilterOperations.le": "JsonApiDotNetCore.Internal.Query.FilterOperations.yml", + "JsonApiDotNetCore.Internal.Query.FilterOperations.like": "JsonApiDotNetCore.Internal.Query.FilterOperations.yml", + "JsonApiDotNetCore.Internal.Query.FilterOperations.lt": "JsonApiDotNetCore.Internal.Query.FilterOperations.yml", + "JsonApiDotNetCore.Internal.Query.FilterQuery": "JsonApiDotNetCore.Internal.Query.FilterQuery.yml", + "JsonApiDotNetCore.Internal.Query.FilterQuery.#ctor(System.String,System.String,System.String)": "JsonApiDotNetCore.Internal.Query.FilterQuery.yml", + "JsonApiDotNetCore.Internal.Query.FilterQuery.Attribute": "JsonApiDotNetCore.Internal.Query.FilterQuery.yml", + "JsonApiDotNetCore.Internal.Query.FilterQuery.IsAttributeOfRelationship": "JsonApiDotNetCore.Internal.Query.FilterQuery.yml", + "JsonApiDotNetCore.Internal.Query.FilterQuery.Key": "JsonApiDotNetCore.Internal.Query.FilterQuery.yml", + "JsonApiDotNetCore.Internal.Query.FilterQuery.Operation": "JsonApiDotNetCore.Internal.Query.FilterQuery.yml", + "JsonApiDotNetCore.Internal.Query.FilterQuery.Value": "JsonApiDotNetCore.Internal.Query.FilterQuery.yml", + "JsonApiDotNetCore.Internal.Query.PageQuery": "JsonApiDotNetCore.Internal.Query.PageQuery.yml", + "JsonApiDotNetCore.Internal.Query.PageQuery.PageOffset": "JsonApiDotNetCore.Internal.Query.PageQuery.yml", + "JsonApiDotNetCore.Internal.Query.PageQuery.PageSize": "JsonApiDotNetCore.Internal.Query.PageQuery.yml", + "JsonApiDotNetCore.Internal.Query.QuerySet": "JsonApiDotNetCore.Internal.Query.QuerySet.yml", + "JsonApiDotNetCore.Internal.Query.QuerySet.Fields": "JsonApiDotNetCore.Internal.Query.QuerySet.yml", + "JsonApiDotNetCore.Internal.Query.QuerySet.Filters": "JsonApiDotNetCore.Internal.Query.QuerySet.yml", + "JsonApiDotNetCore.Internal.Query.QuerySet.IncludedRelationships": "JsonApiDotNetCore.Internal.Query.QuerySet.yml", + "JsonApiDotNetCore.Internal.Query.QuerySet.PageQuery": "JsonApiDotNetCore.Internal.Query.QuerySet.yml", + "JsonApiDotNetCore.Internal.Query.QuerySet.SortParameters": "JsonApiDotNetCore.Internal.Query.QuerySet.yml", + "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery": "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.yml", + "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Internal.Query.FilterQuery)": "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.yml", + "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.FilteredAttribute": "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.yml", + "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.FilteredRelationship": "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.yml", + "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.FilterOperation": "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.yml", + "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.PropertyValue": "JsonApiDotNetCore.Internal.Query.RelatedAttrFilterQuery.yml", + "JsonApiDotNetCore.Internal.Query.SortDirection": "JsonApiDotNetCore.Internal.Query.SortDirection.yml", + "JsonApiDotNetCore.Internal.Query.SortDirection.Ascending": "JsonApiDotNetCore.Internal.Query.SortDirection.yml", + "JsonApiDotNetCore.Internal.Query.SortDirection.Descending": "JsonApiDotNetCore.Internal.Query.SortDirection.yml", + "JsonApiDotNetCore.Internal.Query.SortQuery": "JsonApiDotNetCore.Internal.Query.SortQuery.yml", + "JsonApiDotNetCore.Internal.Query.SortQuery.#ctor(JsonApiDotNetCore.Internal.Query.SortDirection,JsonApiDotNetCore.Models.AttrAttribute)": "JsonApiDotNetCore.Internal.Query.SortQuery.yml", + "JsonApiDotNetCore.Internal.Query.SortQuery.Direction": "JsonApiDotNetCore.Internal.Query.SortQuery.yml", + "JsonApiDotNetCore.Internal.Query.SortQuery.SortedAttribute": "JsonApiDotNetCore.Internal.Query.SortQuery.yml", + "JsonApiDotNetCore.Internal.TypeHelper": "JsonApiDotNetCore.Internal.TypeHelper.yml", + "JsonApiDotNetCore.Internal.TypeHelper.ConvertType(System.Object,System.Type)": "JsonApiDotNetCore.Internal.TypeHelper.yml", + "JsonApiDotNetCore.Internal.TypeHelper.ConvertType``1(System.Object)": "JsonApiDotNetCore.Internal.TypeHelper.yml", + "JsonApiDotNetCore.Middleware": "JsonApiDotNetCore.Middleware.yml", + "JsonApiDotNetCore.Middleware.JsonApiExceptionFilter": "JsonApiDotNetCore.Middleware.JsonApiExceptionFilter.yml", + "JsonApiDotNetCore.Middleware.JsonApiExceptionFilter.#ctor(Microsoft.Extensions.Logging.ILoggerFactory)": "JsonApiDotNetCore.Middleware.JsonApiExceptionFilter.yml", + "JsonApiDotNetCore.Middleware.JsonApiExceptionFilter.OnException(Microsoft.AspNetCore.Mvc.Filters.ExceptionContext)": "JsonApiDotNetCore.Middleware.JsonApiExceptionFilter.yml", + "JsonApiDotNetCore.Middleware.RequestMiddleware": "JsonApiDotNetCore.Middleware.RequestMiddleware.yml", + "JsonApiDotNetCore.Middleware.RequestMiddleware.#ctor(Microsoft.AspNetCore.Http.RequestDelegate)": "JsonApiDotNetCore.Middleware.RequestMiddleware.yml", + "JsonApiDotNetCore.Middleware.RequestMiddleware.Invoke(Microsoft.AspNetCore.Http.HttpContext)": "JsonApiDotNetCore.Middleware.RequestMiddleware.yml", + "JsonApiDotNetCore.Models": "JsonApiDotNetCore.Models.yml", + "JsonApiDotNetCore.Models.AttrAttribute": "JsonApiDotNetCore.Models.AttrAttribute.yml", + "JsonApiDotNetCore.Models.AttrAttribute.#ctor(System.String,System.Boolean,System.Boolean,System.Boolean)": "JsonApiDotNetCore.Models.AttrAttribute.yml", + "JsonApiDotNetCore.Models.AttrAttribute.GetValue(System.Object)": "JsonApiDotNetCore.Models.AttrAttribute.yml", + "JsonApiDotNetCore.Models.AttrAttribute.InternalAttributeName": "JsonApiDotNetCore.Models.AttrAttribute.yml", + "JsonApiDotNetCore.Models.AttrAttribute.Is(System.String)": "JsonApiDotNetCore.Models.AttrAttribute.yml", + "JsonApiDotNetCore.Models.AttrAttribute.IsFilterable": "JsonApiDotNetCore.Models.AttrAttribute.yml", + "JsonApiDotNetCore.Models.AttrAttribute.IsImmutable": "JsonApiDotNetCore.Models.AttrAttribute.yml", + "JsonApiDotNetCore.Models.AttrAttribute.IsSortable": "JsonApiDotNetCore.Models.AttrAttribute.yml", + "JsonApiDotNetCore.Models.AttrAttribute.PublicAttributeName": "JsonApiDotNetCore.Models.AttrAttribute.yml", + "JsonApiDotNetCore.Models.AttrAttribute.SetValue(System.Object,System.Object)": "JsonApiDotNetCore.Models.AttrAttribute.yml", + "JsonApiDotNetCore.Models.Document": "JsonApiDotNetCore.Models.Document.yml", + "JsonApiDotNetCore.Models.Document.Data": "JsonApiDotNetCore.Models.Document.yml", + "JsonApiDotNetCore.Models.DocumentBase": "JsonApiDotNetCore.Models.DocumentBase.yml", + "JsonApiDotNetCore.Models.DocumentBase.Included": "JsonApiDotNetCore.Models.DocumentBase.yml", + "JsonApiDotNetCore.Models.DocumentBase.Links": "JsonApiDotNetCore.Models.DocumentBase.yml", + "JsonApiDotNetCore.Models.DocumentBase.Meta": "JsonApiDotNetCore.Models.DocumentBase.yml", + "JsonApiDotNetCore.Models.DocumentData": "JsonApiDotNetCore.Models.DocumentData.yml", + "JsonApiDotNetCore.Models.Documents": "JsonApiDotNetCore.Models.Documents.yml", + "JsonApiDotNetCore.Models.Documents.Data": "JsonApiDotNetCore.Models.Documents.yml", + "JsonApiDotNetCore.Models.HasManyAttribute": "JsonApiDotNetCore.Models.HasManyAttribute.yml", + "JsonApiDotNetCore.Models.HasManyAttribute.#ctor(System.String,JsonApiDotNetCore.Models.Link)": "JsonApiDotNetCore.Models.HasManyAttribute.yml", + "JsonApiDotNetCore.Models.HasManyAttribute.SetValue(System.Object,System.Object)": "JsonApiDotNetCore.Models.HasManyAttribute.yml", + "JsonApiDotNetCore.Models.HasOneAttribute": "JsonApiDotNetCore.Models.HasOneAttribute.yml", + "JsonApiDotNetCore.Models.HasOneAttribute.#ctor(System.String,JsonApiDotNetCore.Models.Link)": "JsonApiDotNetCore.Models.HasOneAttribute.yml", + "JsonApiDotNetCore.Models.HasOneAttribute.SetValue(System.Object,System.Object)": "JsonApiDotNetCore.Models.HasOneAttribute.yml", + "JsonApiDotNetCore.Models.Identifiable": "JsonApiDotNetCore.Models.Identifiable.yml", + "JsonApiDotNetCore.Models.Identifiable`1": "JsonApiDotNetCore.Models.Identifiable-1.yml", + "JsonApiDotNetCore.Models.Identifiable`1.GetConcreteId(System.String)": "JsonApiDotNetCore.Models.Identifiable-1.yml", + "JsonApiDotNetCore.Models.Identifiable`1.GetStringId(System.Object)": "JsonApiDotNetCore.Models.Identifiable-1.yml", + "JsonApiDotNetCore.Models.Identifiable`1.Id": "JsonApiDotNetCore.Models.Identifiable-1.yml", + "JsonApiDotNetCore.Models.Identifiable`1.StringId": "JsonApiDotNetCore.Models.Identifiable-1.yml", + "JsonApiDotNetCore.Models.IHasMeta": "JsonApiDotNetCore.Models.IHasMeta.yml", + "JsonApiDotNetCore.Models.IHasMeta.GetMeta(JsonApiDotNetCore.Services.IJsonApiContext)": "JsonApiDotNetCore.Models.IHasMeta.yml", + "JsonApiDotNetCore.Models.IIdentifiable": "JsonApiDotNetCore.Models.IIdentifiable.yml", + "JsonApiDotNetCore.Models.IIdentifiable.StringId": "JsonApiDotNetCore.Models.IIdentifiable.yml", + "JsonApiDotNetCore.Models.IIdentifiable`1": "JsonApiDotNetCore.Models.IIdentifiable-1.yml", + "JsonApiDotNetCore.Models.IIdentifiable`1.Id": "JsonApiDotNetCore.Models.IIdentifiable-1.yml", + "JsonApiDotNetCore.Models.JsonApiExtension": "JsonApiDotNetCore.Models.JsonApiExtension.yml", + "JsonApiDotNetCore.Models.JsonApiExtension.Operations": "JsonApiDotNetCore.Models.JsonApiExtension.yml", + "JsonApiDotNetCore.Models.Link": "JsonApiDotNetCore.Models.Link.yml", + "JsonApiDotNetCore.Models.Link.All": "JsonApiDotNetCore.Models.Link.yml", + "JsonApiDotNetCore.Models.Link.None": "JsonApiDotNetCore.Models.Link.yml", + "JsonApiDotNetCore.Models.Link.Paging": "JsonApiDotNetCore.Models.Link.yml", + "JsonApiDotNetCore.Models.Link.Related": "JsonApiDotNetCore.Models.Link.yml", + "JsonApiDotNetCore.Models.Link.Self": "JsonApiDotNetCore.Models.Link.yml", + "JsonApiDotNetCore.Models.Links": "JsonApiDotNetCore.Models.Links.yml", + "JsonApiDotNetCore.Models.Links.Related": "JsonApiDotNetCore.Models.Links.yml", + "JsonApiDotNetCore.Models.Links.Self": "JsonApiDotNetCore.Models.Links.yml", + "JsonApiDotNetCore.Models.LinksAttribute": "JsonApiDotNetCore.Models.LinksAttribute.yml", + "JsonApiDotNetCore.Models.LinksAttribute.#ctor(JsonApiDotNetCore.Models.Link)": "JsonApiDotNetCore.Models.LinksAttribute.yml", + "JsonApiDotNetCore.Models.LinksAttribute.Links": "JsonApiDotNetCore.Models.LinksAttribute.yml", + "JsonApiDotNetCore.Models.Operations": "JsonApiDotNetCore.Models.Operations.yml", + "JsonApiDotNetCore.Models.Operations.Operation": "JsonApiDotNetCore.Models.Operations.Operation.yml", + "JsonApiDotNetCore.Models.Operations.Operation.Data": "JsonApiDotNetCore.Models.Operations.Operation.yml", + "JsonApiDotNetCore.Models.Operations.Operation.DataIsList": "JsonApiDotNetCore.Models.Operations.Operation.yml", + "JsonApiDotNetCore.Models.Operations.Operation.DataList": "JsonApiDotNetCore.Models.Operations.Operation.yml", + "JsonApiDotNetCore.Models.Operations.Operation.DataObject": "JsonApiDotNetCore.Models.Operations.Operation.yml", + "JsonApiDotNetCore.Models.Operations.Operation.GetResourceTypeName": "JsonApiDotNetCore.Models.Operations.Operation.yml", + "JsonApiDotNetCore.Models.Operations.Operation.Op": "JsonApiDotNetCore.Models.Operations.Operation.yml", + "JsonApiDotNetCore.Models.Operations.Operation.Params": "JsonApiDotNetCore.Models.Operations.Operation.yml", + "JsonApiDotNetCore.Models.Operations.Operation.Ref": "JsonApiDotNetCore.Models.Operations.Operation.yml", + "JsonApiDotNetCore.Models.Operations.OperationCode": "JsonApiDotNetCore.Models.Operations.OperationCode.yml", + "JsonApiDotNetCore.Models.Operations.OperationCode.add": "JsonApiDotNetCore.Models.Operations.OperationCode.yml", + "JsonApiDotNetCore.Models.Operations.OperationCode.get": "JsonApiDotNetCore.Models.Operations.OperationCode.yml", + "JsonApiDotNetCore.Models.Operations.OperationCode.remove": "JsonApiDotNetCore.Models.Operations.OperationCode.yml", + "JsonApiDotNetCore.Models.Operations.OperationCode.update": "JsonApiDotNetCore.Models.Operations.OperationCode.yml", + "JsonApiDotNetCore.Models.Operations.OperationsDocument": "JsonApiDotNetCore.Models.Operations.OperationsDocument.yml", + "JsonApiDotNetCore.Models.Operations.OperationsDocument.#ctor": "JsonApiDotNetCore.Models.Operations.OperationsDocument.yml", + "JsonApiDotNetCore.Models.Operations.OperationsDocument.#ctor(System.Collections.Generic.List{JsonApiDotNetCore.Models.Operations.Operation})": "JsonApiDotNetCore.Models.Operations.OperationsDocument.yml", + "JsonApiDotNetCore.Models.Operations.OperationsDocument.Operations": "JsonApiDotNetCore.Models.Operations.OperationsDocument.yml", + "JsonApiDotNetCore.Models.Operations.Params": "JsonApiDotNetCore.Models.Operations.Params.yml", + "JsonApiDotNetCore.Models.Operations.Params.Fields": "JsonApiDotNetCore.Models.Operations.Params.yml", + "JsonApiDotNetCore.Models.Operations.Params.Filter": "JsonApiDotNetCore.Models.Operations.Params.yml", + "JsonApiDotNetCore.Models.Operations.Params.Include": "JsonApiDotNetCore.Models.Operations.Params.yml", + "JsonApiDotNetCore.Models.Operations.Params.Page": "JsonApiDotNetCore.Models.Operations.Params.yml", + "JsonApiDotNetCore.Models.Operations.Params.Sort": "JsonApiDotNetCore.Models.Operations.Params.yml", + "JsonApiDotNetCore.Models.Operations.ResourceReference": "JsonApiDotNetCore.Models.Operations.ResourceReference.yml", + "JsonApiDotNetCore.Models.Operations.ResourceReference.Relationship": "JsonApiDotNetCore.Models.Operations.ResourceReference.yml", + "JsonApiDotNetCore.Models.RelationshipAttribute": "JsonApiDotNetCore.Models.RelationshipAttribute.yml", + "JsonApiDotNetCore.Models.RelationshipAttribute.#ctor(System.String,JsonApiDotNetCore.Models.Link)": "JsonApiDotNetCore.Models.RelationshipAttribute.yml", + "JsonApiDotNetCore.Models.RelationshipAttribute.DocumentLinks": "JsonApiDotNetCore.Models.RelationshipAttribute.yml", + "JsonApiDotNetCore.Models.RelationshipAttribute.Equals(System.Object)": "JsonApiDotNetCore.Models.RelationshipAttribute.yml", + "JsonApiDotNetCore.Models.RelationshipAttribute.InternalRelationshipName": "JsonApiDotNetCore.Models.RelationshipAttribute.yml", + "JsonApiDotNetCore.Models.RelationshipAttribute.Is(System.String)": "JsonApiDotNetCore.Models.RelationshipAttribute.yml", + "JsonApiDotNetCore.Models.RelationshipAttribute.IsHasMany": "JsonApiDotNetCore.Models.RelationshipAttribute.yml", + "JsonApiDotNetCore.Models.RelationshipAttribute.IsHasOne": "JsonApiDotNetCore.Models.RelationshipAttribute.yml", + "JsonApiDotNetCore.Models.RelationshipAttribute.PublicRelationshipName": "JsonApiDotNetCore.Models.RelationshipAttribute.yml", + "JsonApiDotNetCore.Models.RelationshipAttribute.SetValue(System.Object,System.Object)": "JsonApiDotNetCore.Models.RelationshipAttribute.yml", + "JsonApiDotNetCore.Models.RelationshipAttribute.ToString": "JsonApiDotNetCore.Models.RelationshipAttribute.yml", + "JsonApiDotNetCore.Models.RelationshipAttribute.Type": "JsonApiDotNetCore.Models.RelationshipAttribute.yml", + "JsonApiDotNetCore.Models.RelationshipData": "JsonApiDotNetCore.Models.RelationshipData.yml", + "JsonApiDotNetCore.Models.RelationshipData.ExposedData": "JsonApiDotNetCore.Models.RelationshipData.yml", + "JsonApiDotNetCore.Models.RelationshipData.IsHasMany": "JsonApiDotNetCore.Models.RelationshipData.yml", + "JsonApiDotNetCore.Models.RelationshipData.Links": "JsonApiDotNetCore.Models.RelationshipData.yml", + "JsonApiDotNetCore.Models.RelationshipData.ManyData": "JsonApiDotNetCore.Models.RelationshipData.yml", + "JsonApiDotNetCore.Models.RelationshipData.SingleData": "JsonApiDotNetCore.Models.RelationshipData.yml", + "JsonApiDotNetCore.Models.ResourceAttribute": "JsonApiDotNetCore.Models.ResourceAttribute.yml", + "JsonApiDotNetCore.Models.ResourceAttribute.#ctor(System.String)": "JsonApiDotNetCore.Models.ResourceAttribute.yml", + "JsonApiDotNetCore.Models.ResourceAttribute.ResourceName": "JsonApiDotNetCore.Models.ResourceAttribute.yml", + "JsonApiDotNetCore.Models.ResourceIdentifierObject": "JsonApiDotNetCore.Models.ResourceIdentifierObject.yml", + "JsonApiDotNetCore.Models.ResourceIdentifierObject.Id": "JsonApiDotNetCore.Models.ResourceIdentifierObject.yml", + "JsonApiDotNetCore.Models.ResourceIdentifierObject.LocalId": "JsonApiDotNetCore.Models.ResourceIdentifierObject.yml", + "JsonApiDotNetCore.Models.ResourceIdentifierObject.Type": "JsonApiDotNetCore.Models.ResourceIdentifierObject.yml", + "JsonApiDotNetCore.Models.ResourceObject": "JsonApiDotNetCore.Models.ResourceObject.yml", + "JsonApiDotNetCore.Models.ResourceObject.Attributes": "JsonApiDotNetCore.Models.ResourceObject.yml", + "JsonApiDotNetCore.Models.ResourceObject.Relationships": "JsonApiDotNetCore.Models.ResourceObject.yml", + "JsonApiDotNetCore.Models.RootLinks": "JsonApiDotNetCore.Models.RootLinks.yml", + "JsonApiDotNetCore.Models.RootLinks.First": "JsonApiDotNetCore.Models.RootLinks.yml", + "JsonApiDotNetCore.Models.RootLinks.Last": "JsonApiDotNetCore.Models.RootLinks.yml", + "JsonApiDotNetCore.Models.RootLinks.Next": "JsonApiDotNetCore.Models.RootLinks.yml", + "JsonApiDotNetCore.Models.RootLinks.Prev": "JsonApiDotNetCore.Models.RootLinks.yml", + "JsonApiDotNetCore.Models.RootLinks.Self": "JsonApiDotNetCore.Models.RootLinks.yml", + "JsonApiDotNetCore.Models.RootLinks.ShouldSerializeFirst": "JsonApiDotNetCore.Models.RootLinks.yml", + "JsonApiDotNetCore.Models.RootLinks.ShouldSerializeLast": "JsonApiDotNetCore.Models.RootLinks.yml", + "JsonApiDotNetCore.Models.RootLinks.ShouldSerializeNext": "JsonApiDotNetCore.Models.RootLinks.yml", + "JsonApiDotNetCore.Models.RootLinks.ShouldSerializePrev": "JsonApiDotNetCore.Models.RootLinks.yml", + "JsonApiDotNetCore.Models.RootLinks.ShouldSerializeSelf": "JsonApiDotNetCore.Models.RootLinks.yml", + "JsonApiDotNetCore.Serialization": "JsonApiDotNetCore.Serialization.yml", + "JsonApiDotNetCore.Serialization.DasherizedResolver": "JsonApiDotNetCore.Serialization.DasherizedResolver.yml", + "JsonApiDotNetCore.Serialization.DasherizedResolver.CreateProperty(System.Reflection.MemberInfo,Newtonsoft.Json.MemberSerialization)": "JsonApiDotNetCore.Serialization.DasherizedResolver.yml", + "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer": "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.yml", + "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.Deserialize(System.String)": "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.yml", + "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.Deserialize``1(System.String)": "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.yml", + "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.DeserializeList``1(System.String)": "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.yml", + "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.DeserializeRelationship(System.String)": "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.yml", + "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.DocumentToObject(JsonApiDotNetCore.Models.DocumentData)": "JsonApiDotNetCore.Serialization.IJsonApiDeSerializer.yml", + "JsonApiDotNetCore.Serialization.IJsonApiSerializer": "JsonApiDotNetCore.Serialization.IJsonApiSerializer.yml", + "JsonApiDotNetCore.Serialization.IJsonApiSerializer.Serialize(System.Object)": "JsonApiDotNetCore.Serialization.IJsonApiSerializer.yml", + "JsonApiDotNetCore.Serialization.JsonApiDeSerializer": "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.yml", + "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Internal.Generics.IGenericProcessorFactory)": "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.yml", + "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.Deserialize(System.String)": "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.yml", + "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.Deserialize``1(System.String)": "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.yml", + "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.DeserializeList``1(System.String)": "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.yml", + "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.DeserializeRelationship(System.String)": "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.yml", + "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.DocumentToObject(JsonApiDotNetCore.Models.DocumentData)": "JsonApiDotNetCore.Serialization.JsonApiDeSerializer.yml", + "JsonApiDotNetCore.Serialization.JsonApiSerializer": "JsonApiDotNetCore.Serialization.JsonApiSerializer.yml", + "JsonApiDotNetCore.Serialization.JsonApiSerializer.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Builders.IDocumentBuilder)": "JsonApiDotNetCore.Serialization.JsonApiSerializer.yml", + "JsonApiDotNetCore.Serialization.JsonApiSerializer.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Builders.IDocumentBuilder,Microsoft.Extensions.Logging.ILoggerFactory)": "JsonApiDotNetCore.Serialization.JsonApiSerializer.yml", + "JsonApiDotNetCore.Serialization.JsonApiSerializer.Serialize(System.Object)": "JsonApiDotNetCore.Serialization.JsonApiSerializer.yml", + "JsonApiDotNetCore.Services": "JsonApiDotNetCore.Services.yml", + "JsonApiDotNetCore.Services.ControllerContext": "JsonApiDotNetCore.Services.ControllerContext.yml", + "JsonApiDotNetCore.Services.ControllerContext.ControllerType": "JsonApiDotNetCore.Services.ControllerContext.yml", + "JsonApiDotNetCore.Services.ControllerContext.GetControllerAttribute``1": "JsonApiDotNetCore.Services.ControllerContext.yml", + "JsonApiDotNetCore.Services.ControllerContext.RequestEntity": "JsonApiDotNetCore.Services.ControllerContext.yml", + "JsonApiDotNetCore.Services.EntityResourceService`1": "JsonApiDotNetCore.Services.EntityResourceService-1.yml", + "JsonApiDotNetCore.Services.EntityResourceService`1.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Data.IEntityRepository{`0},Microsoft.Extensions.Logging.ILoggerFactory)": "JsonApiDotNetCore.Services.EntityResourceService-1.yml", + "JsonApiDotNetCore.Services.EntityResourceService`2": "JsonApiDotNetCore.Services.EntityResourceService-2.yml", + "JsonApiDotNetCore.Services.EntityResourceService`2.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,JsonApiDotNetCore.Data.IEntityRepository{`0,`1},Microsoft.Extensions.Logging.ILoggerFactory)": "JsonApiDotNetCore.Services.EntityResourceService-2.yml", + "JsonApiDotNetCore.Services.EntityResourceService`2.CreateAsync(`0)": "JsonApiDotNetCore.Services.EntityResourceService-2.yml", + "JsonApiDotNetCore.Services.EntityResourceService`2.DeleteAsync(`1)": "JsonApiDotNetCore.Services.EntityResourceService-2.yml", + "JsonApiDotNetCore.Services.EntityResourceService`2.GetAsync": "JsonApiDotNetCore.Services.EntityResourceService-2.yml", + "JsonApiDotNetCore.Services.EntityResourceService`2.GetAsync(`1)": "JsonApiDotNetCore.Services.EntityResourceService-2.yml", + "JsonApiDotNetCore.Services.EntityResourceService`2.GetRelationshipAsync(`1,System.String)": "JsonApiDotNetCore.Services.EntityResourceService-2.yml", + "JsonApiDotNetCore.Services.EntityResourceService`2.GetRelationshipsAsync(`1,System.String)": "JsonApiDotNetCore.Services.EntityResourceService-2.yml", + "JsonApiDotNetCore.Services.EntityResourceService`2.UpdateAsync(`1,`0)": "JsonApiDotNetCore.Services.EntityResourceService-2.yml", + "JsonApiDotNetCore.Services.EntityResourceService`2.UpdateRelationshipsAsync(`1,System.String,System.Collections.Generic.List{JsonApiDotNetCore.Models.DocumentData})": "JsonApiDotNetCore.Services.EntityResourceService-2.yml", + "JsonApiDotNetCore.Services.IControllerContext": "JsonApiDotNetCore.Services.IControllerContext.yml", + "JsonApiDotNetCore.Services.IControllerContext.ControllerType": "JsonApiDotNetCore.Services.IControllerContext.yml", + "JsonApiDotNetCore.Services.IControllerContext.GetControllerAttribute``1": "JsonApiDotNetCore.Services.IControllerContext.yml", + "JsonApiDotNetCore.Services.IControllerContext.RequestEntity": "JsonApiDotNetCore.Services.IControllerContext.yml", + "JsonApiDotNetCore.Services.ICreateService`1": "JsonApiDotNetCore.Services.ICreateService-1.yml", + "JsonApiDotNetCore.Services.ICreateService`2": "JsonApiDotNetCore.Services.ICreateService-2.yml", + "JsonApiDotNetCore.Services.ICreateService`2.CreateAsync(`0)": "JsonApiDotNetCore.Services.ICreateService-2.yml", + "JsonApiDotNetCore.Services.IDeleteService`1": "JsonApiDotNetCore.Services.IDeleteService-1.yml", + "JsonApiDotNetCore.Services.IDeleteService`2": "JsonApiDotNetCore.Services.IDeleteService-2.yml", + "JsonApiDotNetCore.Services.IDeleteService`2.DeleteAsync(`1)": "JsonApiDotNetCore.Services.IDeleteService-2.yml", + "JsonApiDotNetCore.Services.IGetAllService`1": "JsonApiDotNetCore.Services.IGetAllService-1.yml", + "JsonApiDotNetCore.Services.IGetAllService`2": "JsonApiDotNetCore.Services.IGetAllService-2.yml", + "JsonApiDotNetCore.Services.IGetAllService`2.GetAsync": "JsonApiDotNetCore.Services.IGetAllService-2.yml", + "JsonApiDotNetCore.Services.IGetByIdService`1": "JsonApiDotNetCore.Services.IGetByIdService-1.yml", + "JsonApiDotNetCore.Services.IGetByIdService`2": "JsonApiDotNetCore.Services.IGetByIdService-2.yml", + "JsonApiDotNetCore.Services.IGetByIdService`2.GetAsync(`1)": "JsonApiDotNetCore.Services.IGetByIdService-2.yml", + "JsonApiDotNetCore.Services.IGetRelationshipService`1": "JsonApiDotNetCore.Services.IGetRelationshipService-1.yml", + "JsonApiDotNetCore.Services.IGetRelationshipService`2": "JsonApiDotNetCore.Services.IGetRelationshipService-2.yml", + "JsonApiDotNetCore.Services.IGetRelationshipService`2.GetRelationshipAsync(`1,System.String)": "JsonApiDotNetCore.Services.IGetRelationshipService-2.yml", + "JsonApiDotNetCore.Services.IGetRelationshipsService`1": "JsonApiDotNetCore.Services.IGetRelationshipsService-1.yml", + "JsonApiDotNetCore.Services.IGetRelationshipsService`2": "JsonApiDotNetCore.Services.IGetRelationshipsService-2.yml", + "JsonApiDotNetCore.Services.IGetRelationshipsService`2.GetRelationshipsAsync(`1,System.String)": "JsonApiDotNetCore.Services.IGetRelationshipsService-2.yml", + "JsonApiDotNetCore.Services.IJsonApiContext": "JsonApiDotNetCore.Services.IJsonApiContext.yml", + "JsonApiDotNetCore.Services.IJsonApiContext.ApplyContext``1(System.Object)": "JsonApiDotNetCore.Services.IJsonApiContext.yml", + "JsonApiDotNetCore.Services.IJsonApiContext.AttributesToUpdate": "JsonApiDotNetCore.Services.IJsonApiContext.yml", + "JsonApiDotNetCore.Services.IJsonApiContext.BasePath": "JsonApiDotNetCore.Services.IJsonApiContext.yml", + "JsonApiDotNetCore.Services.IJsonApiContext.ContextGraph": "JsonApiDotNetCore.Services.IJsonApiContext.yml", + "JsonApiDotNetCore.Services.IJsonApiContext.ControllerType": "JsonApiDotNetCore.Services.IJsonApiContext.yml", + "JsonApiDotNetCore.Services.IJsonApiContext.DocumentMeta": "JsonApiDotNetCore.Services.IJsonApiContext.yml", + "JsonApiDotNetCore.Services.IJsonApiContext.GenericProcessorFactory": "JsonApiDotNetCore.Services.IJsonApiContext.yml", + "JsonApiDotNetCore.Services.IJsonApiContext.GetControllerAttribute``1": "JsonApiDotNetCore.Services.IJsonApiContext.yml", + "JsonApiDotNetCore.Services.IJsonApiContext.IncludedRelationships": "JsonApiDotNetCore.Services.IJsonApiContext.yml", + "JsonApiDotNetCore.Services.IJsonApiContext.IsBulkOperationRequest": "JsonApiDotNetCore.Services.IJsonApiContext.yml", + "JsonApiDotNetCore.Services.IJsonApiContext.IsRelationshipData": "JsonApiDotNetCore.Services.IJsonApiContext.yml", + "JsonApiDotNetCore.Services.IJsonApiContext.IsRelationshipPath": "JsonApiDotNetCore.Services.IJsonApiContext.yml", + "JsonApiDotNetCore.Services.IJsonApiContext.MetaBuilder": "JsonApiDotNetCore.Services.IJsonApiContext.yml", + "JsonApiDotNetCore.Services.IJsonApiContext.Options": "JsonApiDotNetCore.Services.IJsonApiContext.yml", + "JsonApiDotNetCore.Services.IJsonApiContext.PageManager": "JsonApiDotNetCore.Services.IJsonApiContext.yml", + "JsonApiDotNetCore.Services.IJsonApiContext.QuerySet": "JsonApiDotNetCore.Services.IJsonApiContext.yml", + "JsonApiDotNetCore.Services.IJsonApiContext.RelationshipsToUpdate": "JsonApiDotNetCore.Services.IJsonApiContext.yml", + "JsonApiDotNetCore.Services.IJsonApiContext.RequestEntity": "JsonApiDotNetCore.Services.IJsonApiContext.yml", + "JsonApiDotNetCore.Services.IQueryAccessor": "JsonApiDotNetCore.Services.IQueryAccessor.yml", + "JsonApiDotNetCore.Services.IQueryAccessor.GetRequired``1(System.String)": "JsonApiDotNetCore.Services.IQueryAccessor.yml", + "JsonApiDotNetCore.Services.IQueryAccessor.TryGetValue``1(System.String,``0@)": "JsonApiDotNetCore.Services.IQueryAccessor.yml", + "JsonApiDotNetCore.Services.IQueryParser": "JsonApiDotNetCore.Services.IQueryParser.yml", + "JsonApiDotNetCore.Services.IQueryParser.Parse(Microsoft.AspNetCore.Http.IQueryCollection)": "JsonApiDotNetCore.Services.IQueryParser.yml", + "JsonApiDotNetCore.Services.IRequestMeta": "JsonApiDotNetCore.Services.IRequestMeta.yml", + "JsonApiDotNetCore.Services.IRequestMeta.GetMeta": "JsonApiDotNetCore.Services.IRequestMeta.yml", + "JsonApiDotNetCore.Services.IResourceCmdService`1": "JsonApiDotNetCore.Services.IResourceCmdService-1.yml", + "JsonApiDotNetCore.Services.IResourceCmdService`2": "JsonApiDotNetCore.Services.IResourceCmdService-2.yml", + "JsonApiDotNetCore.Services.IResourceQueryService`1": "JsonApiDotNetCore.Services.IResourceQueryService-1.yml", + "JsonApiDotNetCore.Services.IResourceQueryService`2": "JsonApiDotNetCore.Services.IResourceQueryService-2.yml", + "JsonApiDotNetCore.Services.IResourceService`1": "JsonApiDotNetCore.Services.IResourceService-1.yml", + "JsonApiDotNetCore.Services.IResourceService`2": "JsonApiDotNetCore.Services.IResourceService-2.yml", + "JsonApiDotNetCore.Services.IScopedServiceProvider": "JsonApiDotNetCore.Services.IScopedServiceProvider.yml", + "JsonApiDotNetCore.Services.IUpdateRelationshipService`1": "JsonApiDotNetCore.Services.IUpdateRelationshipService-1.yml", + "JsonApiDotNetCore.Services.IUpdateRelationshipService`2": "JsonApiDotNetCore.Services.IUpdateRelationshipService-2.yml", + "JsonApiDotNetCore.Services.IUpdateRelationshipService`2.UpdateRelationshipsAsync(`1,System.String,System.Collections.Generic.List{JsonApiDotNetCore.Models.DocumentData})": "JsonApiDotNetCore.Services.IUpdateRelationshipService-2.yml", + "JsonApiDotNetCore.Services.IUpdateService`1": "JsonApiDotNetCore.Services.IUpdateService-1.yml", + "JsonApiDotNetCore.Services.IUpdateService`2": "JsonApiDotNetCore.Services.IUpdateService-2.yml", + "JsonApiDotNetCore.Services.IUpdateService`2.UpdateAsync(`1,`0)": "JsonApiDotNetCore.Services.IUpdateService-2.yml", + "JsonApiDotNetCore.Services.JsonApiContext": "JsonApiDotNetCore.Services.JsonApiContext.yml", + "JsonApiDotNetCore.Services.JsonApiContext.#ctor(JsonApiDotNetCore.Internal.IContextGraph,Microsoft.AspNetCore.Http.IHttpContextAccessor,JsonApiDotNetCore.Configuration.JsonApiOptions,JsonApiDotNetCore.Builders.IMetaBuilder,JsonApiDotNetCore.Internal.Generics.IGenericProcessorFactory,JsonApiDotNetCore.Services.IQueryParser,JsonApiDotNetCore.Services.IControllerContext)": "JsonApiDotNetCore.Services.JsonApiContext.yml", + "JsonApiDotNetCore.Services.JsonApiContext.ApplyContext``1(System.Object)": "JsonApiDotNetCore.Services.JsonApiContext.yml", + "JsonApiDotNetCore.Services.JsonApiContext.AttributesToUpdate": "JsonApiDotNetCore.Services.JsonApiContext.yml", + "JsonApiDotNetCore.Services.JsonApiContext.BasePath": "JsonApiDotNetCore.Services.JsonApiContext.yml", + "JsonApiDotNetCore.Services.JsonApiContext.ContextGraph": "JsonApiDotNetCore.Services.JsonApiContext.yml", + "JsonApiDotNetCore.Services.JsonApiContext.ControllerType": "JsonApiDotNetCore.Services.JsonApiContext.yml", + "JsonApiDotNetCore.Services.JsonApiContext.DocumentMeta": "JsonApiDotNetCore.Services.JsonApiContext.yml", + "JsonApiDotNetCore.Services.JsonApiContext.GenericProcessorFactory": "JsonApiDotNetCore.Services.JsonApiContext.yml", + "JsonApiDotNetCore.Services.JsonApiContext.GetControllerAttribute``1": "JsonApiDotNetCore.Services.JsonApiContext.yml", + "JsonApiDotNetCore.Services.JsonApiContext.IncludedRelationships": "JsonApiDotNetCore.Services.JsonApiContext.yml", + "JsonApiDotNetCore.Services.JsonApiContext.IsBulkOperationRequest": "JsonApiDotNetCore.Services.JsonApiContext.yml", + "JsonApiDotNetCore.Services.JsonApiContext.IsRelationshipData": "JsonApiDotNetCore.Services.JsonApiContext.yml", + "JsonApiDotNetCore.Services.JsonApiContext.IsRelationshipPath": "JsonApiDotNetCore.Services.JsonApiContext.yml", + "JsonApiDotNetCore.Services.JsonApiContext.MetaBuilder": "JsonApiDotNetCore.Services.JsonApiContext.yml", + "JsonApiDotNetCore.Services.JsonApiContext.Options": "JsonApiDotNetCore.Services.JsonApiContext.yml", + "JsonApiDotNetCore.Services.JsonApiContext.PageManager": "JsonApiDotNetCore.Services.JsonApiContext.yml", + "JsonApiDotNetCore.Services.JsonApiContext.QuerySet": "JsonApiDotNetCore.Services.JsonApiContext.yml", + "JsonApiDotNetCore.Services.JsonApiContext.RelationshipsToUpdate": "JsonApiDotNetCore.Services.JsonApiContext.yml", + "JsonApiDotNetCore.Services.JsonApiContext.RequestEntity": "JsonApiDotNetCore.Services.JsonApiContext.yml", + "JsonApiDotNetCore.Services.Operations": "JsonApiDotNetCore.Services.Operations.yml", + "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver": "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.yml", + "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.LocateCreateService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.yml", + "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.LocateGetService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.yml", + "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.LocateRemoveService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.yml", + "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.LocateUpdateService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver.yml", + "JsonApiDotNetCore.Services.Operations.IOperationsProcessor": "JsonApiDotNetCore.Services.Operations.IOperationsProcessor.yml", + "JsonApiDotNetCore.Services.Operations.IOperationsProcessor.ProcessAsync(System.Collections.Generic.List{JsonApiDotNetCore.Models.Operations.Operation})": "JsonApiDotNetCore.Services.Operations.IOperationsProcessor.yml", + "JsonApiDotNetCore.Services.Operations.IOpProcessor": "JsonApiDotNetCore.Services.Operations.IOpProcessor.yml", + "JsonApiDotNetCore.Services.Operations.IOpProcessor.ProcessAsync(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.IOpProcessor.yml", + "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver": "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.yml", + "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.#ctor(JsonApiDotNetCore.Internal.Generics.IGenericProcessorFactory,JsonApiDotNetCore.Services.IJsonApiContext)": "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.yml", + "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.LocateCreateService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.yml", + "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.LocateGetService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.yml", + "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.LocateRemoveService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.yml", + "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.LocateUpdateService(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.OperationProcessorResolver.yml", + "JsonApiDotNetCore.Services.Operations.OperationsProcessor": "JsonApiDotNetCore.Services.Operations.OperationsProcessor.yml", + "JsonApiDotNetCore.Services.Operations.OperationsProcessor.#ctor(JsonApiDotNetCore.Services.Operations.IOperationProcessorResolver,JsonApiDotNetCore.Data.IDbContextResolver)": "JsonApiDotNetCore.Services.Operations.OperationsProcessor.yml", + "JsonApiDotNetCore.Services.Operations.OperationsProcessor.ProcessAsync(System.Collections.Generic.List{JsonApiDotNetCore.Models.Operations.Operation})": "JsonApiDotNetCore.Services.Operations.OperationsProcessor.yml", + "JsonApiDotNetCore.Services.Operations.Processors": "JsonApiDotNetCore.Services.Operations.Processors.yml", + "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor-1.yml", + "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor`1.#ctor(JsonApiDotNetCore.Services.ICreateService{`0,System.Int32},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph)": "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor-1.yml", + "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor-2.yml", + "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor`2.#ctor(JsonApiDotNetCore.Services.ICreateService{`0,`1},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph)": "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor-2.yml", + "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor`2.ProcessAsync(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.Processors.CreateOpProcessor-2.yml", + "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor-1.yml", + "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor`1.#ctor(JsonApiDotNetCore.Services.IGetAllService{`0,System.Int32},JsonApiDotNetCore.Services.IGetByIdService{`0,System.Int32},JsonApiDotNetCore.Services.IGetRelationshipService{`0,System.Int32},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph,JsonApiDotNetCore.Services.IJsonApiContext)": "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor-1.yml", + "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor-2.yml", + "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor`2.#ctor(JsonApiDotNetCore.Services.IGetAllService{`0,`1},JsonApiDotNetCore.Services.IGetByIdService{`0,`1},JsonApiDotNetCore.Services.IGetRelationshipService{`0,`1},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph,JsonApiDotNetCore.Services.IJsonApiContext)": "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor-2.yml", + "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor`2.ProcessAsync(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.Processors.GetOpProcessor-2.yml", + "JsonApiDotNetCore.Services.Operations.Processors.ICreateOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.ICreateOpProcessor-1.yml", + "JsonApiDotNetCore.Services.Operations.Processors.ICreateOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.ICreateOpProcessor-2.yml", + "JsonApiDotNetCore.Services.Operations.Processors.IGetOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.IGetOpProcessor-1.yml", + "JsonApiDotNetCore.Services.Operations.Processors.IGetOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.IGetOpProcessor-2.yml", + "JsonApiDotNetCore.Services.Operations.Processors.IRemoveOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.IRemoveOpProcessor-1.yml", + "JsonApiDotNetCore.Services.Operations.Processors.IRemoveOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.IRemoveOpProcessor-2.yml", + "JsonApiDotNetCore.Services.Operations.Processors.IUpdateOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.IUpdateOpProcessor-1.yml", + "JsonApiDotNetCore.Services.Operations.Processors.IUpdateOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.IUpdateOpProcessor-2.yml", + "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor-1.yml", + "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor`1.#ctor(JsonApiDotNetCore.Services.IDeleteService{`0,System.Int32},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph)": "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor-1.yml", + "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor-2.yml", + "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor`2.#ctor(JsonApiDotNetCore.Services.IDeleteService{`0,`1},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph)": "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor-2.yml", + "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor`2.ProcessAsync(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.Processors.RemoveOpProcessor-2.yml", + "JsonApiDotNetCore.Services.Operations.Processors.UpdateOpProcessor`1": "JsonApiDotNetCore.Services.Operations.Processors.UpdateOpProcessor-1.yml", + "JsonApiDotNetCore.Services.Operations.Processors.UpdateOpProcessor`1.#ctor(JsonApiDotNetCore.Services.IUpdateService{`0,System.Int32},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph)": "JsonApiDotNetCore.Services.Operations.Processors.UpdateOpProcessor-1.yml", + "JsonApiDotNetCore.Services.Operations.Processors.UpdateOpProcessor`2": "JsonApiDotNetCore.Services.Operations.Processors.UpdateOpProcessor-2.yml", + "JsonApiDotNetCore.Services.Operations.Processors.UpdateOpProcessor`2.#ctor(JsonApiDotNetCore.Services.IUpdateService{`0,`1},JsonApiDotNetCore.Serialization.IJsonApiDeSerializer,JsonApiDotNetCore.Builders.IDocumentBuilder,JsonApiDotNetCore.Internal.IContextGraph)": "JsonApiDotNetCore.Services.Operations.Processors.UpdateOpProcessor-2.yml", + "JsonApiDotNetCore.Services.Operations.Processors.UpdateOpProcessor`2.ProcessAsync(JsonApiDotNetCore.Models.Operations.Operation)": "JsonApiDotNetCore.Services.Operations.Processors.UpdateOpProcessor-2.yml", + "JsonApiDotNetCore.Services.QueryAccessor": "JsonApiDotNetCore.Services.QueryAccessor.yml", + "JsonApiDotNetCore.Services.QueryAccessor.#ctor(JsonApiDotNetCore.Services.IJsonApiContext,Microsoft.Extensions.Logging.ILogger{JsonApiDotNetCore.Services.QueryAccessor})": "JsonApiDotNetCore.Services.QueryAccessor.yml", + "JsonApiDotNetCore.Services.QueryAccessor.GetRequired``1(System.String)": "JsonApiDotNetCore.Services.QueryAccessor.yml", + "JsonApiDotNetCore.Services.QueryAccessor.TryGetValue``1(System.String,``0@)": "JsonApiDotNetCore.Services.QueryAccessor.yml", + "JsonApiDotNetCore.Services.QueryParser": "JsonApiDotNetCore.Services.QueryParser.yml", + "JsonApiDotNetCore.Services.QueryParser.#ctor(JsonApiDotNetCore.Services.IControllerContext,JsonApiDotNetCore.Configuration.JsonApiOptions)": "JsonApiDotNetCore.Services.QueryParser.yml", + "JsonApiDotNetCore.Services.QueryParser.GetAttribute(System.String)": "JsonApiDotNetCore.Services.QueryParser.yml", + "JsonApiDotNetCore.Services.QueryParser.Parse(Microsoft.AspNetCore.Http.IQueryCollection)": "JsonApiDotNetCore.Services.QueryParser.yml", + "JsonApiDotNetCore.Services.QueryParser.ParseFieldsQuery(System.String,System.String)": "JsonApiDotNetCore.Services.QueryParser.yml", + "JsonApiDotNetCore.Services.QueryParser.ParseFilterOperation(System.String)": "JsonApiDotNetCore.Services.QueryParser.yml", + "JsonApiDotNetCore.Services.QueryParser.ParseFilterQuery(System.String,System.String)": "JsonApiDotNetCore.Services.QueryParser.yml", + "JsonApiDotNetCore.Services.QueryParser.ParseIncludedRelationships(System.String)": "JsonApiDotNetCore.Services.QueryParser.yml", + "JsonApiDotNetCore.Services.QueryParser.ParsePageQuery(JsonApiDotNetCore.Internal.Query.PageQuery,System.String,System.String)": "JsonApiDotNetCore.Services.QueryParser.yml", + "JsonApiDotNetCore.Services.QueryParser.ParseSortParameters(System.String)": "JsonApiDotNetCore.Services.QueryParser.yml", + "JsonApiDotNetCore.Services.RequestScopedServiceProvider": "JsonApiDotNetCore.Services.RequestScopedServiceProvider.yml", + "JsonApiDotNetCore.Services.RequestScopedServiceProvider.#ctor(Microsoft.AspNetCore.Http.IHttpContextAccessor)": "JsonApiDotNetCore.Services.RequestScopedServiceProvider.yml", + "JsonApiDotNetCore.Services.RequestScopedServiceProvider.GetService(System.Type)": "JsonApiDotNetCore.Services.RequestScopedServiceProvider.yml" +} \ No newline at end of file diff --git a/src/JsonApiDotNetCore/api/index.md b/src/JsonApiDotNetCore/api/index.md new file mode 100644 index 0000000000..78dc9c0057 --- /dev/null +++ b/src/JsonApiDotNetCore/api/index.md @@ -0,0 +1,2 @@ +# PLACEHOLDER +TODO: Add .NET projects to the *src* folder and run `docfx` to generate **REAL** *API Documentation*! diff --git a/src/JsonApiDotNetCore/articles/intro.md b/src/JsonApiDotNetCore/articles/intro.md new file mode 100644 index 0000000000..c0478cedea --- /dev/null +++ b/src/JsonApiDotNetCore/articles/intro.md @@ -0,0 +1 @@ +# Add your introductions here! diff --git a/src/JsonApiDotNetCore/articles/toc.yml b/src/JsonApiDotNetCore/articles/toc.yml new file mode 100644 index 0000000000..ff89ef1fe0 --- /dev/null +++ b/src/JsonApiDotNetCore/articles/toc.yml @@ -0,0 +1,2 @@ +- name: Introduction + href: intro.md diff --git a/src/JsonApiDotNetCore/docfx.json b/src/JsonApiDotNetCore/docfx.json new file mode 100644 index 0000000000..5c46dcbd88 --- /dev/null +++ b/src/JsonApiDotNetCore/docfx.json @@ -0,0 +1,52 @@ +{ + "metadata": [ + { + "src": [ + { + "files": [ "**.csproj" ], + "src": "C:\\Users\\jnance\\dev\\json-api-dotnet-core\\src\\JsonApiDotNetCore" + } + ], + "dest": "api", + "disableGitFeatures": false, + "properties": { + "targetFramework": "netstandard2.0" + } + } + ], + "build": { + "content": [ + { + "files": [ "api/**.yml", "api/index.md" ] + }, + { + "files": [ + "articles/**.md", + "articles/**/toc.yml", + "toc.yml", + "*.md" + ] + } + ], + "resource": [ + { + "files": [ "images/**" ] + } + ], + "overwrite": [ + { + "files": [ "apidoc/**.md" ], + "exclude": [ "obj/**", "_site/**" ] + } + ], + "dest": "_site", + "globalMetadataFiles": [], + "fileMetadataFiles": [], + "template": [ "default" ], + "postProcessors": [], + "noLangKeyword": false, + "keepFileLink": false, + "cleanupCacheHistory": false, + "disableGitFeatures": false + } +} diff --git a/src/JsonApiDotNetCore/index.md b/src/JsonApiDotNetCore/index.md new file mode 100644 index 0000000000..3ae2506361 --- /dev/null +++ b/src/JsonApiDotNetCore/index.md @@ -0,0 +1,4 @@ +# This is the **HOMEPAGE**. +Refer to [Markdown](http://daringfireball.net/projects/markdown/) for how to write markdown files. +## Quick Start Notes: +1. Add images to the *images* folder if the file is referencing an image. diff --git a/src/JsonApiDotNetCore/toc.yml b/src/JsonApiDotNetCore/toc.yml new file mode 100644 index 0000000000..59f8010471 --- /dev/null +++ b/src/JsonApiDotNetCore/toc.yml @@ -0,0 +1,5 @@ +- name: Articles + href: articles/ +- name: Api Documentation + href: api/ + homepage: api/index.md diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/CamelCasedModelsControllerTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/CamelCasedModelsControllerTests.cs index b76293adba..533c59839a 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/CamelCasedModelsControllerTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/CamelCasedModelsControllerTests.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Net; using System.Net.Http; using System.Net.Http.Headers; @@ -19,12 +19,12 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance [Collection("WebHostCollection")] public class CamelCasedModelsControllerTests { - private TestFixture _fixture; + private TestFixture _fixture; private AppDbContext _context; private IJsonApiContext _jsonApiContext; private Faker _faker; - public CamelCasedModelsControllerTests(TestFixture fixture) + public CamelCasedModelsControllerTests(TestFixture fixture) { _fixture = fixture; _context = fixture.GetService(); @@ -58,7 +58,7 @@ public async Task Can_Get_CamelCasedModels() // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotEmpty(deserializedBody); - Assert.True(deserializedBody.Count > 0); + Assert.True(deserializedBody.Count > 0); } [Fact] @@ -114,7 +114,7 @@ public async Task Can_Post_CamelCasedModels() var request = new HttpRequestMessage(httpMethod, route); request.Content = new StringContent(JsonConvert.SerializeObject(content)); request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json"); - + // Act var response = await client.SendAsync(request); var body = await response.Content.ReadAsStringAsync(); @@ -158,7 +158,7 @@ public async Task Can_Patch_CamelCasedModels() var request = new HttpRequestMessage(httpMethod, route); request.Content = new StringContent(JsonConvert.SerializeObject(content)); request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json"); - + // Act var response = await client.SendAsync(request); var body = await response.Content.ReadAsStringAsync(); @@ -173,4 +173,4 @@ public async Task Can_Patch_CamelCasedModels() Assert.Equal(newModel.CompoundAttr, deserializedBody.CompoundAttr); } } -} \ No newline at end of file +} diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/CustomControllerTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/CustomControllerTests.cs index 9b28ee48de..478f40f14f 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/CustomControllerTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/CustomControllerTests.cs @@ -17,11 +17,11 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Extensibility [Collection("WebHostCollection")] public class CustomControllerTests { - private TestFixture _fixture; + private TestFixture _fixture; private Faker _todoItemFaker; private Faker _personFaker; - public CustomControllerTests(TestFixture fixture) + public CustomControllerTests(TestFixture fixture) { _fixture = fixture; _todoItemFaker = new Faker() diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/NullValuedAttributeHandlingTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/NullValuedAttributeHandlingTests.cs index 250ab80d30..7942ffd919 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/NullValuedAttributeHandlingTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/NullValuedAttributeHandlingTests.cs @@ -14,11 +14,11 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Extensibility [Collection("WebHostCollection")] public class NullValuedAttributeHandlingTests : IAsyncLifetime { - private readonly TestFixture _fixture; + private readonly TestFixture _fixture; private readonly AppDbContext _dbContext; private readonly TodoItem _todoItem; - public NullValuedAttributeHandlingTests(TestFixture fixture) + public NullValuedAttributeHandlingTests(TestFixture fixture) { _fixture = fixture; _dbContext = fixture.GetService(); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RepositoryOverrideTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RepositoryOverrideTests.cs index 2813151ad3..09a2791048 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RepositoryOverrideTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RepositoryOverrideTests.cs @@ -17,9 +17,9 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Extensibility [Collection("WebHostCollection")] public class RepositoryOverrideTests { - private TestFixture _fixture; + private TestFixture _fixture; - public RepositoryOverrideTests(TestFixture fixture) + public RepositoryOverrideTests(TestFixture fixture) { _fixture = fixture; } diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RequestMetaTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RequestMetaTests.cs index 9420ea6891..2397bb5529 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RequestMetaTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Extensibility/RequestMetaTests.cs @@ -16,9 +16,9 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Extensibility [Collection("WebHostCollection")] public class RequestMetaTests { - private TestFixture _fixture; + private TestFixture _fixture; - public RequestMetaTests(TestFixture fixture) + public RequestMetaTests(TestFixture fixture) { _fixture = fixture; } diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs index dd7c673b4c..083b2c22d7 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Net; using System.Net.Http; @@ -6,7 +6,6 @@ using Bogus; using JsonApiDotNetCore.Models; using JsonApiDotNetCore.Serialization; -using JsonApiDotNetCoreExample; using JsonApiDotNetCoreExample.Data; using JsonApiDotNetCoreExample.Models; using Newtonsoft.Json; @@ -18,11 +17,11 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec [Collection("WebHostCollection")] public class AttributeFilterTests { - private TestFixture _fixture; + private TestFixture _fixture; private Faker _todoItemFaker; private readonly Faker _personFaker; - public AttributeFilterTests(TestFixture fixture) + public AttributeFilterTests(TestFixture fixture) { _fixture = fixture; _todoItemFaker = new Faker() @@ -88,7 +87,7 @@ public async Task Can_Filter_On_Related_Attrs() Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(included); Assert.NotEmpty(included); - foreach(var item in included) + foreach (var item in included) Assert.Equal(person.FirstName, item.Attributes["first-name"]); } diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeSortTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeSortTests.cs index 8525f251d1..6de3293596 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeSortTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeSortTests.cs @@ -9,9 +9,9 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec [Collection("WebHostCollection")] public class AttributeSortTests { - private TestFixture _fixture; + private TestFixture _fixture; - public AttributeSortTests(TestFixture fixture) + public AttributeSortTests(TestFixture fixture) { _fixture = fixture; } diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/ContentNegotiation.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/ContentNegotiation.cs index 8f76735ee9..76f5fa4aa7 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/ContentNegotiation.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/ContentNegotiation.cs @@ -12,8 +12,8 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec [Collection("WebHostCollection")] public class ContentNegotiation { - private TestFixture _fixture; - public ContentNegotiation(TestFixture fixture) + private TestFixture _fixture; + public ContentNegotiation(TestFixture fixture) { _fixture = fixture; } diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs index 2f461c4f74..2c71275473 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs @@ -23,11 +23,11 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec [Collection("WebHostCollection")] public class CreatingDataTests { - private TestFixture _fixture; + private TestFixture _fixture; private IJsonApiContext _jsonApiContext; private Faker _todoItemFaker; - public CreatingDataTests(TestFixture fixture) + public CreatingDataTests(TestFixture fixture) { _fixture = fixture; _jsonApiContext = fixture.GetService(); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DeletingDataTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DeletingDataTests.cs index 8ddb9a56a1..8c506f4a33 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DeletingDataTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DeletingDataTests.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using System.Net; using System.Net.Http; using System.Threading.Tasks; @@ -15,11 +15,11 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec [Collection("WebHostCollection")] public class DeletingDataTests { - private TestFixture _fixture; + private TestFixture _fixture; private AppDbContext _context; private Faker _todoItemFaker; - public DeletingDataTests(TestFixture fixture) + public DeletingDataTests(TestFixture fixture) { _fixture = fixture; _context = fixture.GetService(); @@ -40,7 +40,7 @@ public async Task Respond_404_If_EntityDoesNotExist() var server = new TestServer(builder); var client = server.CreateClient(); - + var httpMethod = new HttpMethod("DELETE"); var route = $"/api/v1/todo-items/{maxPersonId + 100}"; var request = new HttpRequestMessage(httpMethod, route); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs index 5d4a4aa4e2..a9aa9c4e67 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Included.cs @@ -19,13 +19,13 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec.DocumentTests [Collection("WebHostCollection")] public class Included { - private TestFixture _fixture; + private TestFixture _fixture; private AppDbContext _context; private Bogus.Faker _personFaker; private Faker _todoItemFaker; private Faker _todoItemCollectionFaker; - public Included(TestFixture fixture) + public Included(TestFixture fixture) { _fixture = fixture; _context = fixture.GetService(); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs index 5316753245..bb055e9935 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs @@ -17,9 +17,9 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec.DocumentTests [Collection("WebHostCollection")] public class Meta { - private TestFixture _fixture; + private TestFixture _fixture; private AppDbContext _context; - public Meta(TestFixture fixture) + public Meta(TestFixture fixture) { _fixture = fixture; _context = fixture.GetService(); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs index 0aa4ede88b..787c9f07a0 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/PagingTests.cs @@ -18,13 +18,13 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec.DocumentTests [Collection("WebHostCollection")] public class PagingTests { - private TestFixture _fixture; + private TestFixture _fixture; private AppDbContext _context; private Faker _personFaker; private Faker _todoItemFaker; private Faker _todoItemCollectionFaker; - public PagingTests(TestFixture fixture) + public PagingTests(TestFixture fixture) { _fixture = fixture; _context = fixture.GetService(); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Relationships.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Relationships.cs index 5c0018354d..6c4bf56839 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Relationships.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Relationships.cs @@ -17,11 +17,11 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec.DocumentTests [Collection("WebHostCollection")] public class Relationships { - private TestFixture _fixture; + private TestFixture _fixture; private AppDbContext _context; private Faker _todoItemFaker; - public Relationships(TestFixture fixture) + public Relationships(TestFixture fixture) { _fixture = fixture; _context = fixture.GetService(); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingDataTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingDataTests.cs index 208ec2f72d..8573d0b560 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingDataTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingDataTests.cs @@ -20,12 +20,12 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec [Collection("WebHostCollection")] public class FetchingDataTests { - private TestFixture _fixture; + private TestFixture _fixture; private IJsonApiContext _jsonApiContext; private Faker _todoItemFaker; private Faker _personFaker; - public FetchingDataTests(TestFixture fixture) + public FetchingDataTests(TestFixture fixture) { _fixture = fixture; _jsonApiContext = fixture.GetService(); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingRelationshipsTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingRelationshipsTests.cs index ea805c515f..621cb8e349 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingRelationshipsTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingRelationshipsTests.cs @@ -16,11 +16,11 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec [Collection("WebHostCollection")] public class FetchingRelationshipsTests { - private TestFixture _fixture; + private TestFixture _fixture; private IJsonApiContext _jsonApiContext; private Faker _todoItemFaker; - public FetchingRelationshipsTests(TestFixture fixture) + public FetchingRelationshipsTests(TestFixture fixture) { _fixture = fixture; _jsonApiContext = fixture.GetService(); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs index 7d8401f78d..2d77982e62 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/PagingTests.cs @@ -10,15 +10,18 @@ using Xunit; using Person = JsonApiDotNetCoreExample.Models.Person; -namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec { - public class PagingTests : TestFixture { +namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec +{ + public class PagingTests : TestFixture + { private readonly Faker _todoItemFaker = new Faker() .RuleFor(t => t.Description, f => f.Lorem.Sentence()) .RuleFor(t => t.Ordinal, f => f.Random.Number()) .RuleFor(t => t.CreatedDate, f => f.Date.Past()); [Fact] - public async Task Can_Paginate_TodoItems() { + public async Task Can_Paginate_TodoItems() + { // Arrange const int expectedEntitiesPerPage = 2; var totalCount = expectedEntitiesPerPage * 2; @@ -47,7 +50,8 @@ public async Task Can_Paginate_TodoItems() { } [Fact] - public async Task Can_Paginate_TodoItems_From_Start() { + public async Task Can_Paginate_TodoItems_From_Start() + { // Arrange const int expectedEntitiesPerPage = 2; var totalCount = expectedEntitiesPerPage * 2; @@ -77,7 +81,8 @@ public async Task Can_Paginate_TodoItems_From_Start() { } [Fact] - public async Task Can_Paginate_TodoItems_From_End() { + public async Task Can_Paginate_TodoItems_From_End() + { // Arrange const int expectedEntitiesPerPage = 2; var totalCount = expectedEntitiesPerPage * 2; diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/QueryParameters.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/QueryParameters.cs index c5a02cb6b7..f5f61e156d 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/QueryParameters.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/QueryParameters.cs @@ -13,8 +13,8 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec [Collection("WebHostCollection")] public class QueryParameters { - private TestFixture _fixture; - public QueryParameters(TestFixture fixture) + private TestFixture _fixture; + public QueryParameters(TestFixture fixture) { _fixture = fixture; } diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/SparseFieldSetTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/SparseFieldSetTests.cs index 8c5c6b5249..7286a94fc5 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/SparseFieldSetTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/SparseFieldSetTests.cs @@ -21,10 +21,10 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec [Collection("WebHostCollection")] public class SparseFieldSetTests { - private TestFixture _fixture; + private TestFixture _fixture; private readonly AppDbContext _dbContext; - public SparseFieldSetTests(TestFixture fixture) + public SparseFieldSetTests(TestFixture fixture) { _fixture = fixture; _dbContext = fixture.GetService(); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingDataTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingDataTests.cs index d39f69a855..36ea085508 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingDataTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingDataTests.cs @@ -20,12 +20,12 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec [Collection("WebHostCollection")] public class UpdatingDataTests { - private TestFixture _fixture; + private TestFixture _fixture; private AppDbContext _context; private Faker _todoItemFaker; private Faker _personFaker; - public UpdatingDataTests(TestFixture fixture) + public UpdatingDataTests(TestFixture fixture) { _fixture = fixture; _context = fixture.GetService(); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs index 5cc3772497..1dffa6ce87 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingRelationshipsTests.cs @@ -20,12 +20,12 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec [Collection("WebHostCollection")] public class UpdatingRelationshipsTests { - private TestFixture _fixture; + private TestFixture _fixture; private AppDbContext _context; private Bogus.Faker _personFaker; private Faker _todoItemFaker; - public UpdatingRelationshipsTests(TestFixture fixture) + public UpdatingRelationshipsTests(TestFixture fixture) { _fixture = fixture; _context = fixture.GetService(); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs index d7ec6868b9..ce70fced84 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.TestHost; using JsonApiDotNetCore.Services; +using JsonApiDotNetCore.Data; namespace JsonApiDotNetCoreExampleTests.Acceptance { @@ -22,7 +23,7 @@ public TestFixture() _services = _server.Host.Services; Client = _server.CreateClient(); - Context = GetService(); + Context = GetService().GetContext() as AppDbContext; DeSerializer = GetService(); JsonApiContext = GetService(); } diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs index 657e282cb8..acd37a535a 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; @@ -19,12 +19,12 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance [Collection("WebHostCollection")] public class TodoItemControllerTests { - private TestFixture _fixture; + private TestFixture _fixture; private AppDbContext _context; private IJsonApiContext _jsonApiContext; private Faker _todoItemFaker; - public TodoItemControllerTests(TestFixture fixture) + public TodoItemControllerTests(TestFixture fixture) { _fixture = fixture; _context = fixture.GetService(); @@ -75,7 +75,7 @@ public async Task Can_Filter_TodoItems() var httpMethod = new HttpMethod("GET"); var route = $"/api/v1/todo-items?filter[ordinal]={todoItem.Ordinal}"; var request = new HttpRequestMessage(httpMethod, route); - + // Act var response = await _fixture.Client.SendAsync(request); var body = await response.Content.ReadAsStringAsync(); @@ -339,7 +339,7 @@ public async Task Can_Patch_TodoItem() var request = new HttpRequestMessage(httpMethod, route); request.Content = new StringContent(JsonConvert.SerializeObject(content)); request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json"); - + // Act var response = await _fixture.Client.SendAsync(request); var body = await response.Content.ReadAsStringAsync(); @@ -484,4 +484,4 @@ public async Task Can_Delete_TodoItem() Assert.Null(_context.TodoItems.FirstOrDefault(t => t.Id == todoItem.Id)); } } -} \ No newline at end of file +} diff --git a/test/JsonApiDotNetCoreExampleTests/Helpers/Startups/AuthorizedStartup.cs b/test/JsonApiDotNetCoreExampleTests/Helpers/Startups/AuthorizedStartup.cs index 21cfa0e0dc..12a207fea8 100644 --- a/test/JsonApiDotNetCoreExampleTests/Helpers/Startups/AuthorizedStartup.cs +++ b/test/JsonApiDotNetCoreExampleTests/Helpers/Startups/AuthorizedStartup.cs @@ -11,14 +11,16 @@ using JsonApiDotNetCore.Data; using JsonApiDotNetCoreExample.Models; using JsonApiDotNetCoreExampleTests.Repositories; +using UnitTests; +using JsonApiDotNetCore.Services; namespace JsonApiDotNetCoreExampleTests.Startups { public class AuthorizedStartup : Startup { public AuthorizedStartup(IHostingEnvironment env) - : base (env) - { } + : base(env) + { } public override IServiceProvider ConfigureServices(IServiceCollection services) { @@ -46,6 +48,8 @@ public override IServiceProvider ConfigureServices(IServiceCollection services) services.AddSingleton(authServicMock.Object); services.AddScoped, AuthorizedTodoItemsRepository>(); + services.AddScoped(); + return services.BuildServiceProvider(); } } diff --git a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj index 90bd4050e7..b1df354bf7 100755 --- a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj +++ b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj @@ -13,6 +13,7 @@ + diff --git a/test/JsonApiDotNetCoreExampleTests/TestStartup.cs b/test/JsonApiDotNetCoreExampleTests/TestStartup.cs new file mode 100644 index 0000000000..886d6b3424 --- /dev/null +++ b/test/JsonApiDotNetCoreExampleTests/TestStartup.cs @@ -0,0 +1,22 @@ +using JsonApiDotNetCore.Services; +using JsonApiDotNetCoreExample; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using System; +using UnitTests; + +namespace JsonApiDotNetCoreExampleTests +{ + public class TestStartup : Startup + { + public TestStartup(IHostingEnvironment env) : base(env) + { } + + public override IServiceProvider ConfigureServices(IServiceCollection services) + { + base.ConfigureServices(services); + services.AddScoped(); + return services.BuildServiceProvider(); + } + } +} diff --git a/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs b/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs index b654727a26..f6772fa22b 100644 --- a/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Unit/Extensions/IServiceCollectionExtensionsTests.cs @@ -10,9 +10,9 @@ using JsonApiDotNetCoreExample.Data; using JsonApiDotNetCoreExample.Models; using Microsoft.AspNetCore.Http; -using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.DependencyInjection; +using UnitTests; using Xunit; namespace JsonApiDotNetCoreExampleTests.Unit.Extensions @@ -25,7 +25,7 @@ public void AddJsonApiInternals_Adds_All_Required_Services() // arrange var services = new ServiceCollection(); var jsonApiOptions = new JsonApiOptions(); - + services.AddDbContext(options => { options.UseMemoryCache(new MemoryCache(new MemoryCacheOptions())); @@ -33,6 +33,9 @@ public void AddJsonApiInternals_Adds_All_Required_Services() // act services.AddJsonApiInternals(jsonApiOptions); + // this is required because the DbContextResolver requires access to the current HttpContext + // to get the request scoped DbContext instance + services.AddScoped(); var provider = services.BuildServiceProvider(); // assert diff --git a/test/JsonApiDotNetCoreExampleTests/WebHostCollection.cs b/test/JsonApiDotNetCoreExampleTests/WebHostCollection.cs index 43a89616df..960b7c1e46 100644 --- a/test/JsonApiDotNetCoreExampleTests/WebHostCollection.cs +++ b/test/JsonApiDotNetCoreExampleTests/WebHostCollection.cs @@ -6,6 +6,6 @@ namespace JsonApiDotNetCoreExampleTests { [CollectionDefinition("WebHostCollection")] public class WebHostCollection - : ICollectionFixture> + : ICollectionFixture> { } } diff --git a/test/JsonApiDotNetCoreExampleTests/appsettings.json b/test/JsonApiDotNetCoreExampleTests/appsettings.json index 7af3457293..e65cee8d0d 100644 --- a/test/JsonApiDotNetCoreExampleTests/appsettings.json +++ b/test/JsonApiDotNetCoreExampleTests/appsettings.json @@ -1,14 +1,13 @@ { - "Data": { - "DefaultConnection": - "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password=" - }, - "Logging": { - "IncludeScopes": false, - "LogLevel": { - "Default": "Error", - "System": "Information", - "Microsoft": "Information" + "Data": { + "DefaultConnection": "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password=postgres" + }, + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Error", + "System": "Information", + "Microsoft": "Information" + } } - } } diff --git a/test/NoEntityFrameworkTests/Acceptance/Extensibility/NoEntityFrameworkTests.cs b/test/NoEntityFrameworkTests/Acceptance/Extensibility/NoEntityFrameworkTests.cs index 41a48f2743..e80acc5d50 100644 --- a/test/NoEntityFrameworkTests/Acceptance/Extensibility/NoEntityFrameworkTests.cs +++ b/test/NoEntityFrameworkTests/Acceptance/Extensibility/NoEntityFrameworkTests.cs @@ -10,7 +10,6 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.TestHost; using Newtonsoft.Json; -using NoEntityFrameworkExample; using Xunit; namespace NoEntityFrameworkTests.Acceptance.Extensibility @@ -23,7 +22,7 @@ public class NoEntityFrameworkTests public NoEntityFrameworkTests() { var builder = new WebHostBuilder() - .UseStartup(); + .UseStartup(); _server = new TestServer(builder); _context = _server.GetService(); _context.Database.EnsureCreated(); @@ -97,7 +96,7 @@ public async Task Can_Create_TodoItems() type = "custom-todo-items", attributes = new { - description = description, + description, ordinal = 1 } } diff --git a/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj b/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj index 646cf9d538..f1d4044e0b 100644 --- a/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj +++ b/test/NoEntityFrameworkTests/NoEntityFrameworkTests.csproj @@ -17,6 +17,7 @@ + diff --git a/test/NoEntityFrameworkTests/TestStartup.cs b/test/NoEntityFrameworkTests/TestStartup.cs new file mode 100644 index 0000000000..e925e69fd0 --- /dev/null +++ b/test/NoEntityFrameworkTests/TestStartup.cs @@ -0,0 +1,22 @@ +using JsonApiDotNetCore.Services; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using NoEntityFrameworkExample; +using System; +using UnitTests; + +namespace NoEntityFrameworkTests +{ + public class TestStartup : Startup + { + public TestStartup(IHostingEnvironment env) : base(env) + { } + + public override IServiceProvider ConfigureServices(IServiceCollection services) + { + base.ConfigureServices(services); + services.AddScoped(); + return services.BuildServiceProvider(); + } + } +} diff --git a/test/NoEntityFrameworkTests/appsettings.json b/test/NoEntityFrameworkTests/appsettings.json index 7067b2bee0..01f85e6699 100644 --- a/test/NoEntityFrameworkTests/appsettings.json +++ b/test/NoEntityFrameworkTests/appsettings.json @@ -1,14 +1,13 @@ { - "Data": { - "DefaultConnection": - "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password=" - }, - "Logging": { - "IncludeScopes": false, - "LogLevel": { - "Default": "Debug", - "System": "Information", - "Microsoft": "Information" + "Data": { + "DefaultConnection": "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password=postgres" + }, + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } } - } } diff --git a/test/OperationsExampleTests/Add/AddTests.cs b/test/OperationsExampleTests/Add/AddTests.cs index 2d765e1633..39e9e8a2a6 100644 --- a/test/OperationsExampleTests/Add/AddTests.cs +++ b/test/OperationsExampleTests/Add/AddTests.cs @@ -3,41 +3,33 @@ using System.Net; using System.Threading.Tasks; using Bogus; -using JsonApiDotNetCore.Extensions; using JsonApiDotNetCore.Models.Operations; +using JsonApiDotNetCoreExample.Data; using Microsoft.EntityFrameworkCore; -using OperationsExample.Data; using OperationsExampleTests.Factories; using Xunit; namespace OperationsExampleTests { - [Collection("WebHostCollection")] - public class AddTests + public class AddTests : Fixture { - private readonly Fixture _fixture; private readonly Faker _faker = new Faker(); - public AddTests(Fixture fixture) - { - _fixture = fixture; - } - [Fact] - public async Task Can_Create_Article() + public async Task Can_Create_Author() { // arrange - var context = _fixture.GetService(); - var article = ArticleFactory.Get(); + var context = GetService(); + var author = AuthorFactory.Get(); var content = new { operations = new[] { new { op = "add", data = new { - type = "articles", + type = "authors", attributes = new { - name = article.Name + name = author.Name } } } @@ -45,24 +37,24 @@ public async Task Can_Create_Article() }; // act - var result = await _fixture.PatchAsync("api/bulk", content); + var (response, data) = await PatchAsync("api/bulk", content); // assert - Assert.NotNull(result); - Assert.Equal(HttpStatusCode.OK, result.response.StatusCode); + Assert.NotNull(response); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var id = (string)result.data.Operations.Single().DataObject.Id; - var lastArticle = await context.Articles.SingleAsync(a => a.StringId == id); - Assert.Equal(article.Name, lastArticle.Name); + var id = data.Operations.Single().DataObject.Id; + var lastAuthor = await context.Authors.SingleAsync(a => a.StringId == id); + Assert.Equal(author.Name, lastAuthor.Name); } [Fact] - public async Task Can_Create_Articles() + public async Task Can_Create_Authors() { // arrange var expectedCount = _faker.Random.Int(1, 10); - var context = _fixture.GetService(); - var articles = ArticleFactory.Get(expectedCount); + var context = GetService(); + var authors = AuthorFactory.Get(expectedCount); var content = new { operations = new List() @@ -76,10 +68,10 @@ public async Task Can_Create_Articles() op = "add", data = new { - type = "articles", + type = "authors", attributes = new { - name = articles[i].Name + name = authors[i].Name } } } @@ -87,19 +79,86 @@ public async Task Can_Create_Articles() } // act - var result = await _fixture.PatchAsync("api/bulk", content); + var (response, data) = await PatchAsync("api/bulk", content); // assert - Assert.NotNull(result); - Assert.Equal(HttpStatusCode.OK, result.response.StatusCode); - Assert.Equal(expectedCount, result.data.Operations.Count); + Assert.NotNull(response); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal(expectedCount, data.Operations.Count); for (int i = 0; i < expectedCount; i++) { - var data = result.data.Operations[i].DataObject; - var article = context.Articles.Single(a => a.StringId == data.Id.ToString()); - Assert.Equal(articles[i].Name, article.Name); + var dataObject = data.Operations[i].DataObject; + var author = context.Authors.Single(a => a.StringId == dataObject.Id); + Assert.Equal(authors[i].Name, author.Name); } + } + + [Fact] + public async Task Can_Create_Author_With_Article() + { + // arrange + var context = GetService(); + var author = AuthorFactory.Get(); + var article = ArticleFactory.Get(); + const string authorLocalId = "author-1"; + + var content = new + { + operations = new object[] { + new { + op = "add", + data = new { + lid = authorLocalId, + type = "authors", + attributes = new { + name = author.Name + }, + } + }, + new { + op = "add", + data = new { + type = "articles", + attributes = new { + name = article.Name + }, + relationships = new { + author = new { + data = new { + type = "authors", + lid = authorLocalId + } + } + } + } + } + } + }; + + // act + var (response, data) = await PatchAsync("api/bulk", content); + + // assert + Assert.NotNull(response); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal(2, data.Operations.Count); + + var authorOperationResult = data.Operations[0]; + var id = authorOperationResult.DataObject.Id; + var lastAuthor = await context.Authors + .Include(a => a.Articles) + .SingleAsync(a => a.StringId == id); + var articleOperationResult = data.Operations[1]; + + // author validation + Assert.Equal(authorLocalId, authorOperationResult.DataObject.LocalId); + Assert.Equal(author.Name, lastAuthor.Name); + + // article validation + Assert.Equal(1, lastAuthor.Articles.Count); + Assert.Equal(article.Name, lastAuthor.Articles[0].Name); + Assert.Equal(articleOperationResult.DataObject.Id, lastAuthor.Articles[0].StringId); } } } diff --git a/test/OperationsExampleTests/Factories/ArticleFactory.cs b/test/OperationsExampleTests/Factories/ArticleFactory.cs index 1907e2de24..a03bc3fbea 100644 --- a/test/OperationsExampleTests/Factories/ArticleFactory.cs +++ b/test/OperationsExampleTests/Factories/ArticleFactory.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using Bogus; -using OperationsExample.Models; +using JsonApiDotNetCoreExample.Models; namespace OperationsExampleTests.Factories { @@ -22,4 +22,4 @@ public static List
Get(int count) return articles; } } -} \ No newline at end of file +} diff --git a/test/OperationsExampleTests/Factories/AuthorFactory.cs b/test/OperationsExampleTests/Factories/AuthorFactory.cs new file mode 100644 index 0000000000..e80b100a59 --- /dev/null +++ b/test/OperationsExampleTests/Factories/AuthorFactory.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using Bogus; +using JsonApiDotNetCoreExample.Models; + +namespace OperationsExampleTests.Factories +{ + public static class AuthorFactory + { + public static Author Get() + { + var faker = new Faker(); + faker.RuleFor(m => m.Name, f => f.Person.UserName); + return faker.Generate(); + } + + public static List Get(int count) + { + var authors = new List(); + for (int i = 0; i < count; i++) + authors.Add(Get()); + + return authors; + } + } +} diff --git a/test/OperationsExampleTests/WebHostCollection.cs b/test/OperationsExampleTests/Fixture.cs similarity index 64% rename from test/OperationsExampleTests/WebHostCollection.cs rename to test/OperationsExampleTests/Fixture.cs index e385ace992..11621d36e4 100644 --- a/test/OperationsExampleTests/WebHostCollection.cs +++ b/test/OperationsExampleTests/Fixture.cs @@ -1,29 +1,42 @@ +using System; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; +using JsonApiDotNetCoreExample.Data; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.TestHost; using Newtonsoft.Json; -using OperationsExample; using Xunit; +[assembly: CollectionBehavior(DisableTestParallelization = true)] namespace OperationsExampleTests { - [CollectionDefinition("WebHostCollection")] - public class WebHostCollection : ICollectionFixture - { } - - public class Fixture + public class Fixture : IDisposable { public Fixture() { - var builder = new WebHostBuilder().UseStartup(); + var builder = new WebHostBuilder().UseStartup(); Server = new TestServer(builder); Client = Server.CreateClient(); } public TestServer Server { get; private set; } public HttpClient Client { get; } + + public void Dispose() + { + try + { + var context = GetService(); + context.Articles.RemoveRange(context.Articles); + context.Authors.RemoveRange(context.Authors); + context.SaveChanges(); + } // it is possible the test may try to do something that is an invalid db operation + // validation should be left up to the test, so we should not bomb the run in the + // disposal of that context + catch (Exception) { } + } + public T GetService() => (T)Server.Host.Services.GetService(typeof(T)); public async Task PatchAsync(string route, object data) diff --git a/test/OperationsExampleTests/Get/GetByIdTests.cs b/test/OperationsExampleTests/Get/GetByIdTests.cs new file mode 100644 index 0000000000..1dee2867ce --- /dev/null +++ b/test/OperationsExampleTests/Get/GetByIdTests.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using Bogus; +using JsonApiDotNetCore.Internal; +using JsonApiDotNetCore.Models.Operations; +using JsonApiDotNetCoreExample.Data; +using OperationsExampleTests.Factories; +using Xunit; + +namespace OperationsExampleTests +{ + public class GetTests : Fixture, IDisposable + { + private readonly Faker _faker = new Faker(); + + [Fact] + public async Task Can_Get_Author_By_Id() + { + // arrange + var context = GetService(); + var author = AuthorFactory.Get(); + context.Authors.Add(author); + context.SaveChanges(); + + var content = new + { + operations = new[] { + new Dictionary { + { "op", "get"}, + { "ref", new { type = "authors", id = author.StringId } } + } + } + }; + + // act + var result = await PatchAsync("api/bulk", content); + + // assert + Assert.NotNull(result.response); + Assert.NotNull(result.data); + Assert.Equal(HttpStatusCode.OK, result.response.StatusCode); + Assert.Equal(1, result.data.Operations.Count); + Assert.Equal(author.Id.ToString(), result.data.Operations.Single().DataObject.Id); + } + + [Fact] + public async Task Get_Author_By_Id_Returns_404_If_NotFound() + { + // arrange + var authorId = _faker.Random.Int(max: 0).ToString(); + + var content = new + { + operations = new[] { + new Dictionary { + { "op", "get"}, + { "ref", new { type = "authors", id = authorId } } + } + } + }; + + // act + var (response, data) = await PatchAsync("api/bulk", content); + + // assert + Assert.NotNull(response); + Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); + Assert.NotNull(data); + Assert.Equal(1, data.Errors.Count); + Assert.True(data.Errors[0].Detail.Contains("authors"), "The error detail should contain the name of the entity that could not be found."); + Assert.True(data.Errors[0].Detail.Contains(authorId), "The error detail should contain the entity id that could not be found"); + Assert.True(data.Errors[0].Title.Contains("operation[0]"), "The error title should contain the operation identifier that failed"); + } + } +} diff --git a/test/OperationsExampleTests/Get/GetRelationshipTests.cs b/test/OperationsExampleTests/Get/GetRelationshipTests.cs new file mode 100644 index 0000000000..03f276da17 --- /dev/null +++ b/test/OperationsExampleTests/Get/GetRelationshipTests.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using Bogus; +using JsonApiDotNetCore.Models.Operations; +using JsonApiDotNetCoreExample.Data; +using OperationsExampleTests.Factories; +using Xunit; + +namespace OperationsExampleTests +{ + public class GetRelationshipTests : Fixture, IDisposable + { + private readonly Faker _faker = new Faker(); + + [Fact] + public async Task Can_Get_Article_Author() + { + // arrange + var context = GetService(); + var author = AuthorFactory.Get(); + var article = ArticleFactory.Get(); + article.Author = author; + context.Articles.Add(article); + context.SaveChanges(); + + var content = new + { + operations = new[] { + new Dictionary { + { "op", "get"}, + { "ref", new { type = "articles", id = article.StringId, relationship = nameof(article.Author) } } + } + } + }; + + // act + var (response, data) = await PatchAsync("api/bulk", content); + + // assert + Assert.NotNull(response); + Assert.NotNull(data); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal(1, data.Operations.Count); + var resourceObject = data.Operations.Single().DataObject; + Assert.Equal(author.Id.ToString(), resourceObject.Id); + Assert.Equal("authors", resourceObject.Type); + } + } +} diff --git a/test/OperationsExampleTests/Get/GetTests.cs b/test/OperationsExampleTests/Get/GetTests.cs index 17c868cebd..bf1c15e3a4 100644 --- a/test/OperationsExampleTests/Get/GetTests.cs +++ b/test/OperationsExampleTests/Get/GetTests.cs @@ -1,35 +1,30 @@ +using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Threading.Tasks; using Bogus; using JsonApiDotNetCore.Models.Operations; -using OperationsExample.Data; +using JsonApiDotNetCoreExample.Data; using OperationsExampleTests.Factories; using Xunit; namespace OperationsExampleTests { - [Collection("WebHostCollection")] - public class GetTests + public class GetByIdTests : Fixture, IDisposable { - private readonly Fixture _fixture; - private readonly Faker _faker = new Faker(); - - public GetTests(Fixture fixture) - { - _fixture = fixture; - } + private readonly Faker _faker = new Faker(); [Fact] - public async Task Can_Get_Articles() + public async Task Can_Get_Authors() { // arrange var expectedCount = _faker.Random.Int(1, 10); - var context = _fixture.GetService(); + var context = GetService(); context.Articles.RemoveRange(context.Articles); - var articles = ArticleFactory.Get(expectedCount); - context.AddRange(articles); + context.Authors.RemoveRange(context.Authors); + var authors = AuthorFactory.Get(expectedCount); + context.AddRange(authors); context.SaveChanges(); var content = new @@ -37,13 +32,13 @@ public async Task Can_Get_Articles() operations = new[] { new Dictionary { { "op", "get"}, - { "ref", new { type = "articles" } } + { "ref", new { type = "authors" } } } } }; // act - var result = await _fixture.PatchAsync("api/bulk", content); + var result = await PatchAsync("api/bulk", content); // assert Assert.NotNull(result.response); @@ -51,36 +46,6 @@ public async Task Can_Get_Articles() Assert.Equal(HttpStatusCode.OK, result.response.StatusCode); Assert.Equal(1, result.data.Operations.Count); Assert.Equal(expectedCount, result.data.Operations.Single().DataList.Count); - } - - [Fact] - public async Task Can_Get_Article_By_Id() - { - // arrange - var context = _fixture.GetService(); - var article = ArticleFactory.Get(); - context.Articles.Add(article); - context.SaveChanges(); - - var content = new - { - operations = new[] { - new Dictionary { - { "op", "get"}, - { "ref", new { type = "articles", id = article.StringId } } - } - } - }; - - // act - var result = await _fixture.PatchAsync("api/bulk", content); - - // assert - Assert.NotNull(result.response); - Assert.NotNull(result.data); - Assert.Equal(HttpStatusCode.OK, result.response.StatusCode); - Assert.Equal(1, result.data.Operations.Count); - Assert.Equal(article.Id.ToString(), result.data.Operations.Single().DataObject.Id); - } + } } } diff --git a/test/OperationsExampleTests/OperationsExampleTests.csproj b/test/OperationsExampleTests/OperationsExampleTests.csproj index a7727475bd..13f68faf5a 100644 --- a/test/OperationsExampleTests/OperationsExampleTests.csproj +++ b/test/OperationsExampleTests/OperationsExampleTests.csproj @@ -14,6 +14,7 @@ + diff --git a/test/OperationsExampleTests/Remove/RemoveTests.cs b/test/OperationsExampleTests/Remove/RemoveTests.cs index f5229ebbd5..b5e0cffaf3 100644 --- a/test/OperationsExampleTests/Remove/RemoveTests.cs +++ b/test/OperationsExampleTests/Remove/RemoveTests.cs @@ -4,30 +4,23 @@ using System.Threading.Tasks; using Bogus; using JsonApiDotNetCore.Models.Operations; -using OperationsExample.Data; +using JsonApiDotNetCoreExample.Data; using OperationsExampleTests.Factories; using Xunit; namespace OperationsExampleTests { - [Collection("WebHostCollection")] - public class RemoveTests - { - private readonly Fixture _fixture; + public class RemoveTests : Fixture + { private readonly Faker _faker = new Faker(); - public RemoveTests(Fixture fixture) - { - _fixture = fixture; - } - [Fact] - public async Task Can_Remove_Article() + public async Task Can_Remove_Author() { // arrange - var context = _fixture.GetService(); - var article = ArticleFactory.Get(); - context.Articles.Add(article); + var context = GetService(); + var author = AuthorFactory.Get(); + context.Authors.Add(author); context.SaveChanges(); var content = new @@ -35,32 +28,32 @@ public async Task Can_Remove_Article() operations = new[] { new Dictionary { { "op", "remove"}, - { "ref", new { type = "articles", id = article.StringId } } + { "ref", new { type = "authors", id = author.StringId } } } } }; // act - var result = await _fixture.PatchAsync("api/bulk", content); + var (response, data) = await PatchAsync("api/bulk", content); // assert - Assert.NotNull(result.response); - Assert.NotNull(result.data); - Assert.Equal(HttpStatusCode.OK, result.response.StatusCode); - Assert.Equal(1, result.data.Operations.Count); - Assert.Null(context.Articles.SingleOrDefault(a => a.Id == article.Id)); + Assert.NotNull(response); + Assert.NotNull(data); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Empty(data.Operations); + Assert.Null(context.Authors.SingleOrDefault(a => a.Id == author.Id)); } [Fact] - public async Task Can_Remove_Articles() + public async Task Can_Remove_Authors() { // arrange var count = _faker.Random.Int(1, 10); - var context = _fixture.GetService(); + var context = GetService(); - var articles = ArticleFactory.Get(count); + var authors = AuthorFactory.Get(count); - context.Articles.AddRange(articles); + context.Authors.AddRange(authors); context.SaveChanges(); var content = new @@ -72,21 +65,21 @@ public async Task Can_Remove_Articles() content.operations.Add( new Dictionary { { "op", "remove"}, - { "ref", new { type = "articles", id = articles[i].StringId } } + { "ref", new { type = "authors", id = authors[i].StringId } } } ); // act - var result = await _fixture.PatchAsync("api/bulk", content); + var (response, data) = await PatchAsync("api/bulk", content); // assert - Assert.NotNull(result.response); - Assert.NotNull(result.data); - Assert.Equal(HttpStatusCode.OK, result.response.StatusCode); - Assert.Equal(count, result.data.Operations.Count); + Assert.NotNull(response); + Assert.NotNull(data); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Empty(data.Operations); for (int i = 0; i < count; i++) - Assert.Null(context.Articles.SingleOrDefault(a => a.Id == articles[i].Id)); + Assert.Null(context.Authors.SingleOrDefault(a => a.Id == authors[i].Id)); } } } diff --git a/test/OperationsExampleTests/Replace/ReplaceTests.cs b/test/OperationsExampleTests/Replace/ReplaceTests.cs deleted file mode 100644 index 521dcd979b..0000000000 --- a/test/OperationsExampleTests/Replace/ReplaceTests.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using Bogus; -using JsonApiDotNetCore.Models.Operations; -using OperationsExample.Data; -using OperationsExampleTests.Factories; -using Xunit; - -namespace OperationsExampleTests -{ - [Collection("WebHostCollection")] - public class ReplaceTests - { - private readonly Fixture _fixture; - private readonly Faker _faker = new Faker(); - - public ReplaceTests(Fixture fixture) - { - _fixture = fixture; - } - - [Fact] - public async Task Can_Update_Article() - { - // arrange - var context = _fixture.GetService(); - var article = ArticleFactory.Get(); - var updates = ArticleFactory.Get(); - context.Articles.Add(article); - context.SaveChanges(); - - var content = new - { - operations = new[] { - new { - op = "replace", - data = new { - type = "articles", - id = article.Id, - attributes = new { - name = updates.Name - } - } - }, - } - }; - - // act - var result = await _fixture.PatchAsync("api/bulk", content); - - // assert - Assert.NotNull(result.response); - Assert.NotNull(result.data); - Assert.Equal(HttpStatusCode.OK, result.response.StatusCode); - Assert.Equal(1, result.data.Operations.Count); - - var attrs = result.data.Operations.Single().DataObject.Attributes; - Assert.Equal(updates.Name, attrs["name"]); - } - - [Fact] - public async Task Can_Update_Articles() - { - // arrange - var count = _faker.Random.Int(1, 10); - var context = _fixture.GetService(); - - var articles = ArticleFactory.Get(count); - var updates = ArticleFactory.Get(count); - - context.Articles.AddRange(articles); - context.SaveChanges(); - - var content = new - { - operations = new List() - }; - - for (int i = 0; i < count; i++) - content.operations.Add(new - { - op = "replace", - data = new - { - type = "articles", - id = articles[i].Id, - attributes = new - { - name = updates[i].Name - } - } - }); - - // act - var result = await _fixture.PatchAsync("api/bulk", content); - - // assert - Assert.NotNull(result.response); - Assert.NotNull(result.data); - Assert.Equal(HttpStatusCode.OK, result.response.StatusCode); - Assert.Equal(count, result.data.Operations.Count); - - for (int i = 0; i < count; i++) - { - var attrs = result.data.Operations[i].DataObject.Attributes; - Assert.Equal(updates[i].Name, attrs["name"]); - } - } - } -} diff --git a/test/OperationsExampleTests/TestStartup.cs b/test/OperationsExampleTests/TestStartup.cs new file mode 100644 index 0000000000..449c193177 --- /dev/null +++ b/test/OperationsExampleTests/TestStartup.cs @@ -0,0 +1,25 @@ +using JsonApiDotNetCore.Data; +using JsonApiDotNetCore.Services; +using JsonApiDotNetCoreExample.Data; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using OperationsExample; +using System; +using UnitTests; + +namespace OperationsExampleTests +{ + public class TestStartup : Startup + { + public TestStartup(IHostingEnvironment env) : base(env) + { } + + public override IServiceProvider ConfigureServices(IServiceCollection services) + { + base.ConfigureServices(services); + services.AddScoped(); + services.AddSingleton>(); + return services.BuildServiceProvider(); + } + } +} diff --git a/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs b/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs new file mode 100644 index 0000000000..05dea7f29d --- /dev/null +++ b/test/OperationsExampleTests/Transactions/TransactionFailureTests.cs @@ -0,0 +1,80 @@ +using System; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using Bogus; +using JsonApiDotNetCore.Internal; +using JsonApiDotNetCoreExample.Data; +using Microsoft.EntityFrameworkCore; +using OperationsExampleTests.Factories; +using Xunit; + +namespace OperationsExampleTests +{ + public class TransactionFailureTests : Fixture + { + private readonly Faker _faker = new Faker(); + + [Fact] + public async Task Cannot_Create_Author_If_Article_Creation_Fails() + { + // arrange + var context = GetService(); + var author = AuthorFactory.Get(); + var article = ArticleFactory.Get(); + + // do this so that the name is random enough for db validations + author.Name = Guid.NewGuid().ToString("N"); + article.Name = Guid.NewGuid().ToString("N"); + + var content = new + { + operations = new object[] { + new { + op = "add", + data = new { + type = "authors", + attributes = new { + name = author.Name + }, + } + }, + new { + op = "add", + data = new { + type = "articles", + attributes = new { + name = article.Name + }, + // by not including the author, the article creation will fail + // relationships = new { + // author = new { + // data = new { + // type = "authors", + // lid = authorLocalId + // } + // } + // } + } + } + } + }; + + // act + var (response, data) = await PatchAsync("api/bulk", content); + + // assert + Assert.NotNull(response); + // for now, it is up to application implementations to perform validation and + // provide the proper HTTP response code + Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); + Assert.Equal(1, data.Errors.Count); + Assert.Contains("operation[1] (add)", data.Errors[0].Title); + + var dbAuthors = await context.Authors.Where(a => a.Name == author.Name).ToListAsync(); + var dbArticles = await context.Articles.Where(a => a.Name == article.Name).ToListAsync(); + Assert.Empty(dbAuthors); + Assert.Empty(dbArticles); + } + } +} diff --git a/test/OperationsExampleTests/Update/UpdateTests.cs b/test/OperationsExampleTests/Update/UpdateTests.cs new file mode 100644 index 0000000000..c5d0f20900 --- /dev/null +++ b/test/OperationsExampleTests/Update/UpdateTests.cs @@ -0,0 +1,112 @@ +using Bogus; +using JsonApiDotNetCore.Models.Operations; +using JsonApiDotNetCoreExample.Data; +using OperationsExampleTests.Factories; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using Xunit; + +namespace OperationsExampleTests.Update +{ + public class UpdateTests : Fixture + { + private readonly Faker _faker = new Faker(); + + [Fact] + public async Task Can_Update_Author() + { + // arrange + var context = GetService(); + var author = AuthorFactory.Get(); + var updates = AuthorFactory.Get(); + context.Authors.Add(author); + context.SaveChanges(); + + var content = new + { + operations = new[] { + new Dictionary { + { "op", "update" }, + { "ref", new { + type = "authors", + id = author.Id, + } }, + { "data", new { + type = "authors", + id = author.Id, + attributes = new + { + name = updates.Name + } + } }, + } + } + }; + + // act + var (response, data) = await PatchAsync("api/bulk", content); + + // assert + Assert.NotNull(response); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.NotNull(data); + Assert.Equal(1, data.Operations.Count); + + var attrs = data.Operations.Single().DataObject.Attributes; + Assert.Equal(updates.Name, attrs["name"]); + } + + [Fact] + public async Task Can_Update_Authors() + { + // arrange + var count = _faker.Random.Int(1, 10); + var context = GetService(); + + var authors = AuthorFactory.Get(count); + var updates = AuthorFactory.Get(count); + + context.Authors.AddRange(authors); + context.SaveChanges(); + + var content = new + { + operations = new List() + }; + + for (int i = 0; i < count; i++) + content.operations.Add(new Dictionary { + { "op", "update" }, + { "ref", new { + type = "authors", + id = authors[i].Id, + } }, + { "data", new { + type = "authors", + id = authors[i].Id, + attributes = new + { + name = updates[i].Name + } + } }, + }); + + // act + var (response, data) = await PatchAsync("api/bulk", content); + + // assert + Assert.NotNull(response); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.NotNull(data); + Assert.Equal(count, data.Operations.Count); + + for (int i = 0; i < count; i++) + { + var attrs = data.Operations[i].DataObject.Attributes; + Assert.Equal(updates[i].Name, attrs["name"]); + } + } + } +} diff --git a/test/OperationsExampleTests/appsettings.json b/test/OperationsExampleTests/appsettings.json index c1061281cc..0d77cd40f2 100644 --- a/test/OperationsExampleTests/appsettings.json +++ b/test/OperationsExampleTests/appsettings.json @@ -1,13 +1,13 @@ -{ - "Data": { - "DefaultConnection": "Host=localhost;Port=5432;Database=OperationsExample;User ID=postgres;Password=password" - }, - "Logging": { - "IncludeScopes": false, - "LogLevel": { - "Default": "Trace", - "System": "Trace", - "Microsoft": "Trace" +{ + "Data": { + "DefaultConnection": "Host=localhost;Port=5432;Database=JsonApiDotNetCoreExample;User ID=postgres;Password=postgres" + }, + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Trace", + "System": "Trace", + "Microsoft": "Trace" + } } - } } diff --git a/test/UnitTests/Models/Pointers/OperationsPointerTests.cs b/test/UnitTests/Models/Pointers/OperationsPointerTests.cs deleted file mode 100644 index 9aafc284dc..0000000000 --- a/test/UnitTests/Models/Pointers/OperationsPointerTests.cs +++ /dev/null @@ -1,164 +0,0 @@ -using System.Collections.Generic; -using JsonApiDotNetCore.Models.Operations; -using JsonApiDotNetCore.Models.Pointers; -using Newtonsoft.Json; -using Xunit; - -namespace UnitTests.Models.Pointers -{ - public class OperationsPointerTests - { - [Fact] - public void GetValue_Can_Get_Value_From_Ref_Id() - { - // arrange - var json = @"[ - { - ""op"": ""add"", - ""ref"": { - ""type"": ""articles"", - ""id"": ""1"" - } - }]"; - var operations = JsonConvert.DeserializeObject>(json); - var pointerJson = @"{ ""pointer"": ""/operations/0/ref/id"" }"; - var pointer = JsonConvert.DeserializeObject(pointerJson); - var value = pointer.GetValue(operations); - Assert.Equal("1", value.ToString()); - } - - [Fact] - public void GetValue_Can_Get_Value_From_Data_Id() - { - // arrange - var json = @"[ - { - ""op"": ""add"", - ""data"": { - ""id"": ""1"", - ""type"": ""authors"", - ""attributes"": { - ""name"": ""dgeb"" - } - } - }]"; - var operations = JsonConvert.DeserializeObject>(json); - var pointerJson = @"{ ""pointer"": ""/operations/0/data/id"" }"; - var pointer = JsonConvert.DeserializeObject(pointerJson); - var value = pointer.GetValue(operations); - Assert.Equal("1", value.ToString()); - } - - [Fact] - public void GetValue_Can_Get_Value_From_Data_Type() - { - // arrange - var json = @"[ - { - ""op"": ""add"", - ""data"": { - ""id"": ""1"", - ""type"": ""authors"", - ""attributes"": { - ""name"": ""dgeb"" - } - } - }]"; - var operations = JsonConvert.DeserializeObject>(json); - var pointerJson = @"{ ""pointer"": ""/operations/0/data/type"" }"; - var pointer = JsonConvert.DeserializeObject(pointerJson); - var value = pointer.GetValue(operations); - Assert.Equal("authors", value.ToString()); - } - - [Fact] - public void GetValue_Can_Get_Value_From_ListData_Id() - { - // arrange - var json = @"[ - { - ""op"": ""get"", - ""data"": [{ - ""id"": ""1"", - ""type"": ""authors"", - ""attributes"": { - ""name"": ""dgeb"" - } - }, { - ""id"": ""2"", - ""type"": ""authors"", - ""attributes"": { - ""name"": ""jaredcnance"" - } - }] - }]"; - var operations = JsonConvert.DeserializeObject>(json); - var pointerJson = @"{ ""pointer"": ""/operations/0/data/1/id"" }"; - var pointer = JsonConvert.DeserializeObject(pointerJson); - var value = pointer.GetValue(operations); - Assert.Equal("2", value.ToString()); - } - - [Fact] - public void GetValue_Can_Get_Value_From_Second_Operations_Data_Id() - { - // arrange - var json = @"[ - { - ""op"": ""get"", - ""data"": { - ""id"": ""1"", - ""type"": ""authors"", - ""attributes"": { - ""name"": ""dgeb"" - } - } - },{ - ""op"": ""get"", - ""data"": { - ""id"": ""2"", - ""type"": ""authors"", - ""attributes"": { - ""name"": ""jaredcnance"" - } - } - }]"; - var operations = JsonConvert.DeserializeObject>(json); - var pointerJson = @"{ ""pointer"": ""/operations/1/data/id"" }"; - var pointer = JsonConvert.DeserializeObject(pointerJson); - var value = pointer.GetValue(operations); - Assert.Equal("2", value.ToString()); - } - - [Fact] - public void GetValue_Can_Get_Value_From_Second_Operations_Data_Type() - { - // arrange - var json = @"[ - { - ""op"": ""get"", - ""data"": { - ""id"": ""1"", - ""type"": ""authors"", - ""attributes"": { - ""name"": ""dgeb"" - } - } - },{ - ""op"": ""get"", - ""data"": { - ""id"": ""1"", - ""type"": ""articles"", - ""attributes"": { - ""name"": ""JSON API paints my bikeshed!"" - } - } - }]"; - var operations = JsonConvert.DeserializeObject>(json); - var pointerJson = @"{ ""pointer"": ""/operations/1/data/type"" }"; - var pointer = JsonConvert.DeserializeObject(pointerJson); - var value = pointer.GetValue(operations); - Assert.Equal("articles", value.ToString()); - } - } -} \ No newline at end of file diff --git a/test/UnitTests/Services/Operations/OperationsProcessorTests.cs b/test/UnitTests/Services/Operations/OperationsProcessorTests.cs index 0a7fd501ae..9635c6f6f3 100644 --- a/test/UnitTests/Services/Operations/OperationsProcessorTests.cs +++ b/test/UnitTests/Services/Operations/OperationsProcessorTests.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using JsonApiDotNetCore.Data; @@ -121,7 +121,7 @@ public async Task ProcessAsync_Performs_LocalId_ReplacementAsync_In_References() } } }, { - ""op"": ""replace"", + ""op"": ""update"", ""ref"": { ""type"": ""authors"", ""lid"": ""a"" @@ -169,7 +169,7 @@ public async Task ProcessAsync_Performs_LocalId_ReplacementAsync_In_References() var updateOpProcessorMock = new Mock(); updateOpProcessorMock.Setup(m => m.ProcessAsync(It.Is(op => op.DataObject.Type.ToString() == "authors"))) .ReturnsAsync((Operation)null); - _resolverMock.Setup(m => m.LocateReplaceService(It.IsAny())) + _resolverMock.Setup(m => m.LocateUpdateService(It.IsAny())) .Returns(updateOpProcessorMock.Object); _dbContextResolverMock.Setup(m => m.GetContext()).Returns(_dbContextMock.Object); diff --git a/test/UnitTests/TestScopedServiceProvider.cs b/test/UnitTests/TestScopedServiceProvider.cs new file mode 100644 index 0000000000..af68e340b9 --- /dev/null +++ b/test/UnitTests/TestScopedServiceProvider.cs @@ -0,0 +1,28 @@ +using JsonApiDotNetCore.Services; +using Microsoft.AspNetCore.Http; +using Moq; +using System; + +namespace UnitTests +{ + public class TestScopedServiceProvider : IScopedServiceProvider + { + private readonly IServiceProvider _serviceProvider; + private Mock _httpContextAccessorMock = new Mock(); + + public TestScopedServiceProvider(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public object GetService(Type serviceType) + { + if (serviceType == typeof(IHttpContextAccessor)) + { + return _httpContextAccessorMock.Object; + } + + return _serviceProvider.GetService(serviceType); + } + } +}