diff --git a/src/Examples/JsonApiDotNetCoreExample/Controllers/UsersController.cs b/src/Examples/JsonApiDotNetCoreExample/Controllers/UsersController.cs index cc47e88d84..de1996d5e5 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Controllers/UsersController.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Controllers/UsersController.cs @@ -15,4 +15,14 @@ public UsersController( : base(jsonApiOptions, resourceService, loggerFactory) { } } + + public class SuperUsersController : JsonApiController + { + public SuperUsersController( + IJsonApiOptions jsonApiOptions, + IResourceService resourceService, + ILoggerFactory loggerFactory) + : base(jsonApiOptions, resourceService, loggerFactory) + { } + } } diff --git a/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs b/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs index 7faa22bd55..9411f48a4f 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Data/AppDbContext.cs @@ -14,6 +14,7 @@ public class AppDbContext : DbContext public DbSet AuthorDifferentDbContextName { get; set; } public DbSet NonJsonApiResources { get; set; } public DbSet Users { get; set; } + public DbSet SuperUsers { get; set; } public DbSet PersonRoles { get; set; } public DbSet ArticleTags { get; set; } public DbSet IdentifiableArticleTags { get; set; } @@ -23,6 +24,8 @@ public AppDbContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { + modelBuilder.Entity().HasBaseType(); + modelBuilder.Entity() .Property(t => t.CreatedDate).HasDefaultValueSql("CURRENT_TIMESTAMP").IsRequired(); diff --git a/src/Examples/JsonApiDotNetCoreExample/Models/User.cs b/src/Examples/JsonApiDotNetCoreExample/Models/User.cs index f966cb84cd..d0e38b93e7 100644 --- a/src/Examples/JsonApiDotNetCoreExample/Models/User.cs +++ b/src/Examples/JsonApiDotNetCoreExample/Models/User.cs @@ -8,4 +8,9 @@ public class User : Identifiable [Attr] public string Username { get; set; } [Attr] public string Password { get; set; } } + + public class SuperUser : User + { + [Attr] public int SecurityLevel { get; set; } + } } diff --git a/src/JsonApiDotNetCore/Internal/DefaultRoutingConvention.cs b/src/JsonApiDotNetCore/Internal/DefaultRoutingConvention.cs index eb68142e31..f694d95010 100644 --- a/src/JsonApiDotNetCore/Internal/DefaultRoutingConvention.cs +++ b/src/JsonApiDotNetCore/Internal/DefaultRoutingConvention.cs @@ -58,6 +58,7 @@ public void Apply(ApplicationModel application) foreach (var controller in application.Controllers) { var resourceType = GetResourceTypeFromController(controller.ControllerType); + if (resourceType != null) _registeredResources.Add(controller.ControllerName, resourceType); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs index 32ac423eee..982dfdd100 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/CreatingDataTests.cs @@ -36,6 +36,23 @@ public CreatingDataTests(TestFixture fixture) : base(fixture) } + [Fact] + public async Task CreateResource_ModelWithEntityFrameworkInHeritance_IsCreated() + { + // Arrange + var dbContext = PrepareTest(); + var serializer = GetSerializer(e => new { e.SecurityLevel, e.Username, e.Password }); + var superUser = new SuperUser { SecurityLevel = 1337, Username = "Super", Password = "User" }; + + // Act + var (body, response) = await Post("/api/v1/super-users", serializer.Serialize(superUser)); + + // Assert + AssertEqualStatusCode(HttpStatusCode.Created, response); + var createdSuperUser = _deserializer.DeserializeSingle(body).Data; + var created = dbContext.SuperUsers.Where(e => e.Id.Equals(createdSuperUser.Id)).First(); + } + [Fact] public async Task CreateResource_GuidResource_IsCreated() { diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/EndToEndTest.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/EndToEndTest.cs index e287e1ae20..0f0d045bdc 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/EndToEndTest.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/EndToEndTest.cs @@ -61,6 +61,11 @@ public AppDbContext GetDbContext() return SendRequest("POST", route, content); } + public Task<(string, HttpResponseMessage)> Patch(string route, string content) + { + return SendRequest("PATCH", route, content); + } + public IRequestSerializer GetSerializer(Expression> attributes = null, Expression> relationships = null) where TResource : class, IIdentifiable { return _fixture.GetSerializer(attributes, relationships); diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingDataTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingDataTests.cs index 9860f4e2cf..9d58f4d75c 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingDataTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/UpdatingDataTests.cs @@ -20,15 +20,15 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec { [Collection("WebHostCollection")] - public class UpdatingDataTests + public class UpdatingDataTests : EndToEndTest { private TestFixture _fixture; private AppDbContext _context; private Faker _todoItemFaker; private Faker _personFaker; - public UpdatingDataTests(TestFixture fixture) - { + public UpdatingDataTests(TestFixture fixture) : base(fixture) + { _fixture = fixture; _context = fixture.GetService(); @@ -41,6 +41,25 @@ public UpdatingDataTests(TestFixture fixture) .RuleFor(p => p.LastName, f => f.Name.LastName()); } + [Fact] + public async Task PatchResource_ModelWithEntityFrameworkInHeritance_IsPatched() + { + // Arrange + var dbContext = PrepareTest(); + var serializer = GetSerializer(e => new { e.SecurityLevel }); + var superUser = new SuperUser { SecurityLevel = 1337, Username = "Super", Password = "User" }; + dbContext.SuperUsers.Add(superUser); + dbContext.SaveChanges(); + var su = new SuperUser { Id = superUser.Id, SecurityLevel = 2674 }; + + // Act + var (body, response) = await Patch($"/api/v1/super-users/{su.Id}", serializer.Serialize(su)); + + // Assert + AssertEqualStatusCode(HttpStatusCode.OK, response); + var updated = _deserializer.DeserializeSingle(body).Data; + Assert.Equal(2674, updated.SecurityLevel); + } [Fact] public async Task Response400IfUpdatingNotSettableAttribute() diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs index a24bf58208..92cb977c58 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/TestFixture.cs @@ -52,6 +52,7 @@ public IResponseDeserializer GetDeserializer() .AddResource() .AddResource() .AddResource() + .AddResource() .AddResource() .AddResource() .AddResource()