Skip to content

Commit baa1802

Browse files
Bart Koelmanmaurei
Bart Koelman
andauthored
Write enhancements (continued) (#875)
* Enhancements in create/update/delete Continuation of #851. * Various cleanups based on diff with master. * refactor: reduced ResourceService dependencies * refactor: move logic from GetResourcesByIds to composer * Refactor: remove IGetResourcesByIds * Replace repo.GetPrimaryResourceForCompleteReplacement with overridable coordination from service. * Removed IDataStoreUpdateFailureInspector dependency from repository * Simplified code * More refactorings * Added services.AddResourceRepository() * removed TODO * Reorder methods in calling order, renames, expose FlushFromCache/SaveChangesAsync * Removed ThroughEntitiesFilter * Renames * Extract responsibilities * Added tracking TODOs * formatting * TODO * Added tests for obfuscated IDs * Added marker to our TODOs * Added documentation * Tests for cyclic relationships * Folder rename * Migrated left-over tests * Change casing of .sln (1/2) * Change casing of .sln (2/2) * chore: restore toplevel related links in relationship endpoint * Merged IntegrationTests project * Added tests for 0 or empty string as primary key value * Removed TODO * tests: pagination on relationship endpoint * Fixes and more tests for handling zero/empty primary key * added check for related link * Fixes for proper error on relationship kind mismatch (HasOne vs HasMany) * Removed empty folder * tests: added required relationship tests, changed existing tests to display better assertion failures if they would have covered required relationships * Improved purging of change tracker * Replaced dependency on IResourceRepository with IResourceRepositoryAccessor * Move logic around to reduce dependencies in SecondaryResourceResolver. * Inlined ISecondaryResourceResolver into JsonApiResourceService * Refactorings to remove joinTableFilter parameter from ResourceRepository.AddToToManyRelationshipAsync() * Do not fetch resource for hooks on delete (because we didn't do that for GetSecondary either). * tests: required relationships * feat: throw CannotClearRequiredRelationshipException * chore: self review * refactor: EF Core null assignment change tracker trick no longer required * refactorings * refactorings * Added ID to error message * chore: review todos * Remove unused usings * fix: minor refactor repository * review * removed query for jointable * fix name * Use generic type parameter in IResourceRepositoryAccessor * Expose EntityFrameworkCoreRepository methods as protected to enable copy/paste Update method in derived classes * Readme updates * Small tweaks based on diff with master * Fixed casing Co-authored-by: maurei <maurits.moeys@gmail.com>
1 parent 2c1045a commit baa1802

File tree

266 files changed

+17710
-6147
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

266 files changed

+17710
-6147
lines changed

JsonApiDotnetCore.sln renamed to JsonApiDotNetCore.sln

Lines changed: 223 additions & 238 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<img src ="https://raw.githubusercontent.com/json-api-dotnet/JsonApiDotnetCore/master/logo.png" />
33
</p>
44

5-
# JSON API .Net Core
5+
# JSON:API .NET Core
66

77
[![Build status](https://ci.appveyor.com/api/projects/status/5go47hrm0iik0ls3/branch/master?svg=true)](https://ci.appveyor.com/project/jaredcnance/jsonapidotnetcore/branch/master)
88
[![Travis](https://travis-ci.org/json-api-dotnet/JsonApiDotNetCore.svg?branch=master)](https://travis-ci.org/json-api-dotnet/JsonApiDotNetCore)
@@ -21,7 +21,7 @@ These are some steps you can take to help you understand what this project is an
2121
- [Demo [Video]](https://youtu.be/KAMuo6K7VcE)
2222
- [Our documentation](https://json-api-dotnet.github.io/JsonApiDotNetCore/)
2323
- [Check out the example projects](https://github.com/json-api-dotnet/JsonApiDotNetCore/tree/master/src/Examples)
24-
- [Embercasts: Full Stack Ember with ASP .NET Core](https://www.embercasts.com/course/full-stack-ember-with-dotnet/watch/whats-in-this-course-cs)
24+
- [Embercasts: Full Stack Ember with ASP.NET Core](https://www.embercasts.com/course/full-stack-ember-with-dotnet/watch/whats-in-this-course-cs)
2525

2626
## Related Projects
2727

@@ -43,7 +43,7 @@ See [our documentation](https://json-api-dotnet.github.io/JsonApiDotNetCore/) fo
4343
```csharp
4444
public class Article : Identifiable
4545
{
46-
[Attr("name")]
46+
[Attr]
4747
public string Name { get; set; }
4848
}
4949
```
@@ -53,12 +53,11 @@ public class Article : Identifiable
5353
```csharp
5454
public class ArticlesController : JsonApiController<Article>
5555
{
56-
public ArticlesController(
57-
IJsonApiOptions options,
58-
IResourceService<Article> resourceService,
59-
ILoggerFactory loggerFactory)
60-
: base(options, resourceService, loggerFactory)
61-
{ }
56+
public ArticlesController(IJsonApiOptions options, IResourceService<Article> resourceService,
57+
ILoggerFactory loggerFactory)
58+
: base(options, resourceService, loggerFactory)
59+
{
60+
}
6261
}
6362
```
6463

@@ -67,14 +66,16 @@ public class ArticlesController : JsonApiController<Article>
6766
```csharp
6867
public class Startup
6968
{
70-
public IServiceProvider ConfigureServices(IServiceCollection services) {
69+
public IServiceProvider ConfigureServices(IServiceCollection services)
70+
{
7171
services.AddJsonApi<AppDbContext>();
72-
// ...
7372
}
7473

75-
public void Configure(IApplicationBuilder app) {
76-
app.UseJsonApi()
77-
// ...
74+
public void Configure(IApplicationBuilder app)
75+
{
76+
app.UseRouting();
77+
app.UseJsonApi();
78+
app.UseEndpoints(endpoints => endpoints.MapControllers());
7879
}
7980
}
8081
```
@@ -101,26 +102,19 @@ And then to run the tests:
101102
dotnet test
102103
```
103104

104-
#### Cleaning
105-
106-
Sometimes the compiled files can be dirty / corrupt from other branches / failed builds.
107-
108-
```bash
109-
dotnet clean
110-
```
111-
112105
#### Compiler warnings
113106

114107
The `Release` build configuration is set to fail on warnings. That means when submitting a PR there shouldn't be any compiler warnings because the CI build it set to `Release`.
115108

116109
## Compatibility
117110

118-
A lot of changes were introduced in v4.0.0, the following chart should help you with compatibility issues between .NET Core versions
111+
A lot of changes were introduced in v4, the following chart should help you with compatibility issues between .NET Core versions.
119112

120-
| .NET Core Version | JADNC Version |
121-
| ----------------- | ------------- |
122-
| 2.* | v3.* |
123-
| 3.* | v4.* |
113+
| .NET Core Version | EF Core Version | JADNC Version |
114+
| ----------------- | --------------- | ------------- |
115+
| 2.x | 2.x | v3.x |
116+
| 3.x | 3.x, 5.x | v4.x |
117+
| 5.x | 5.x | v4.x |
124118

125119
## Trying out the latest build
126120

benchmarks/Serialization/JsonApiDeserializerBenchmarks.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.ComponentModel.Design;
44
using BenchmarkDotNet.Attributes;
55
using JsonApiDotNetCore.Configuration;
6+
using JsonApiDotNetCore.Middleware;
67
using JsonApiDotNetCore.Resources;
78
using JsonApiDotNetCore.Serialization;
89
using JsonApiDotNetCore.Serialization.Objects;
@@ -37,7 +38,8 @@ public JsonApiDeserializerBenchmarks()
3738
var options = new JsonApiOptions();
3839
IResourceGraph resourceGraph = DependencyFactory.CreateResourceGraph(options);
3940
var targetedFields = new TargetedFields();
40-
_jsonApiDeserializer = new RequestDeserializer(resourceGraph, new ResourceFactory(new ServiceContainer()), targetedFields, new HttpContextAccessor());
41+
var request = new JsonApiRequest();
42+
_jsonApiDeserializer = new RequestDeserializer(resourceGraph, new ResourceFactory(new ServiceContainer()), targetedFields, new HttpContextAccessor(), request);
4143
}
4244

4345
[Benchmark]

benchmarks/Serialization/JsonApiSerializerBenchmarks.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ private static FieldsToSerialize CreateFieldsToSerialize(IResourceGraph resource
4949

5050
var accessor = new Mock<IResourceDefinitionAccessor>().Object;
5151

52-
return new FieldsToSerialize(resourceGraph, constraintProviders, accessor);
52+
return new FieldsToSerialize(resourceGraph, constraintProviders, accessor, request);
5353
}
5454

5555
[Benchmark]

docs/getting-started/install.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ Install-Package JsonApiDotnetCore
1616
```xml
1717
<ItemGroup>
1818
<!-- Be sure to check NuGet for the latest version # -->
19-
<PackageReference Include="JsonApiDotNetCore" Version="3.0.0" />
19+
<PackageReference Include="JsonApiDotNetCore" Version="4.0.0" />
2020
</ItemGroup>
2121
```

docs/internals/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# Internals
22

3-
The section contains overviews for the inner workings of the JsonApiDotNetCore library.
3+
This section contains overviews for the inner workings of the JsonApiDotNetCore library.

docs/request-examples/index.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,22 +45,22 @@ _Note that cURL requires "[" and "]" in URLs to be escaped._
4545

4646
# Writing data
4747

48-
### Create
48+
### Create resource
4949

5050
[!code-ps[REQUEST](010_CREATE_Person.ps1)]
5151
[!code-json[RESPONSE](010_CREATE_Person_Response.json)]
5252

53-
### Create with relationship
53+
### Create resource with relationship
5454

5555
[!code-ps[REQUEST](011_CREATE_Book-with-Author.ps1)]
5656
[!code-json[RESPONSE](011_CREATE_Book-with-Author_Response.json)]
5757

58-
### Update
58+
### Update resource
5959

6060
[!code-ps[REQUEST](012_PATCH_Book.ps1)]
6161
[!code-json[RESPONSE](012_PATCH_Book_Response.json)]
6262

63-
### Delete
63+
### Delete resource
6464

6565
[!code-ps[REQUEST](013_DELETE_Book.ps1)]
6666
[!code-json[RESPONSE](013_DELETE_Book_Response.json)]

docs/usage/extensibility/repositories.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
If you want to use a data access technology other than Entity Framework Core, you can create an implementation of `IResourceRepository<TResource, TId>`.
44
If you only need minor changes you can override the methods defined in `EntityFrameworkCoreRepository<TResource, TId>`.
55

6-
The repository should then be added to the service collection in Startup.cs.
6+
The repository should then be registered in Startup.cs.
77

88
```c#
99
public void ConfigureServices(IServiceCollection services)
@@ -12,6 +12,21 @@ public void ConfigureServices(IServiceCollection services)
1212
}
1313
```
1414

15+
In v4.0 we introduced an extension method that you can use to register a resource repository on all of its JsonApiDotNetCore interfaces.
16+
This is helpful when you implement a subset of the resource interfaces and want to register them all in one go.
17+
18+
Note: If you're using service discovery, this happens automatically.
19+
20+
```c#
21+
public class Startup
22+
{
23+
public void ConfigureServices(IServiceCollection services)
24+
{
25+
services.AddResourceRepository<ArticleRepository>();
26+
}
27+
}
28+
```
29+
1530
A sample implementation that performs authorization might look like this.
1631

1732
All of the methods in EntityFrameworkCoreRepository will use the `GetAll()` method to get the `DbSet<TResource>`, so this is a good method to apply filters such as user or tenant authorization.

docs/usage/extensibility/services.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ IResourceService
115115
PATCH /{id}/relationships/{relationship}
116116
```
117117

118-
In order to take advantage of these interfaces you first need to inject the service for each implemented interface.
118+
In order to take advantage of these interfaces you first need to register the service for each implemented interface.
119119

120120
```c#
121121
public class ArticleService : ICreateService<Article>, IDeleteService<Article>
@@ -136,6 +136,8 @@ public class Startup
136136
In v3.0 we introduced an extension method that you can use to register a resource service on all of its JsonApiDotNetCore interfaces.
137137
This is helpful when you implement a subset of the resource interfaces and want to register them all in one go.
138138

139+
Note: If you're using service discovery, this happens automatically.
140+
139141
```c#
140142
public class Startup
141143
{
File renamed without changes.

docs/usage/including-relationships.md renamed to docs/usage/reading/including-relationships.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ GET /articles/1?include=comments HTTP/1.1
4747

4848
## Nested Inclusions
4949

50-
_since v3.0.0_
50+
_since v3_
5151

5252
JsonApiDotNetCore also supports nested inclusions.
5353
This allows you to include data across relationships by using a period-delimited relationship path, for example:
File renamed without changes.
File renamed without changes.

docs/usage/resource-graph.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# The Resource Graph
22

3-
_NOTE: prior to 3.0.0 this was called the `ContextGraph`_
3+
_NOTE: prior to v4 this was called the `ContextGraph`_
44

55
The `ResourceGraph` is a map of all the json:api resources and their relationships that your API serves.
66

docs/usage/resources/relationships.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@ public class TodoItem : Identifiable<int>
2020
}
2121
```
2222

23-
The convention used to locate the foreign key property (e.g. `OwnerId`) can be changed on
24-
the @JsonApiDotNetCore.Configuration.JsonApiOptions#JsonApiDotNetCore_Configuration_JsonApiOptions_RelatedIdMapper
25-
2623
## HasMany
2724

2825
```c#

docs/usage/resources/resource-definitions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ public class EmployeeDefinition : JsonApiResourceDefinition<Employee>
193193

194194
## Custom query string parameters
195195

196-
_since v3.0.0_
196+
_since v3_
197197

198198
You can define additional query string parameters with the LINQ expression that should be used.
199199
If the key is present in a query string, the supplied LINQ expression will be added to the database query.

docs/usage/toc.md

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,20 @@
33
## [Relationships](resources/relationships.md)
44
## [Resource Definitions](resources/resource-definitions.md)
55

6+
# Reading data
7+
## [Filtering](reading/filtering.md)
8+
## [Sorting](reading/sorting.md)
9+
## [Pagination](reading/pagination.md)
10+
## [Sparse Fieldset Selection](reading/sparse-fieldset-selection.md)
11+
## [Including Relationships](reading/including-relationships.md)
12+
13+
# Writing data
14+
## [Creating](writing/creating.md)
15+
## [Updating](writing/updating.md)
16+
## [Deleting](writing/deleting.md)
17+
618
# [Resource Graph](resource-graph.md)
719
# [Options](options.md)
8-
# [Filtering](filtering.md)
9-
# [Sorting](sorting.md)
10-
# [Pagination](pagination.md)
11-
# [Sparse Fieldset Selection](sparse-fieldset-selection.md)
12-
# [Including Relationships](including-relationships.md)
1320
# [Routing](routing.md)
1421
# [Errors](errors.md)
1522
# [Metadata](meta.md)

docs/usage/writing/creating.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Creating resources
2+
3+
A single resource can be created by sending a POST request. The next example creates a new article:
4+
5+
```http
6+
POST /articles HTTP/1.1
7+
8+
{
9+
"data": {
10+
"type": "articles",
11+
"attributes": {
12+
"caption": "A new article!",
13+
"url": "www.website.com"
14+
}
15+
}
16+
}
17+
```
18+
19+
When using client-generated IDs and only attributes from the request have changed, the server returns `204 No Content`.
20+
Otherwise, the server returns `200 OK`, along with the updated resource and its newly assigned ID.
21+
22+
In both cases, a `Location` header is returned that contains the URL to the new resource.
23+
24+
# Creating resources with relationships
25+
26+
It is possible to create a new resource and establish relationships to existing resources in a single request.
27+
The example below creates an article and sets both its owner and tags.
28+
29+
```http
30+
POST /articles HTTP/1.1
31+
32+
{
33+
"data": {
34+
"type": "articles",
35+
"attributes": {
36+
"caption": "A new article!"
37+
},
38+
"relationships": {
39+
"author": {
40+
"data": {
41+
"type": "person",
42+
"id": "101"
43+
}
44+
},
45+
"tags": {
46+
"data": [
47+
{
48+
"type": "tag",
49+
"id": "123"
50+
},
51+
{
52+
"type": "tag",
53+
"id": "456"
54+
}
55+
]
56+
}
57+
}
58+
}
59+
}
60+
```
61+
62+
# Response body
63+
64+
POST requests can be combined with query string parameters that are normally used for reading data, such as `include` and `fields`. For example:
65+
66+
```http
67+
POST /articles?include=owner&fields[owner]=firstName HTTP/1.1
68+
69+
{
70+
...
71+
}
72+
```
73+
74+
After the resource has been created on the server, it is re-fetched from the database using the specified query string parameters and returned to the client.

docs/usage/writing/deleting.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Deleting resources
2+
3+
A single resource can be deleted using a DELETE request. The next example deletes an article:
4+
5+
```http
6+
DELETE /articles/1 HTTP/1.1
7+
```
8+
9+
This returns `204 No Content` if the resource was successfully deleted. Alternatively, if the resource does not exist, `404 Not Found` is returned.

0 commit comments

Comments
 (0)