+ 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 view/create/change/sort/filter of attributes and relationships
+
+
+
+
+
+
Validation
+
Validate incoming requests using built-in ASP.NET Core ModelState 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
+
+public class Article : Identifiable
+{
+ [Attr]
+ [Required, MaxLength(30)]
+ public string Title { get; set; }
+
+ [Attr(Capabilities = AttrCapabilities.AllowFilter)]
+ public string Summary { get; set; }
+
+ [Attr(PublicName = "websiteUrl")]
+ public string Url { get; set; }
+
+ [Attr(Capabilities = AttrCapabilities.AllowView)]
+ public DateTimeOffset LastModifiedAt { get; set; }
+
+ [HasOne]
+ public Person Author { get; set; }
+
+ [HasMany]
+ public ICollection<Revision> Revisions { get; set; }
+
+ [HasManyThrough(nameof(ArticleTags))]
+ [NotMapped]
+ public ICollection<Tag> Tags { get; set; }
+ public ICollection<ArticleTag> ArticleTags { get; set; }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/index.md b/docs/index.md
deleted file mode 100644
index c4518c8884..0000000000
--- a/docs/index.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# JsonApiDotNetCore
-
-A [json:api](https://jsonapi.org) web application framework for .NET Core.
-
-## Objectives
-
-### 1. Eliminate Boilerplate
-
-The goal of this package is to facilitate the development of APIs that leverage the full range
-of features provided by the json:api specification.
-
-Eliminate CRUD boilerplate and provide the following features across your resource endpoints, from HTTP all the way down to the database:
-
-- Filtering
-- Sorting
-- Pagination
-- Sparse fieldset selection
-- Relationship inclusion and navigation
-
-Checkout the [example requests](request-examples/index.md) to see the kind of features you will get out of the box.
-
-### 2. Extensibility
-
-This library relies heavily on an open-generic-based dependency injection model, which allows for easy per-resource customization.
-
diff --git a/docs/usage/options.md b/docs/usage/options.md
index 1ee93a13de..b50713bf30 100644
--- a/docs/usage/options.md
+++ b/docs/usage/options.md
@@ -89,7 +89,7 @@ options.SerializerSettings.Converters.Add(new StringEnumConverter());
options.SerializerSettings.Formatting = Formatting.Indented;
```
-The default naming convention (as used in the routes and public resources names) is also determined here, and can be changed (default is camel-case):
+The default naming convention (as used in the routes and resource/attribute/relationship names) is also determined here, and can be changed (default is camel-case):
```c#
options.SerializerSettings.ContractResolver = new DefaultContractResolver
{
diff --git a/docs/usage/resource-graph.md b/docs/usage/resource-graph.md
index 7cce11dab7..e9f2859e92 100644
--- a/docs/usage/resource-graph.md
+++ b/docs/usage/resource-graph.md
@@ -71,7 +71,7 @@ public void ConfigureServices(IServiceCollection services)
}
```
-## Public Resource Name
+## Resource Name
The public resource name is exposed through the `type` member in the json:api payload. This can be configured by the following approaches (in order of priority):
diff --git a/docs/usage/resources/attributes.md b/docs/usage/resources/attributes.md
index 549f14483c..70686c7734 100644
--- a/docs/usage/resources/attributes.md
+++ b/docs/usage/resources/attributes.md
@@ -10,14 +10,13 @@ public class Person : Identifiable
}
```
-## Public name
+## Name
-There are two ways the public attribute name is determined:
+There are two ways the exposed attribute name is determined:
1. Using the configured [naming convention](~/usage/options.md#custom-serializer-settings).
-
-2. Individually using the attribute's constructor
+2. Individually using the attribute's constructor.
```c#
public class Person : Identifiable
{
@@ -43,7 +42,7 @@ This can be overridden per attribute.
Attributes can be marked to allow returning their value in responses. When not allowed and requested using `?fields=`, it results in an HTTP 400 response.
```c#
-public class User : Identifiable
+public class User : Identifiable
{
[Attr(Capabilities = ~AttrCapabilities.AllowView)]
public string Password { get; set; }
@@ -55,7 +54,7 @@ public class User : Identifiable
Attributes can be marked as creatable, which will allow `POST` requests to assign a value to them. When sent but not allowed, an HTTP 422 response is returned.
```c#
-public class Person : Identifiable
+public class Person : Identifiable
{
[Attr(Capabilities = AttrCapabilities.AllowCreate)]
public string CreatorName { get; set; }
@@ -67,7 +66,7 @@ public class Person : Identifiable
Attributes can be marked as changeable, which will allow `PATCH` requests to update them. When sent but not allowed, an HTTP 422 response is returned.
```c#
-public class Person : Identifiable
+public class Person : Identifiable
{
[Attr(Capabilities = AttrCapabilities.AllowChange)]
public string FirstName { get; set; }
@@ -79,7 +78,7 @@ public class Person : Identifiable
Attributes can be marked to allow filtering and/or sorting. When not allowed, it results in an HTTP 400 response.
```c#
-public class Person : Identifiable
+public class Person : Identifiable
{
[Attr(Capabilities = AttrCapabilities.AllowSort | AttrCapabilities.AllowFilter)]
public string FirstName { get; set; }
diff --git a/docs/usage/resources/relationships.md b/docs/usage/resources/relationships.md
index 3976e93ebb..b16640658f 100644
--- a/docs/usage/resources/relationships.md
+++ b/docs/usage/resources/relationships.md
@@ -5,30 +5,24 @@ they should be labeled with the appropriate attribute (either `HasOne`, `HasMany
## HasOne
-Dependent relationships should contain a property in the form `{RelationshipName}Id`.
-For example, a TodoItem may have an Owner and so the Id attribute should be OwnerId.
+This exposes a to-one relationship.
```c#
-public class TodoItem : Identifiable
+public class TodoItem : Identifiable
{
- [Attr]
- public string Description { get; set; }
-
[HasOne]
public Person Owner { get; set; }
- public int OwnerId { get; set; }
}
```
## HasMany
+This exposes a to-many relationship.
+
```c#
-public class Person : Identifiable
+public class Person : Identifiable
{
- [Attr(PublicName = "first-name")]
- public string FirstName { get; set; }
-
- [HasMany(PublicName = "todo-items")]
+ [HasMany]
public ICollection TodoItems { get; set; }
}
```
@@ -44,14 +38,41 @@ However, under the covers it will use the join type and Entity Framework Core's
public class Article : Identifiable
{
[NotMapped] // tells Entity Framework Core to ignore this property
- [HasManyThrough(nameof(ArticleTags))] // tells JsonApiDotNetCore to use this as an alias to ArticleTags.Tags
+ [HasManyThrough(nameof(ArticleTags))] // tells JsonApiDotNetCore to use the join table below
public ICollection Tags { get; set; }
- // this is the Entity Framework Core join relationship
+ // this is the Entity Framework Core navigation to the join table
public ICollection ArticleTags { get; set; }
}
```
+## Name
+
+There are two ways the exposed relationship name is determined:
+
+1. Using the configured [naming convention](~/usage/options.md#custom-serializer-settings).
+
+2. Individually using the attribute's constructor.
+```c#
+public class TodoItem : Identifiable
+{
+ [HasOne(PublicName = "item-owner")]
+ public Person Owner { get; set; }
+}
+```
+
+## Includibility
+
+Relationships can be marked to disallow including them using the `?include=` query string parameter. When not allowed, it results in an HTTP 400 response.
+
+```c#
+public class TodoItem : Identifiable
+{
+ [HasOne(CanInclude: false)]
+ public Person Owner { get; set; }
+}
+```
+
# Eager loading
_since v4.0_
diff --git a/docs/usage/routing.md b/docs/usage/routing.md
index 454d256bc9..640a3ba880 100644
--- a/docs/usage/routing.md
+++ b/docs/usage/routing.md
@@ -33,7 +33,7 @@ public class OrderLineController : JsonApiController
GET /orderLines HTTP/1.1
```
-The public name of the resource ([which can be customized](~/usage/resource-graph.md#public-resource-name)) is used for the route, instead of the controller name.
+The exposed name of the resource ([which can be customized](~/usage/resource-graph.md#resource-name)) is used for the route, instead of the controller name.
### Non-json:api controllers
@@ -59,7 +59,7 @@ public class OrderLineController : JsonApiController
}
}
```
-It is required to match your custom url with the public name of the associated resource.
+It is required to match your custom url with the exposed name of the associated resource.
## Advanced Usage: Custom Routing Convention