Skip to content

Commit f51e1b7

Browse files
committed
Consolidate getting-started steps
1 parent 1736377 commit f51e1b7

File tree

10 files changed

+209
-346
lines changed

10 files changed

+209
-346
lines changed

README.md

+13-2
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,23 @@ The ultimate goal of this library is to eliminate as much boilerplate as possibl
2020

2121
The following steps describe how to create a JSON:API project.
2222

23+
1. Create a new ASP.NET Core Web API project:
24+
25+
```bash
26+
dotnet new webapi --no-openapi --use-controllers --name ExampleJsonApi
27+
cd ExampleJsonApi
28+
```
29+
2330
1. Install the JsonApiDotNetCore package, along with your preferred Entity Framework Core provider:
31+
2432
```bash
2533
dotnet add package JsonApiDotNetCore
2634
dotnet add package Microsoft.EntityFrameworkCore.Sqlite
2735
```
2836

2937
1. Declare your entities, annotated with JsonApiDotNetCore attributes:
30-
```c#
31-
#nullable enable
3238

39+
```c#
3340
[Resource]
3441
public class Person : Identifiable<long>
3542
{
@@ -40,6 +47,7 @@ The following steps describe how to create a JSON:API project.
4047
```
4148

4249
1. Define your `DbContext`, seeding the database with sample data:
50+
4351
```c#
4452
public class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options)
4553
{
@@ -70,6 +78,7 @@ The following steps describe how to create a JSON:API project.
7078
```
7179

7280
1. Configure Entity Framework Core and JsonApiDotNetCore in `Program.cs`:
81+
7382
```c#
7483
var builder = WebApplication.CreateBuilder(args);
7584
builder.Services.AddDbContext<AppDbContext>();
@@ -96,11 +105,13 @@ The following steps describe how to create a JSON:API project.
96105
```
97106

98107
1. Start your API
108+
99109
```bash
100110
dotnet run
101111
```
102112

103113
1. Send a GET request to retrieve data:
114+
104115
```bash
105116
GET http://localhost:5000/people?filter=equals(firstName,'John')&include=children HTTP/1.1
106117
```

docs/getting-started/faq.md

+3-176
Original file line numberDiff line numberDiff line change
@@ -1,176 +1,3 @@
1-
# Frequently Asked Questions
2-
3-
#### Where can I find documentation and examples?
4-
While the [documentation](~/usage/resources/index.md) covers basic features and a few runnable example projects are available [here](https://github.com/json-api-dotnet/JsonApiDotNetCore/tree/master/src/Examples),
5-
many more advanced use cases are available as integration tests [here](https://github.com/json-api-dotnet/JsonApiDotNetCore/tree/master/test/JsonApiDotNetCoreTests/IntegrationTests), so be sure to check them out!
6-
7-
#### Why don't you use the built-in OpenAPI support in ASP.NET Core?
8-
The structure of JSON:API request and response bodies differs significantly from the signature of JsonApiDotNetCore controllers.
9-
JsonApiDotNetCore provides OpenAPI support using [Swashbuckle](https://github.com/domaindrivendev/Swashbuckle.AspNetCore), a mature and feature-rich library that is highly extensible.
10-
The [OpenAPI support in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/openapi/overview) is still very young
11-
and doesn't provide the level of extensibility needed for JsonApiDotNetCore.
12-
13-
#### What's available to implement a JSON:API client?
14-
To generate a typed client (specific to the resource types in your project), consider using our [OpenAPI](https://www.jsonapi.net/usage/openapi.html) NuGet package.
15-
16-
If you need a generic client, it depends on the programming language used. There's an overwhelming list of client libraries at https://jsonapi.org/implementations/#client-libraries.
17-
18-
The JSON object model inside JsonApiDotNetCore is tweaked for server-side handling (be tolerant at inputs and strict at outputs).
19-
While you technically *could* use our `JsonSerializer` converters from a .NET client application with some hacks, we don't recommend doing so.
20-
You'll need to build the resource graph on the client and rely on internal implementation details that are subject to change in future versions.
21-
22-
#### How can I debug my API project?
23-
Due to auto-generated controllers, you may find it hard to determine where to put your breakpoints.
24-
In Visual Studio, controllers are accessible below **Solution Explorer > Project > Dependencies > Analyzers > JsonApiDotNetCore.SourceGenerators**.
25-
26-
After turning on [Source Link](https://devblogs.microsoft.com/dotnet/improving-debug-time-productivity-with-source-link/#enabling-source-link) (which enables to download the JsonApiDotNetCore source code from GitHub), you can step into our source code and add breakpoints there too.
27-
28-
Here are some key places in the execution pipeline to set a breakpoint:
29-
- `JsonApiRoutingConvention.Apply`: Controllers are registered here (executes once at startup)
30-
- `JsonApiMiddleware.InvokeAsync`: Content negotiation and `IJsonApiRequest` setup
31-
- `QueryStringReader.ReadAll`: Parses the query string parameters
32-
- `JsonApiReader.ReadAsync`: Parses the request body
33-
- `OperationsProcessor.ProcessAsync`: Entry point for handling atomic operations
34-
- `JsonApiResourceService`: Called by controllers, delegating to the repository layer
35-
- `EntityFrameworkCoreRepository.ApplyQueryLayer`: Builds the `IQueryable<>` that is offered to Entity Framework Core (which turns it into SQL)
36-
- `JsonApiWriter.WriteAsync`: Renders the response body
37-
- `ExceptionHandler.HandleException`: Interception point for thrown exceptions
38-
39-
Aside from debugging, you can get more info by:
40-
- Including exception stack traces and incoming request bodies in error responses, as well as writing human-readable JSON:
41-
42-
```c#
43-
// Program.cs
44-
builder.Services.AddJsonApi<AppDbContext>(options =>
45-
{
46-
options.IncludeExceptionStackTraceInErrors = true;
47-
options.IncludeRequestBodyInErrors = true;
48-
options.SerializerOptions.WriteIndented = true;
49-
});
50-
```
51-
- Turning on verbose logging and logging of executed SQL statements, by adding the following to your `appsettings.Development.json`:
52-
53-
```json
54-
{
55-
"Logging": {
56-
"LogLevel": {
57-
"Default": "Warning",
58-
"Microsoft.EntityFrameworkCore.Database.Command": "Information",
59-
"JsonApiDotNetCore": "Verbose"
60-
}
61-
}
62-
}
63-
```
64-
65-
#### What if my JSON:API resources do not exactly match the shape of my database tables?
66-
We often find users trying to write custom code to solve that. They usually get it wrong or incomplete, and it may not perform well.
67-
Or it simply fails because it cannot be translated to SQL.
68-
The good news is that there's an easier solution most of the time: configure Entity Framework Core mappings to do the work.
69-
70-
For example, if your primary key column is named "CustomerId" instead of "Id":
71-
```c#
72-
builder.Entity<Customer>().Property(x => x.Id).HasColumnName("CustomerId");
73-
```
74-
75-
It certainly pays off to read up on these capabilities at [Creating and Configuring a Model](https://learn.microsoft.com/ef/core/modeling/).
76-
Another great resource is [Learn Entity Framework Core](https://www.learnentityframeworkcore.com/configuration).
77-
78-
#### Can I share my resource models with .NET Framework projects?
79-
Yes, you can. Put your model classes in a separate project that only references [JsonApiDotNetCore.Annotations](https://www.nuget.org/packages/JsonApiDotNetCore.Annotations/).
80-
This package contains just the JSON:API attributes and targets NetStandard 1.0, which makes it flexible to consume.
81-
At startup, use [Auto-discovery](~/usage/resource-graph.md#auto-discovery) and point it to your shared project.
82-
83-
#### What's the best place to put my custom business/validation logic?
84-
For basic input validation, use the attributes from [ASP.NET ModelState Validation](https://learn.microsoft.com/aspnet/core/mvc/models/validation?source=recommendations&view=aspnetcore-7.0#built-in-attributes) to get the best experience.
85-
JsonApiDotNetCore is aware of them and adjusts behavior accordingly. And it produces the best possible error responses.
86-
87-
For non-trivial business rules that require custom code, the place to be is [Resource Definitions](~/usage/extensibility/resource-definitions.md).
88-
They provide a callback-based model where you can respond to everything going on.
89-
The great thing is that your callbacks are invoked for various endpoints.
90-
For example, the filter callback on Author executes at `GET /authors?filter=`, `GET /books/1/authors?filter=` and `GET /books?include=authors?filter[authors]=`.
91-
Likewise, the callbacks for changing relationships execute for POST/PATCH resource endpoints, as well as POST/PATCH/DELETE relationship endpoints.
92-
93-
#### Can API users send multiple changes in a single request?
94-
Yes, just activate [atomic operations](~/usage/writing/bulk-batch-operations.md).
95-
It enables sending multiple changes in a batch request, which are executed in a database transaction.
96-
If something fails, all changes are rolled back. The error response indicates which operation failed.
97-
98-
#### Is there any way to add `[Authorize(Roles = "...")]` to the generated controllers?
99-
Sure, this is possible. Simply add the attribute at the class level.
100-
See the docs on [Augmenting controllers](~/usage/extensibility/controllers.md#augmenting-controllers).
101-
102-
#### How do I expose non-JSON:API endpoints?
103-
You can add your own controllers that do not derive from `(Base)JsonApiController` or `(Base)JsonApiOperationsController`.
104-
Whatever you do in those is completely ignored by JsonApiDotNetCore.
105-
This is useful if you want to add a few RPC-style endpoints or provide binary file uploads/downloads.
106-
107-
A middle-ground approach is to add custom action methods to existing JSON:API controllers.
108-
While you can route them as you like, they must return JSON:API resources.
109-
And on error, a JSON:API error response is produced.
110-
This is useful if you want to stay in the JSON:API-compliant world, but need to expose something non-standard, for example: `GET /users/me`.
111-
112-
#### How do I optimize for high scalability and prevent denial of service?
113-
Fortunately, JsonApiDotNetCore [scales pretty well](https://github.com/json-api-dotnet/PerformanceReports) under high load and/or large database tables.
114-
It never executes filtering, sorting, or pagination in-memory and tries pretty hard to produce the most efficient query possible.
115-
There are a few things to keep in mind, though:
116-
- Prevent users from executing slow queries by locking down [attribute capabilities](~/usage/resources/attributes.md#capabilities) and [relationship capabilities](~/usage/resources/relationships.md#capabilities).
117-
Ensure the right database indexes are in place for what you enable.
118-
- Prevent users from fetching lots of data by tweaking [maximum page size/number](~/usage/options.md#pagination) and [maximum include depth](~/usage/options.md#maximum-include-depth).
119-
- Avoid long-running transactions by tweaking `MaximumOperationsPerRequest` in options.
120-
- Tell your users to utilize [E-Tags](~/usage/caching.md) to reduce network traffic.
121-
- Not included in JsonApiDotNetCore: Apply general practices such as rate limiting, load balancing, authentication/authorization, blocking very large URLs/request bodies, etc.
122-
123-
#### Can I offload requests to a background process?
124-
Yes, that's possible. Override controller methods to return `HTTP 202 Accepted`, with a `Location` HTTP header where users can retrieve the result.
125-
Your controller method needs to store the request state (URL, query string, and request body) in a queue, which your background process can read from.
126-
From within your background process job handler, reconstruct the request state, execute the appropriate `JsonApiResourceService` method and store the result.
127-
There's a basic example available at https://github.com/json-api-dotnet/JsonApiDotNetCore/pull/1144, which processes a captured query string.
128-
129-
#### What if I want to use something other than Entity Framework Core?
130-
This basically means you'll need to implement data access yourself. There are two approaches for interception: at the resource service level and at the repository level.
131-
Either way, you can use the built-in query string and request body parsing, as well as routing, error handling, and rendering of responses.
132-
133-
Here are some injectable request-scoped types to be aware of:
134-
- `IJsonApiRequest`: This contains routing information, such as whether a primary, secondary, or relationship endpoint is being accessed.
135-
- `ITargetedFields`: Lists the attributes and relationships from an incoming POST/PATCH resource request. Any fields missing there should not be stored (partial updates).
136-
- `IEnumerable<IQueryConstraintProvider>`: Provides access to the parsed query string parameters.
137-
- `IEvaluatedIncludeCache`: This tells the response serializer which related resources to render.
138-
- `ISparseFieldSetCache`: This tells the response serializer which fields to render in the `attributes` and `relationships` objects.
139-
140-
You may also want to inject the singletons `IJsonApiOptions` (which contains settings such as default page size) and `IResourceGraph` (the JSON:API model of resources, attributes and relationships).
141-
142-
So, back to the topic of where to intercept. It helps to familiarize yourself with the [execution pipeline](~/internals/queries.md).
143-
Replacing at the service level is the simplest. But it means you'll need to read the parsed query string parameters and invoke
144-
all resource definition callbacks yourself. And you won't get change detection (HTTP 203 Not Modified).
145-
Take a look at [JsonApiResourceService](https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/src/JsonApiDotNetCore/Services/JsonApiResourceService.cs) to see what you're missing out on.
146-
147-
You'll get a lot more out of the box if replacing at the repository level instead. You don't need to apply options or analyze query strings.
148-
And most resource definition callbacks are handled.
149-
That's because the built-in resource service translates all JSON:API query aspects of the request into a database-agnostic data structure called `QueryLayer`.
150-
Now the hard part for you becomes reading that data structure and producing data access calls from that.
151-
If your data store provides a LINQ provider, you can probably reuse [QueryableBuilder](https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryableBuilder.cs),
152-
which drives the translation into [System.Linq.Expressions](https://learn.microsoft.com/dotnet/csharp/programming-guide/concepts/expression-trees/).
153-
Note however, that it also produces calls to `.Include("")`, which is an Entity Framework Core-specific extension method, so you'll need to
154-
[prevent that from happening](https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/src/JsonApiDotNetCore/Queries/QueryableBuilding/QueryLayerIncludeConverter.cs).
155-
156-
The example [here](https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/src/Examples/NoEntityFrameworkExample/Repositories/InMemoryResourceRepository.cs) compiles and executes
157-
the LINQ query against an in-memory list of resources.
158-
For [MongoDB](https://github.com/json-api-dotnet/JsonApiDotNetCore.MongoDb/blob/master/src/JsonApiDotNetCore.MongoDb/Repositories/MongoRepository.cs), we use the MongoDB LINQ provider.
159-
If there's no LINQ provider available, the example [here](https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/src/Examples/DapperExample/Repositories/DapperRepository.cs) may be of help,
160-
which produces SQL and uses [Dapper](https://github.com/DapperLib/Dapper) for data access.
161-
162-
> [!TIP]
163-
> [ExpressionTreeVisualizer](https://github.com/zspitz/ExpressionTreeVisualizer) is very helpful in trying to debug LINQ expression trees!
164-
165-
#### I love JsonApiDotNetCore! How can I support the team?
166-
The best way to express your gratitude is by starring our repository.
167-
This increases our leverage when asking for bug fixes in dependent projects, such as the .NET runtime and Entity Framework Core.
168-
You can also [sponsor](https://github.com/sponsors/json-api-dotnet) our project.
169-
Of course, a simple thank-you message in our [Gitter channel](https://gitter.im/json-api-dotnet-core/Lobby) is appreciated too!
170-
171-
If you'd like to do more: try things out, ask questions, create GitHub bug reports or feature requests, or upvote existing issues that are important to you.
172-
We welcome PRs, but keep in mind: The worst thing in the world is opening a PR that gets rejected after you've put a lot of effort into it.
173-
So for any non-trivial changes, please open an issue first to discuss your approach and ensure it fits the product vision.
174-
175-
#### Is there anything else I should be aware of?
176-
See [Common Pitfalls](~/usage/common-pitfalls.md).
1+
---
2+
redirect_url: ../usage/faq.html
3+
---

docs/getting-started/index.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Getting Started
2+
3+
The easiest way to get started is to run the [example project](https://github.com/json-api-dotnet/JsonApiDotNetCore/tree/master/src/Examples/GettingStarted).
4+
5+
Or create your first JsonApiDotNetCore project by following the steps described [here](https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/master/README.md#getting-started).

docs/getting-started/install.md

+3-24
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,3 @@
1-
# Installation
2-
3-
Click [here](https://www.nuget.org/packages/JsonApiDotNetCore/) for the latest NuGet version.
4-
5-
### CLI
6-
7-
```
8-
dotnet add package JsonApiDotNetCore
9-
```
10-
11-
### Visual Studio
12-
13-
```powershell
14-
Install-Package JsonApiDotNetCore
15-
```
16-
17-
### *.csproj
18-
19-
```xml
20-
<ItemGroup>
21-
<!-- Be sure to check NuGet for the latest version # -->
22-
<PackageReference Include="JsonApiDotNetCore" Version="4.0.0" />
23-
</ItemGroup>
24-
```
1+
---
2+
redirect_url: index.html
3+
---

0 commit comments

Comments
 (0)