1
- using dotnet_sample_app . Models ;
2
- using dotnet_sample_app . Repositories ;
1
+ using DotNetSampleApp . Models ;
3
2
using Fauna ;
4
3
using Fauna . Types ;
5
4
using Microsoft . AspNetCore . Mvc ;
6
5
7
- namespace dotnet_sample_app . Controllers ;
6
+ namespace DotNetSampleApp . Controllers ;
8
7
9
8
/// <summary>
10
9
/// Customers controller
@@ -14,21 +13,6 @@ namespace dotnet_sample_app.Controllers;
14
13
Route ( "/[controller]" ) ]
15
14
public class Customers ( Client client ) : ControllerBase
16
15
{
17
- private readonly CustomerDb _customerDb = client . DataContext < CustomerDb > ( ) ;
18
-
19
- /// <summary>
20
- /// Creates a new Customer
21
- /// </summary>
22
- /// <returns>Customer Details</returns>
23
- [ ProducesResponseType ( typeof ( Customer ) , StatusCodes . Status201Created ) ]
24
- [ ProducesResponseType ( StatusCodes . Status400BadRequest ) ]
25
- [ ProducesResponseType ( StatusCodes . Status500InternalServerError ) ]
26
- [ HttpPost ]
27
- public async Task < IActionResult > CreateCustomer ( CustomerRequest customer )
28
- {
29
- return StatusCode ( StatusCodes . Status201Created , await _customerDb . Create ( customer ) ) ;
30
- }
31
-
32
16
33
17
/// <summary>
34
18
/// Get Customer by ID
@@ -41,9 +25,43 @@ public async Task<IActionResult> CreateCustomer(CustomerRequest customer)
41
25
[ HttpGet ( "{customerId}" ) ]
42
26
public async Task < IActionResult > GetCustomer ( [ FromRoute ] string customerId )
43
27
{
44
- return Ok ( await _customerDb . Get ( customerId ) ) ;
28
+ // Get the Customer document by `id`, using the ! operator to assert that the document exists.
29
+ // If the document does not exist, Fauna will throw a document_not_found error.
30
+ //
31
+ // Use projection to only return the fields you need.
32
+ var query = Query . FQL ( $ """
33
+ let customer: Any = Customer.byId({ customerId } )!
34
+ { QuerySnippets . CustomerResponse ( ) }
35
+ """ ) ;
36
+
37
+ // Connect to fauna using the client. The query method accepts an FQL query
38
+ // as a parameter and a generic type parameter representing the return type.
39
+ var res = await client . QueryAsync < Customer > ( query ) ;
40
+ return Ok ( res . Data ) ;
45
41
}
46
42
43
+ /// <summary>
44
+ /// Creates a new Customer
45
+ /// </summary>
46
+ /// <returns>Customer Details</returns>
47
+ [ ProducesResponseType ( typeof ( Customer ) , StatusCodes . Status201Created ) ]
48
+ [ ProducesResponseType ( StatusCodes . Status400BadRequest ) ]
49
+ [ ProducesResponseType ( StatusCodes . Status500InternalServerError ) ]
50
+ [ HttpPost ]
51
+ public async Task < IActionResult > CreateCustomer ( CustomerRequest customer )
52
+ {
53
+ // Create a new Customer document with the provided fields.
54
+ var query = Query . FQL ( $ """
55
+ let customer: Any = Customer.create({ customer } )
56
+ { QuerySnippets . CustomerResponse ( ) }
57
+ """ ) ;
58
+
59
+ // Connect to fauna using the client. The query method accepts an FQL query
60
+ // as a parameter and a generic type parameter representing the return type.
61
+ var res = await client . QueryAsync < Customer > ( query ) ;
62
+ return StatusCode ( StatusCodes . Status201Created , res . Data ) ;
63
+ }
64
+
47
65
/// <summary>
48
66
/// Update Customer Details
49
67
/// </summary>
@@ -52,26 +70,75 @@ public async Task<IActionResult> GetCustomer([FromRoute] string customerId)
52
70
[ ProducesResponseType ( StatusCodes . Status400BadRequest ) ]
53
71
[ ProducesResponseType ( StatusCodes . Status404NotFound ) ]
54
72
[ ProducesResponseType ( StatusCodes . Status500InternalServerError ) ]
55
- [ HttpPatch ( "{customerId}" ) ]
73
+ [ HttpPost ( "{customerId}" ) ]
56
74
public async Task < IActionResult > UpdateCustomer (
57
75
[ FromRoute ] string customerId ,
58
76
CustomerRequest customer )
59
77
{
60
- return Ok ( await _customerDb . Update ( customerId , customer ) ) ;
78
+ // Get the Customer document by `customerId`, using the ! operator to assert that the document exists.
79
+ // If the document does not exist, Fauna will throw a document_not_found error.
80
+ //
81
+ // All unannotated fields and fields annotated with @FaunaField will be serialized, including
82
+ // those with `null` values. When an update is made to a field with a null value, that value of
83
+ // that field is unset on the document. Partial updates must be made with a dedicated class,
84
+ // anonymous class, or Map.
85
+ //
86
+ // Use projection to only return the fields you need.
87
+ var query = Query . FQL ( $ """
88
+ let customer: Any = Customer.byId({ customerId } )!.update({ customer } )
89
+ { QuerySnippets . CustomerResponse ( ) }
90
+ """ ) ;
91
+
92
+ // Connect to fauna using the client. The query method accepts an FQL query
93
+ // as a parameter and a generic type parameter representing the return type.
94
+ var res = await client . QueryAsync < Customer > ( query ) ;
95
+ return StatusCode ( StatusCodes . Status201Created , res . Data ) ;
61
96
}
62
97
63
98
/// <summary>
64
99
/// Return all orders for a specific customer.
65
100
/// </summary>
66
101
/// <param name="customerId">Customer ID</param>
102
+ /// <param name="afterToken">The after token for pagination.</param>
103
+ /// <param name="pageSize">A page size. Ignored if after token is provided.</param>
67
104
/// <returns>List of Orders.</returns>
68
105
[ ProducesResponseType ( typeof ( Page < Order > ) , StatusCodes . Status200OK ) ]
69
106
[ ProducesResponseType ( StatusCodes . Status404NotFound ) ]
70
107
[ ProducesResponseType ( StatusCodes . Status500InternalServerError ) ]
71
108
[ HttpGet ( "{customerId}/orders" ) ]
72
- public async Task < IActionResult > GetOrdersByCustomer ( [ FromRoute ] string customerId )
109
+ public async Task < IActionResult > GetOrdersByCustomer (
110
+ [ FromRoute ] string customerId ,
111
+ [ FromQuery ] string ? afterToken ,
112
+ [ FromQuery ] int pageSize = 10 )
73
113
{
74
- return Ok ( await _customerDb . GetOrdersByCustomer ( customerId ) ) ;
114
+ // The `afterToken` parameter contains a Fauna `after` cursor.
115
+ // `after` cursors may contain special characters, such as `.` or `+`).
116
+ // Make sure to URL encode the `afterToken` value to preserve these
117
+ // characters in URLs.
118
+ var query = ! string . IsNullOrEmpty ( afterToken )
119
+
120
+ // Paginate with the after token if it's present.
121
+ ? Query . FQL ( $ "Set.paginate({ afterToken } )")
122
+
123
+ // Define an FQL query to retrieve a page of orders for a given customer.
124
+ // Get the Customer document by id, using the ! operator to assert that the document exists.
125
+ // If the document does not exist, Fauna will throw a document_not_found error. We then
126
+ // use the Order.byCustomer index to retrieve all orders for that customer and map over
127
+ // the results to return only the fields we care about.
128
+ : Query . FQL ( @$ """
129
+ let customer: Any = Customer.byId({ customerId } )!
130
+ Order.byCustomer(customer).pageSize({ pageSize } ).map((order) => {{
131
+ let order: Any = order
132
+
133
+ // Return the order.
134
+ { QuerySnippets . OrderResponse ( ) }
135
+ }})
136
+ """ ) ;
137
+
138
+ // Connect to fauna using the client. The query method accepts an FQL query
139
+ // as a parameter and a generic type parameter representing the return type.
140
+ var result = await client . QueryAsync < Page < Order > > ( query ) ;
141
+ return Ok ( result . Data ) ;
75
142
}
76
143
77
144
@@ -86,7 +153,19 @@ public async Task<IActionResult> GetOrdersByCustomer([FromRoute] string customer
86
153
[ HttpPost ( "{customerId}/cart" ) ]
87
154
public async Task < IActionResult > CreateCart ( [ FromRoute ] string customerId )
88
155
{
89
- return Ok ( await _customerDb . GetOrCreateCart ( customerId ) ) ;
156
+ // Call our getOrCreateCart UDF to get the customer's cart. The function
157
+ // definition can be found 'server/schema/functions.fsl'.
158
+ var query = Query . FQL ( $ """
159
+ let order: Any = getOrCreateCart({ customerId } )
160
+
161
+ // Return the cart.
162
+ { QuerySnippets . OrderResponse ( ) }
163
+ """ ) ;
164
+
165
+ // Connect to fauna using the client. The query method accepts an FQL query
166
+ // as a parameter and a generic type parameter representing the return type.
167
+ var res = await client . QueryAsync < Order > ( query ) ;
168
+ return StatusCode ( StatusCodes . Status201Created , res . Data ) ;
90
169
}
91
170
92
171
/// <summary>
@@ -101,7 +180,20 @@ public async Task<IActionResult> CreateCart([FromRoute] string customerId)
101
180
[ HttpPost ( "{customerId}/cart/item" ) ]
102
181
public async Task < IActionResult > AddItemToCart ( [ FromRoute ] string customerId , AddItemToCartRequest item )
103
182
{
104
- return Ok ( await _customerDb . AddItemToCart ( customerId , item ) ) ;
183
+ // Call our createOrUpdateCartItem UDF to add an item to the customer's cart. The function
184
+ // definition can be found 'server/schema/functions.fsl'.
185
+ var query = Query . FQL ( $ """
186
+ let req = { item }
187
+ let order: Any = createOrUpdateCartItem({ customerId } , req.productName, req.quantity)
188
+
189
+ // Return the cart as an OrderResponse object.
190
+ { QuerySnippets . OrderResponse ( ) }
191
+ """ ) ;
192
+
193
+ // Connect to fauna using the client. The query method accepts an FQL query
194
+ // as a parameter and a generic type parameter representing the return type.
195
+ var res = await client . QueryAsync < Order > ( query ) ;
196
+ return StatusCode ( StatusCodes . Status201Created , res . Data ) ;
105
197
}
106
198
107
199
/// <summary>
@@ -115,22 +207,18 @@ public async Task<IActionResult> AddItemToCart([FromRoute] string customerId, Ad
115
207
[ HttpGet ( "{customerId}/cart" ) ]
116
208
public async Task < IActionResult > GetCart ( [ FromRoute ] string customerId )
117
209
{
118
- return Ok ( await _customerDb . GetOrCreateCart ( customerId ) ) ;
119
- }
120
-
121
- /// <summary>
122
- /// Delete Customer
123
- /// </summary>
124
- /// <param name="customerId">Customer ID</param>
125
- /// <returns>No Content</returns>
126
- [ ProducesResponseType ( typeof ( Cart ) , StatusCodes . Status200OK ) ]
127
- [ ProducesResponseType ( StatusCodes . Status400BadRequest ) ]
128
- [ ProducesResponseType ( StatusCodes . Status404NotFound ) ]
129
- [ ProducesResponseType ( StatusCodes . Status500InternalServerError ) ]
130
- [ HttpDelete ( "{customerId}" ) ]
131
- public async Task < IActionResult > DeleteCustomer ( [ FromRoute ] string customerId )
132
- {
133
- await _customerDb . Delete ( customerId ) ;
134
- return NoContent ( ) ;
210
+ // Get the customer's cart by id, using the ! operator to assert that the document exists.
211
+ // If the document does not exist, Fauna will throw a document_not_found error.
212
+ var query = Query . FQL ( $ """
213
+ let order: Any = Customer.byId({ customerId } )!.cart
214
+
215
+ // Return the cart as an OrderResponse object.
216
+ { QuerySnippets . OrderResponse ( ) }
217
+ """ ) ;
218
+
219
+ // Connect to fauna using the client. The query method accepts an FQL query
220
+ // as a parameter and a generic type parameter representing the return type.
221
+ var res = await client . QueryAsync < Order > ( query ) ;
222
+ return StatusCode ( StatusCodes . Status201Created , res . Data ) ;
135
223
}
136
- }
224
+ }
0 commit comments