Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions docs/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,5 @@ This section documents the package API and is generated from the XML source comm
## Common APIs

- [`JsonApiOptions`](JsonApiDotNetCore.Configuration.JsonApiOptions.html)
- [`IResourceGraph`](JsonApiDotNetCore.Internal.IResourceGraph.html)
- [`IResourceGraph`](JsonApiDotNetCore.Internal.Contracts.IResourceGraph.html)
- [`ResourceDefinition<T>`](JsonApiDotNetCore.Models.ResourceDefinition-1.html)
- [`IQueryAccessor`](JsonApiDotNetCore.Services.IQueryAccessor.html)
9 changes: 0 additions & 9 deletions docs/generators/index.md

This file was deleted.

16 changes: 0 additions & 16 deletions docs/getting-started/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,3 @@ Install-Package JsonApiDotnetCore
<PackageReference Include="JsonApiDotNetCore" Version="3.0.0" />
</ItemGroup>
```

## Pre-Release Packages

Occasionally we will release experimental features as pre-release packages on our
MyGet feed. You can download these by adding [the pacakge feed](https://www.myget.org/feed/Details/research-institute) to your nuget configuration.

These releases are deployed from the `develop` branch directly.

```xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="JADNC Pre-Release" value="https://www.myget.org/F/research-institute/api/v3/index.json" />
</packageSources>
</configuration>
```
44 changes: 23 additions & 21 deletions docs/getting-started/step-by-step.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Step-By-Step Guide to a Running API

The most basic use case leverages Entity Framework.
The most basic use case leverages Entity Framework Core.
The shortest path to a running API looks like:

- Create a new web app
Expand Down Expand Up @@ -35,7 +35,7 @@ Install-Package JsonApiDotnetCore
### Define Models

Define your domain models such that they implement `IIdentifiable<TId>`.
The easiest way to do this is to inherit `Identifiable`
The easiest way to do this is to inherit from `Identifiable`

```c#
public class Person : Identifiable
Expand All @@ -61,17 +61,17 @@ public class AppDbContext : DbContext

### Define Controllers

You need to create controllers that inherit from `JsonApiController<TEntity>` or `JsonApiController<TEntity, TId>`
where `TEntity` is the model that inherits from `Identifiable<TId>`
You need to create controllers that inherit from `JsonApiController<T>` or `JsonApiController<T, TId>`
where `T` is the model that inherits from `Identifiable<TId>`

```c#
public class PeopleController : JsonApiController<Person>
{
public PeopleController(
IJsonApiContext jsonApiContext,
IResourceService<Person> resourceService,
ILoggerFactory loggerFactory)
: base(jsonApiContext, resourceService, loggerFactory)
IJsonApiOptions jsonApiOptions,
ILoggerFactory loggerFactory,
IResourceService<Person> resourceService)
: base(jsonApiOptions, loggerFactory, resourceService)
{ }
}
```
Expand All @@ -81,24 +81,26 @@ public class PeopleController : JsonApiController<Person>
Finally, add the services by adding the following to your Startup.ConfigureServices:

```c#
public IServiceProvider ConfigureServices(IServiceCollection services)
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// add the db context like you normally would
// Add the Entity Framework Core DbContext like you normally would
services.AddDbContext<AppDbContext>(options =>
{ // use whatever provider you want, this is just an example
{
// Use whatever provider you want, this is just an example
options.UseNpgsql(GetDbConnectionString());
}, ServiceLifetime.Transient);
});

// add jsonapi dotnet core
// Add JsonApiDotNetCore
services.AddJsonApi<AppDbContext>();
// ...
}
```

Add the middleware to the Startup.Configure method. Note that under the hood,
this will call `app.UseMvc()` so there is no need to add that as well.
this will call `app.UseRouting()` and `app.UseEndpoints(...)` so there is no need to add that as well.

