You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/advanced/graph-action-results.md
+8-4Lines changed: 8 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -40,7 +40,7 @@ public class BakeryController : Controller
40
40
41
41
You can either return the data itself or some alternate `IActionResult` to tell MVC how to render a response.
42
42
43
-
Common Action Results for MVC:
43
+
Some common ASP.NET MVC action results:
44
44
45
45
-`this.Ok()` : Everything worked fine, return status 200.
46
46
-`this.NotFound()` : The item doesn't exist, return status 404.
@@ -49,7 +49,7 @@ Common Action Results for MVC:
49
49
50
50
This works the same way in GraphQL ASP.NET. The available actions are slightly different (GraphQL won't stream files) but the usage is the same. You can even write your own action results.
51
51
52
-
## Common Graph Action Results
52
+
## Common Action Results
53
53
54
54
Instead of `IActionResult` we use `IGraphActionResult` from a controller action method. Both [directives](../directives) and controller [action methods](../controllers/actions) can return action results.
55
55
@@ -62,9 +62,13 @@ Built in Controller Action Methods:
62
62
-`this.BadRequest()`: Commonly used in conjunction with `this.ModelState`. This result indicates the data supplied to the method is not valid for the operation. If given the model state collection an error for each validation error is rendered.
63
63
-`this.InternalServerError()`: Indicates an unintended error, such as an exception occurred. The supplied message will be added to the response and no child fields will be resolved.
64
64
65
-
[Directives](../directives) have one Additional Action Result:
65
+
## Directive Action Results
66
+
[Directives](../directives) have two built in Action Results:
66
67
67
-
-`this.Cancel()`: When returned as part of a method that executes before field resolution, this action will cancel the field execution pipeline. No error is returned, but the field is dropped from the request.
68
+
-`this.Ok()`: Indicates that the directive completed its expected operation successfully and query processing can continue.
69
+
-`this.Cancel()`: Indicates that the directive did NOT complete its operation successfully.
70
+
- If this is a type system directive, the schema will fail to complete and the server will not start.
71
+
- If this is an execution directive, the query will be abandoned and the user will receive an error message.
Copy file name to clipboardExpand all lines: docs/controllers/actions.md
+51-4Lines changed: 51 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -418,7 +418,7 @@ query {
418
418
</div>
419
419
<br/>
420
420
421
-
Note that there is a difference between "nullable" and "not required". If we have a nullable int as an input parameter, without a default value we still have to pass it to the field, even if we pass it as null.
421
+
Note that there is a difference between "nullable" and "not required". If we have a nullable int as an input parameter, without a default value we still have to pass it to the field, even if we pass it as null just like if we were to invoke the method from our C# code.
422
422
423
423
<divclass="sideBySideCode hljs">
424
424
<div>
@@ -491,6 +491,53 @@ query {
491
491
</div>
492
492
</div>
493
493
494
+
### Working With Lists
495
+
496
+
When constructing a set of items as an argument to an action method, GraphQL will instantiate a `List<T>` and fill it with the appropriate data, be that another list, another input object, a scalar etc. While you can declare an array (e.g. `Donut[]`, `int[]` etc.) as your list structure for an input argument, graphql has to rebuild its internal representation as an array (or nested arrays) to meet the requirements of your method. In some cases, especially with nested lists, this results in a linear increase in processing time. It is recommended to use `IEnumerable<T>` or `IList<T>` to avoid this performance bottleneck when sending lots of items as input data.
497
+
498
+
This example shows various ways of accepting collections of data as inputs to controller actions.
You might be tempted to use a dictionary as a parameter to accept arbitrary key value pairs into your methods. GraphQL will reject it and throw a declaration exception when your schema is created:
@@ -501,7 +548,7 @@ You might be tempted to use a dictionary as a parameter to accept arbitrary key
501
548
```csharp
502
549
publicclassBakeryController : GraphController
503
550
{
504
-
// ERROR, a GraphDeclarationException
551
+
// ERROR, a GraphTypeDeclarationException
505
552
// will be thrown.
506
553
[QueryRoot]
507
554
public IEnumerable<Donut>
@@ -515,7 +562,7 @@ public class BakeryController : GraphController
515
562
516
563
```javascript
517
564
query {
518
-
searchDonuts(
565
+
searchDonuts(searchParams:
519
566
name:"jelly*"
520
567
filled:true
521
568
dayOld:false){
@@ -529,7 +576,7 @@ query {
529
576
</div>
530
577
<br/>
531
578
532
-
At runtime, GraphQL will try to validate every parameter passed on a query against the type expression it has stored in the target schema. No where have we we declared `filled` to be a boolean or `name` to be a string.
579
+
At runtime, GraphQL will try to validate every parameter passed on a query against the type expression it has stored in the target schema. No where have we declared an argument`filled` to be a boolean or `name` to be a string.
533
580
534
581
One might think, well it should be passed as an object reference to the dictionary parameter:
`INPUT_OBJECT` graph types function in much the same way as [object graph types](./objects) do.
8
-
While GraphQL is doing its discovery of controllers and graph types, whenever it comes across a class used as a parameter to a method it will attempt to generate the appropriate input type definition.
7
+
`INPUT_OBJECT` graph types (a.k.a. input objects) represent complex data supplied to arguments on fields or directives. Anytime you want to pass more data than a single string or a number, perhaps an Address or a new Employee, you use an INPUT_OBJECT to represent that entity in GraphQL. When the system scans your controllers, if it comes across a class used as a parameter to a method it will attempt to generate the appropriate input type definition to represent that class.
9
8
10
-
The rules surrounding naming, field declarations, exclusions, use of `[GraphSkip]` etc. apply to input objects but with a few key differences.
9
+
The rules surrounding naming, field declarations, exclusions, use of `[GraphSkip]` etc. apply to input objects but with a few key differences:
11
10
12
-
By Default:
13
-
14
-
- An input object is named the same as its `class` name, prefixed with `Input_`
15
-
- i.e. `Input_Donut`, `Input_Employee`
16
-
- All public properties with a `get` and `set` statement will be included.
17
-
- The return type of the property must be an acceptable type or it will be skipped
11
+
- Unless overridden, an input object is named the same as its class name, prefixed with `Input_` (e.g. `Input_Address`, `Input_Employee`)
12
+
- Only public properties with a `get` and `set` will be included.
13
+
- Property return types cannot be `Task<T>`, an `interface` and cannot implement `IGraphUnionProxy` or `IGraphActionResult`. Such properties are always skipped.
18
14
- Methods are always skipped.
19
15
20
-
## Names
16
+
## Customized Type Names
21
17
22
-
Input object types can be given customized names, just like with object types, using the `[GraphType]` attribute.
18
+
Input objects can be given customized names, just like with object types, using the `[GraphType]` attribute.
23
19
24
20
<divclass="sideBySideCode hljs">
25
21
<div>
@@ -53,6 +49,8 @@ input NewDonutModel {
53
49
</div>
54
50
<br/>
55
51
52
+
>Not the specific callout to `InputName` in the attribution.
53
+
56
54
## Use an Empty Constructor
57
55
58
56
When GraphQL executes a query it will attempt to create an instance of your input object then assign the key/value pairs received on the query to the properties. In order to do the initial instantiation it requires a public parameterless constructor to do so.
@@ -78,7 +76,7 @@ public class DonutModel
78
76
}
79
77
```
80
78
81
-
Because of this restriction it can be helpful to separate your classes between "input" and "output" types much is the same way we do with `ViewModel` vs. `BindingModel` objects in MVC. This is optional, mix and match as needed by your use case.
79
+
Because of this restriction it can be helpful to separate your classes between "input" and "output" types much is the same way we do with `ViewModel` vs. `BindingModel` objects with REST queries in ASP.NET. This is optional, mix and match as needed by your use case.
82
80
83
81
## Properties Must Have a Public Setter
84
82
@@ -128,7 +126,8 @@ While its possible to have methods be exposed as resolvable fields on regular `O
Add `[Required]` (from System.ComponentModel) to any property to force a user to supply the field in a query document.
162
162
163
-
When constructing a set of items as an input value, GraphQL will instantiate a `List<T>` and fill it with the appropriate data, be that another list, another input object or a scalar. While you can declare a regular array (e.g. `Donut[]`, `int[]` etc.) as your list structure for an input argument, graphql has to rebuild its internal list structure as an array (or nested arrays) to meet the requirements of your method. In some cases, especially with nested lists, this results in a linear increase in processing time. It is recommended to use `IEnumerable<T>` or `IList<T>` to avoid this performance bottleneck when sending a lot of items as input arguments.
163
+
Any non-required field will automatically be assigned a default value if not supplied. This default value is equivilant to the property value of the object when its instantiated via its public, parameterless constructor.
164
164
165
-
This example shows various ways of accepting collections of data as inputs to controller actions.
Any default value declared for an input field must be coercible by its target graph type in the target schema.
297
+
298
+
### Enum Values
200
299
201
-
publicclassDonutCollection
300
+
Take a look at this example of an enum and input object:
301
+
302
+
```csharp
303
+
publicclassDonut
202
304
{
203
-
publicList<Donut> Donuts { get; set; }
305
+
publicstringName{ get; set; }
306
+
publicDonutFlavorFlavor { get; set; }
204
307
}
205
308
309
+
publicenumDonutFlavor
310
+
{
311
+
[GraphSkip]
312
+
Vanilla=0,
313
+
Chocolate=1,
314
+
315
+
}
206
316
```
317
+
318
+
When `Donut` is instantiated the value of Flavor will be `Vanilla` because
319
+
thats the default value (0) of the enum's underlying data type (int). However, the enum value `Vanilla` is marked as being skipped in the schema.
320
+
321
+
Because of this mismatch, a `GraphTypeDeclarationException` will be thrown when the introspection data for your schema is built. As a result, the server will fail to start until the problem is corrected.
322
+
323
+
> Enum values used for the default value of input object properties MUST also exist as values in the schema or an exception will be thrown.
0 commit comments