Objectives
The goal of this library is to simplify the development of APIs that leverage the full range of features provided by the JSON:API specification. You just need to focus on defining the resources and implementing your custom business logic.
Eliminate boilerplate
We strive to eliminate as much boilerplate as possible by offering out-of-the-box features such as sorting, filtering and pagination.
Extensibility
This library has been designed around dependency injection, making extensibility incredibly easy.
Features
The following features are supported, from HTTP all the way down to the database
Filtering
Perform compound filtering using the filter
query string parameter
Sorting
Order resources on one or multiple attributes using the sort
query string parameter
Pagination
Leverage the benefits of paginated resources with the page
query string parameter
Sparse fieldset selection
Get only the data that you need using the fields
query string parameter
Relationship inclusion
Side-load related resources of nested relationships using the include
query string parameter
Security
Configure permissions, such as viewing, creating, modifying, sorting and filtering of attributes and relationships
Validation
Validate incoming requests using built-in ASP.NET Model Validation, which works seamlessly with partial updates
Customizable
Use various extensibility points to intercept and run custom code, besides just model annotations
Example usage
Expose resources with attributes and relationships
Resource
#nullable enable
public class Article : Identifiable<long>
{
[Attr]
[MaxLength(30)]
public string Title { get; set; } = null!;
[Attr(Capabilities = AttrCapabilities.AllowFilter)]
public string? Summary { get; set; }
[Attr(PublicName = "websiteUrl")]
public string? Url { get; set; }
[Attr]
[Required]
public int? WordCount { get; set; }
[Attr(Capabilities = AttrCapabilities.AllowView)]
public DateTimeOffset LastModifiedAt { get; set; }
[HasOne]
public Person Author { get; set; } = null!;
[HasOne]
public Person? Reviewer { get; set; }
[HasMany]
public ICollection<Tag> Tags { get; set; } = new HashSet<Tag>();
}
Request
GET /articles?filter=contains(summary,'web')&sort=-lastModifiedAt&fields[articles]=title,summary&include=author HTTP/1.1
Response
{
"meta": {
"totalResources": 1
},
"links": {
"self": "/articles?filter=contains(summary,'web')&sort=-lastModifiedAt&fields%5Barticles%5D=title,summary&include=author",
"first": "/articles?filter=contains(summary,'web')&sort=-lastModifiedAt&fields%5Barticles%5D=title,summary&include=author",
"last": "/articles?filter=contains(summary,'web')&sort=-lastModifiedAt&fields%5Barticles%5D=title,summary&include=author"
},
"data": [
{
"type": "articles",
"id": "1",
"attributes": {
"title": "JsonApiDotNetCore rocks!",
"summary": "Using JsonApiDotNetCore makes the web a better accessible place."
},
"relationships": {
"author": {
"links": {
"self": "/articles/1/relationships/author",
"related": "/articles/1/author"
},
"data": {
"type": "people",
"id": "1"
}
}
},
"links": {
"self": "/articles/1"
}
}
],
"included": [
{
"type": "people",
"id": "1",
"attributes": {
"name": "John Doe"
},
"relationships": {
"articles": {
"links": {
"self": "/people/1/relationships/articles",
"related": "/people/1/articles"
}
}
},
"links": {
"self": "/people/1"
}
}
]
}