```c#
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app)
{
app.UseJsonApi();
Expand All @@ -110,19 +112,19 @@ public void Configure(IApplicationBuilder app)
One way to seed the database is in your Configure method:

```c#
public void Configure(
IApplicationBuilder app,
AppDbContext context)
public void Configure(IApplicationBuilder app, AppDbContext context)
{
context.Database.EnsureCreated();
if(context.People.Any() == false)

if (!context.People.Any())
{
context.People.Add(new Person {
context.People.Add(new Person
{
Name = "John Doe"
});
context.SaveChanges();
}
// ...

app.UseJsonApi();
}
```
Expand Down
1 change: 0 additions & 1 deletion docs/request-examples/000-CREATE_Person.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
curl -vs http://localhost:5001/api/people \
-H "Accept: application/vnd.api+json" \
-H "Content-Type: application/vnd.api+json" \
-d '{
"data": {
Expand Down
1 change: 0 additions & 1 deletion docs/request-examples/001-CREATE_Article.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
curl -vs http://localhost:5001/api/articles \
-H "Accept: application/vnd.api+json" \
-H "Content-Type: application/vnd.api+json" \
-d '{
"data": {
Expand Down
3 changes: 1 addition & 2 deletions docs/request-examples/002-GET_Articles.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
curl -vs http://localhost:5001/api/articles \
-H "Accept: application/vnd.api+json"
curl -vs http://localhost:5001/api/articles
3 changes: 1 addition & 2 deletions docs/request-examples/003-GET_Article.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
curl -vs http://localhost:5001/api/articles/1 \
-H "Accept: application/vnd.api+json"
curl -vs http://localhost:5001/api/articles/1
3 changes: 1 addition & 2 deletions docs/request-examples/004-GET_Articles_With_Authors.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
curl -vs http://localhost:5001/api/articles?include=author \
-H "Accept: application/vnd.api+json"
curl -vs http://localhost:5001/api/articles?include=author
3 changes: 1 addition & 2 deletions docs/request-examples/005-PATCH_Article.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
curl -vs http://localhost:5001/api/people/1 \
-H "Accept: application/vnd.api+json" \
curl -vs http://localhost:5001/api/people/1 \
-H "Content-Type: application/vnd.api+json" \
-X PATCH \
-d '{
Expand Down
1 change: 0 additions & 1 deletion docs/request-examples/006-DELETE_Article.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
curl -vs http://localhost:5001/api/articles/1 \
-H "Accept: application/vnd.api+json" \
-X DELETE
2 changes: 0 additions & 2 deletions docs/request-examples/007-__SEED__.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
curl -vs http://localhost:5001/api/people \
-H "Accept: application/vnd.api+json" \
-H "Content-Type: application/vnd.api+json" \
-d '{
"data": {
Expand All @@ -11,7 +10,6 @@ curl -vs http://localhost:5001/api/people \
}'

curl -vs http://localhost:5001/api/articles \
-H "Accept: application/vnd.api+json" \
-H "Content-Type: application/vnd.api+json" \
-d '{
"data": {
Expand Down
3 changes: 1 addition & 2 deletions docs/request-examples/008-GET_Articles_With_Filter_Eq.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
curl -vs http://localhost:5001/api/articles?filter%5Btitle%5D=Moby \
-H "Accept: application/vnd.api+json"
curl -vs http://localhost:5001/api/articles?filter%5Btitle%5D=Moby
3 changes: 1 addition & 2 deletions docs/request-examples/009-GET_Articles_With_Filter_Like.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
curl -vs http://localhost:5001/api/people?filter%5Bname%5D=like:Al \
-H "Accept: application/vnd.api+json"
curl -vs http://localhost:5001/api/people?filter%5Bname%5D=like:Al
3 changes: 1 addition & 2 deletions docs/request-examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ To update these requests:

1. Add a bash (.sh) file prefixed by a number that is used to determine the order the scripts are executed. The bash script should execute a request and output the response. Example:
```
curl -vs http://localhost:5001/api/articles \
-H "Accept: application/vnd.api+json"
curl -vs http://localhost:5001/api/articles
```

2. Add the example to `index.md`. Example:
Expand Down
70 changes: 14 additions & 56 deletions docs/usage/errors.md
Original file line number Diff line number Diff line change
@@ -1,67 +1,25 @@
# Errors

By default, errors will only contain the properties defined by the `Error` class.
However, you can create your own by inheriting from Error and either throwing it in a `JsonApiException` or returning the error from your controller.
Errors returned will contain only the properties that are set on the `Error` class. Custom fields can be added through `Error.Meta`.
You can create a custom error by throwing a `JsonApiException` (which accepts an `Error` instance), or returning an `Error` instance from an `ActionResult` in a controller.
Please keep in mind that json:api requires Title to be a generic message, while Detail should contain information about the specific problem occurence.

From a controller method:
```c#
public class CustomError : Error
return Conflict(new Error(HttpStatusCode.Conflict)
{
public CustomError(int status, string title, string detail, string myProp)
: base(status, title, detail)
{
MyCustomProperty = myProp;
}

public string MyCustomProperty { get; set; }
}
Title = "Target resource was modified by another user.",
Detail = $"User {userName} changed the {resourceField} field on the {resourceName} resource."
});
```

If you throw a `JsonApiException` that is unhandled, the middleware will properly serialize it and return it as a json:api error.

From other code:
```c#
public void MyMethod()
throw new JsonApiException(new Error(HttpStatusCode.Conflict)
{
var error = new CustomError(507, "title", "detail", "custom");
throw new JsonApiException(error);
}
Title = "Target resource was modified by another user.",
Detail = $"User {userName} changed the {resourceField} field on the {resourceName} resource."
});
```

You can use the `IActionResult Error(Error error)` method to return a single error message, or you can use the `IActionResult Errors(ErrorCollection errors)` method to return a collection of errors from your controller.

```c#
[HttpPost]
public override async Task<IActionResult> PostAsync([FromBody] MyEntity entity)
{
if(_db.IsFull)
return Error(new CustomError("507", "Database is full.", "Theres no more room.", "Sorry."));

if(model.Validations.IsValid == false)
return Errors(model.Validations.GetErrors());
}
```

## Example: Including Links

This example demonstrates one way you can include links with your error payloads.

This example assumes that there is a support documentation site that provides additional information based on the HTTP Status Code.

```c#
public class LinkableError : Error
{
public LinkableError(int status, string title)
: base(status, title)
{ }

public ErrorLink Links => "https://example.com/errors/" + Status;
}

var error = new LinkableError(401, "You're not allowed to do that.");
throw new JsonApiException(error);
```






In both cases, the middleware will properly serialize it and return it as a json:api error.
Loading