|
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 | +--- |
0 commit comments