diff --git a/JsonApiDotnetCore.sln b/JsonApiDotnetCore.sln index 769230390d..942396a4c1 100644 --- a/JsonApiDotnetCore.sln +++ b/JsonApiDotnetCore.sln @@ -43,6 +43,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GettingStarted", "src\Examp EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IntegrationTests", "test\IntegrationTests\IntegrationTests.csproj", "{CEB08B86-6BF1-4227-B20F-45AE9C1CC6D9}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "src\Examples\IncludeBug\Test.csproj", "{63A979EE-488C-44D5-BC93-163E02B65F75}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -185,6 +187,18 @@ Global {CEB08B86-6BF1-4227-B20F-45AE9C1CC6D9}.Release|x64.Build.0 = Release|Any CPU {CEB08B86-6BF1-4227-B20F-45AE9C1CC6D9}.Release|x86.ActiveCfg = Release|Any CPU {CEB08B86-6BF1-4227-B20F-45AE9C1CC6D9}.Release|x86.Build.0 = Release|Any CPU + {63A979EE-488C-44D5-BC93-163E02B65F75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {63A979EE-488C-44D5-BC93-163E02B65F75}.Debug|Any CPU.Build.0 = Debug|Any CPU + {63A979EE-488C-44D5-BC93-163E02B65F75}.Debug|x64.ActiveCfg = Debug|Any CPU + {63A979EE-488C-44D5-BC93-163E02B65F75}.Debug|x64.Build.0 = Debug|Any CPU + {63A979EE-488C-44D5-BC93-163E02B65F75}.Debug|x86.ActiveCfg = Debug|Any CPU + {63A979EE-488C-44D5-BC93-163E02B65F75}.Debug|x86.Build.0 = Debug|Any CPU + {63A979EE-488C-44D5-BC93-163E02B65F75}.Release|Any CPU.ActiveCfg = Release|Any CPU + {63A979EE-488C-44D5-BC93-163E02B65F75}.Release|Any CPU.Build.0 = Release|Any CPU + {63A979EE-488C-44D5-BC93-163E02B65F75}.Release|x64.ActiveCfg = Release|Any CPU + {63A979EE-488C-44D5-BC93-163E02B65F75}.Release|x64.Build.0 = Release|Any CPU + {63A979EE-488C-44D5-BC93-163E02B65F75}.Release|x86.ActiveCfg = Release|Any CPU + {63A979EE-488C-44D5-BC93-163E02B65F75}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -201,6 +215,7 @@ Global {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B} = {026FBC6C-AF76-4568-9B87-EC73457899FD} {21D27239-138D-4604-8E49-DCBE41BCE4C8} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} {CEB08B86-6BF1-4227-B20F-45AE9C1CC6D9} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} + {63A979EE-488C-44D5-BC93-163E02B65F75} = {026FBC6C-AF76-4568-9B87-EC73457899FD} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {A2421882-8F0A-4905-928F-B550B192F9A4} diff --git a/src/Examples/IncludeBug/AppDbContext.cs b/src/Examples/IncludeBug/AppDbContext.cs new file mode 100644 index 0000000000..1191f42328 --- /dev/null +++ b/src/Examples/IncludeBug/AppDbContext.cs @@ -0,0 +1,21 @@ +using Microsoft.EntityFrameworkCore; + +namespace Test +{ + public class AppDbContext : DbContext + { + public AppDbContext(DbContextOptions options) + : base(options) { } + + public DbSet People { get; set; } + public DbSet Books { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.Entity() + .HasKey(bookPerson => new { bookPerson.BookId, bookPerson.PersonId }); + } + } +} diff --git a/src/Examples/IncludeBug/Book.cs b/src/Examples/IncludeBug/Book.cs new file mode 100644 index 0000000000..72c1367c80 --- /dev/null +++ b/src/Examples/IncludeBug/Book.cs @@ -0,0 +1,18 @@ +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Test +{ + public class Book : Identifiable + { + [Attr] + public string Title { get; set; } + + [NotMapped] + [HasManyThrough(nameof(BookPeople))] + public List People { get; set; } + public virtual List BookPeople { get; set; } + } +} diff --git a/src/Examples/IncludeBug/BookPerson.cs b/src/Examples/IncludeBug/BookPerson.cs new file mode 100644 index 0000000000..1b60a186bb --- /dev/null +++ b/src/Examples/IncludeBug/BookPerson.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace Test +{ + public class BookPerson + { + public int BookId { get; set; } + [ForeignKey("BookId")] + public virtual Book Book { get; set; } + + public int PersonId { get; set; } + [ForeignKey("PersonId")] + public virtual Person Person { get; set; } + } +} diff --git a/src/Examples/IncludeBug/BooksController.cs b/src/Examples/IncludeBug/BooksController.cs new file mode 100644 index 0000000000..ea1f8318f1 --- /dev/null +++ b/src/Examples/IncludeBug/BooksController.cs @@ -0,0 +1,17 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Services; +using Microsoft.Extensions.Logging; + +namespace Test +{ + public class BooksController : JsonApiController + { + public BooksController( + IJsonApiOptions options, + ILoggerFactory loggerFactory, + IResourceService resourceService) + : base(options, loggerFactory, resourceService) + { } + } +} diff --git a/src/Examples/IncludeBug/PeopleController.cs b/src/Examples/IncludeBug/PeopleController.cs new file mode 100644 index 0000000000..29b888c5cd --- /dev/null +++ b/src/Examples/IncludeBug/PeopleController.cs @@ -0,0 +1,17 @@ +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCore.Controllers; +using JsonApiDotNetCore.Services; +using Microsoft.Extensions.Logging; + +namespace Test +{ + public class PeopleController : JsonApiController + { + public PeopleController( + IJsonApiOptions options, + ILoggerFactory loggerFactory, + IResourceService resourceService) + : base(options, loggerFactory, resourceService) + { } + } +} diff --git a/src/Examples/IncludeBug/Person.cs b/src/Examples/IncludeBug/Person.cs new file mode 100644 index 0000000000..30c830e42f --- /dev/null +++ b/src/Examples/IncludeBug/Person.cs @@ -0,0 +1,18 @@ +using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Test +{ + public class Person : Identifiable + { + [Attr] + public string Name { get; set; } + + [NotMapped] + [HasManyThrough(nameof(BookPeople))] + public List Books { get; set; } + public virtual List BookPeople { get; set; } + } +} diff --git a/src/Examples/IncludeBug/Program.cs b/src/Examples/IncludeBug/Program.cs new file mode 100644 index 0000000000..537248d206 --- /dev/null +++ b/src/Examples/IncludeBug/Program.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace Test +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + } +} diff --git a/src/Examples/IncludeBug/Properties/launchSettings.json b/src/Examples/IncludeBug/Properties/launchSettings.json new file mode 100644 index 0000000000..27ecedfd58 --- /dev/null +++ b/src/Examples/IncludeBug/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:54652/", + "sslPort": 44385 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Test": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:5001;http://localhost:5000" + } + } +} \ No newline at end of file diff --git a/src/Examples/IncludeBug/Startup.cs b/src/Examples/IncludeBug/Startup.cs new file mode 100644 index 0000000000..eb3b9f483c --- /dev/null +++ b/src/Examples/IncludeBug/Startup.cs @@ -0,0 +1,74 @@ +using JsonApiDotNetCore.Configuration; +using Microsoft.AspNetCore.Builder; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using System.Collections.Generic; +using System.Linq; + +namespace Test +{ + public class Startup + { + public void ConfigureServices(IServiceCollection services) + { + // Add the Entity Framework Core DbContext like you normally would + services.AddDbContext(options => + { + // Use whatever provider you want, this is just an example + options.UseSqlServer("Data Source=.\\SQLEXPRESS;Initial Catalog=testDb;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite"); + }); + + // Add JsonApiDotNetCore + services.AddJsonApi(); + } + + public void Configure(IApplicationBuilder app, AppDbContext appDbContext) + { + appDbContext.Database.EnsureCreated(); + if (!appDbContext.People.Any()) + { + var person1 = new Person + { + Name = "John Doe" + }; + var person2 = new Person + { + Name = "Alan Thrall" + }; + var book1 = new Book + { + Title = "Explode" + }; + var book2 = new Book + { + Title = "Blastoise" + }; + var bookPerson1 = new BookPerson + { + Book = book1, + Person = person1 + }; + var bookPerson2 = new BookPerson + { + Book = book2, + Person = person2 + }; + var bookPerson3 = new BookPerson + { + Book = book1, + Person = person2 + }; + person1.BookPeople = new List { bookPerson1 }; + person2.BookPeople = new List { bookPerson2, bookPerson3 }; + appDbContext.People.Add(person1); + appDbContext.People.Add(person2); + appDbContext.Books.Add(book1); + appDbContext.Books.Add(book2); + appDbContext.SaveChanges(); + } + app.UseRouting(); + app.UseJsonApi(); + app.UseEndpoints(endpoints => endpoints.MapControllers()); + } + } +} diff --git a/src/Examples/IncludeBug/Test.csproj b/src/Examples/IncludeBug/Test.csproj new file mode 100644 index 0000000000..fbed816f67 --- /dev/null +++ b/src/Examples/IncludeBug/Test.csproj @@ -0,0 +1,15 @@ + + + + netcoreapp3.1 + + + + + + + + + + + diff --git a/src/Examples/IncludeBug/appsettings.Development.json b/src/Examples/IncludeBug/appsettings.Development.json new file mode 100644 index 0000000000..8983e0fc1c --- /dev/null +++ b/src/Examples/IncludeBug/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/src/Examples/IncludeBug/appsettings.json b/src/Examples/IncludeBug/appsettings.json new file mode 100644 index 0000000000..d9d9a9bff6 --- /dev/null +++ b/src/Examples/IncludeBug/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +}