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: README.md
+61-46Lines changed: 61 additions & 46 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -24,18 +24,9 @@ The WebResultEndpoint and ServiceResultEndpoint abstractions are a structured ap
24
24
- Supports auto discovery and registration.
25
25
- Has built-in validation support with [FluentValidation](https://github.com/FluentValidation/FluentValidation). If a validator is registered for request model, request is automatically validated before being handled.
26
26
- Supports constructor dependency injection in endpoint implementations.
27
+
- Enforces response model type safety in request handlers.
27
28
- Abstracts the logic for converting business results into HTTP responses.
28
29
29
-
## Performance
30
-
31
-
WebResultEndpoints have a slight overhead (3-4%) over regular Minimal Apis on request/sec metric under load tests with 100 virtual users.
32
-
33
-
MinimalEndpoints perform about same as regular Minimal Apis.
34
-
35
-
The web apis called for tests, perform only in-process operations like resolving dependency, validating input, calling local methods with no network or disk I/O.
36
-
37
-
See [test results](./samples/BenchmarkWebApi/BenchmarkFiles/inprocess_benchmark_results.txt) under [BenchmarkFiles](https://github.com/modabas/ModEndpoints/tree/main/samples/BenchmarkWebApi/BenchmarkFiles) folder of BenchmarkWebApi project for detailed results and test scripts.
38
-
39
30
## Workflow
40
31
41
32
An endpoint must implement two virtual methods: Configure and HandleAsync.
@@ -46,21 +37,11 @@ The 'Configure' method is called at application startup to define routes and ass
46
37
47
38
### Request Handling:
48
39
49
-
The request is processed in 'HandleAsync' method which returns a [result](https://github.com/modabas/ModResults). This result is handled differently for each endpoint type before being sent to client.
50
-
51
-
## Endpoint Types
52
-
53
-
WebResultEndpoint and ServiceResultEndpoint, the two abstract endpoint bases, differ only in converting business results into HTTP responses before sending response to client. Other features described previously are common for both of them.
54
-
55
-
### WebResultEndpoint
56
-
57
-
A WebResultEndpoint implementation, after handling request, maps the [result](https://github.com/modabas/ModResults) of HandleAsync method to an IResult depending on the result type, state and failure type (if any). Mapping behaviour can be modified or replaced with a custom one.
58
-
59
-
### ServiceResultEndpoint
40
+
The request is processed in 'HandleAsync' method which returns a strongly typed [business result](https://github.com/modabas/ModResults). This business result is handled differently for each endpoint type before being sent to client.
60
41
61
-
A ServiceResultEndpoint implementation, after handling request, encapsulates the [result](https://github.com/modabas/ModResults) of HandleAsync method in a HTTP 200 IResult (Minimal Api response type) and sends to client. This behaviour makes ServiceResultEndpoints more suitable for internal services, where clients are aware of Result or Result<TValue> implementations.
42
+
## Quickstart
62
43
63
-
## Service Registration
44
+
###Service Registration
64
45
65
46
Use AddModEndpointsFromAssembly extension method to register all endpoints defined in an assembly.
66
47
@@ -80,14 +61,12 @@ app.MapModEndpoints();
80
61
app.Run();
81
62
```
82
63
83
-
##Usage
64
+
### A basic sample: A GET endpoint with empty request
84
65
85
66
Configuration of each endpoint implementation starts with calling one of the MapGet, MapPost, MapPut, MapDelete and MapPatch methods with a route pattern string. The return from any of these methods, a RouteHandlerBuilder instance, can be used to further customize the endpoint like a regular Minimal Api.
86
67
87
68
Have a look at [ShowcaseWebApi](https://github.com/modabas/ModEndpoints/tree/main/samples/ShowcaseWebApi) project for various kinds of endpoint implementations and configurations.
88
69
89
-
### A basic sample: An endpoint with empty request and configured for GET
90
-
91
70
This sample demonstrates a GET endpoint with basic configuration and without any request model binding.
92
71
93
72
```csharp
@@ -224,27 +203,9 @@ internal class UploadBook
224
203
}
225
204
```
226
205
227
-
### Response mapping for WebResultEndpoint
228
-
229
-
Default mapping behaviour is:
230
-
- For an [endpoint without a response model](./samples/ShowcaseWebApi/Features/Books/DeleteBook.cs), return HTTP 204 No Content.
231
-
- For an endpoint with a response model, return HTTP 200 OK with response model as body.
232
-
233
-
For both cases, response HTTP status code can be changed by [calling 'Produces' extension method during configuration](./samples/ShowcaseWebApi/Features/Books/CreateBook.cs) with one of the following status codes:
234
-
- StatusCodes.Status200OK,
235
-
- StatusCodes.Status201Created,
236
-
- StatusCodes.Status202Accepted,
237
-
- StatusCodes.Status204NoContent,
238
-
- StatusCodes.Status205ResetContent
239
-
240
-
For implementing custom response mapping for an endpoint:
241
-
- Create an IResultToResponseMapper implementation,
242
-
- Add it to dependency injection service collection with a string key during app startup,
243
-
- Apply ResultToResponseMapper attribute to endpoint classes that will be using custom mapper. Use service registration string key as Name property of attribute.
244
-
245
206
### Route groups
246
207
247
-
By default, all endpoints are mapped under root route group. It is possible to define route groups similar to using 'MapGroup' extension method and to map Minimal Apis under said group. Since endpoints are configured by endpoint basis in the 'Configure' method of each endpoint, the approach is a little different than regular Minimal Apis, but these are still Minimal Api route groups and can be configured by any extension method of RouteGroupConfigurator. Route groups are also subject to auto discovery and registration like endpoints.
208
+
By default, all endpoints are mapped under root route group. It is possible to define route groups similar to using 'MapGroup' extension method and to map Minimal Apis under said group. Since endpoints are configured by endpoint basis in the 'Configure' method of each endpoint, the approach is a little different than regular Minimal Apis, but these are still Minimal Api route groups and can be configured by any extension method of RouteGroupConfigurator. Route groups are also subject to auto discovery and registration, similar to endpoints.
248
209
249
210
-[Create a route group implementation](./samples/ShowcaseWebApi/Features/FeaturesRouteGroup.cs) by inheriting RouteGroupConfigurator and implementing 'Configure' method,
250
211
- Configuration of each route group implementation starts with calling MapGroup method with a route pattern prefix. The return of 'MapGroup' method, a RouteGroupBuilder instance, can be used to further customize the route group like a regular Minimal Api route group.
@@ -299,4 +260,58 @@ internal class CreateBook(ServiceDbContext db, ILocationStore location)
299
260
//Handle...
300
261
}
301
262
}
302
-
```
263
+
```
264
+
265
+
## Performance
266
+
267
+
WebResultEndpoints have a slight overhead (3-4%) over regular Minimal Apis on request/sec metric under load tests with 100 virtual users.
268
+
269
+
MinimalEndpoints perform about same as regular Minimal Apis.
270
+
271
+
The web apis called for tests, perform only in-process operations like resolving dependency, validating input, calling local methods with no network or disk I/O.
272
+
273
+
See [test results](./samples/BenchmarkWebApi/BenchmarkFiles/inprocess_benchmark_results.txt) under [BenchmarkFiles](https://github.com/modabas/ModEndpoints/tree/main/samples/BenchmarkWebApi/BenchmarkFiles) folder of BenchmarkWebApi project for detailed results and test scripts.
274
+
275
+
## Endpoint Types
276
+
277
+
WebResultEndpoint and ServiceResultEndpoint, the two abstract endpoint bases, have a 'HandleAsync' method which returns a strongly typed [business result](https://github.com/modabas/ModResults).
278
+
279
+
They differ only in converting these business results into HTTP responses before sending response to client. Other features described previously are common for both of them.
280
+
281
+
Each type of andpoint has various implementations that accept a request model or not, that has a response model or not.
282
+
283
+
### ServiceResultEndpoint
284
+
285
+
A ServiceResultEndpoint implementation, after handling request, encapsulates the [business result](https://github.com/modabas/ModResults) of HandleAsync method in a HTTP 200 Minimal Api IResult and sends to client. The [business result](https://github.com/modabas/ModResults) returned may be in Ok or Failed state. This behaviour makes ServiceResultEndpoints more suitable for internal services, where clients are aware of Result or Result<TValue> implementations.
286
+
287
+
- ServiceResultEndpoint<TRequest, TResultValue>: Has a request model, supports request validation and returns a [Result<TResultValue>](https://github.com/modabas/ModResults) within HTTP 200 IResult.
288
+
- ServiceResultEndpoint<TRequest>: Has a request model, supports request validation and returns a [Result](https://github.com/modabas/ModResults) within HTTP 200 IResult.
289
+
- ServiceResultEndpointWithEmptyRequest<TResultValue>: Doesn't have a request model and returns a [Result<TResultValue>](https://github.com/modabas/ModResults) within HTTP 200 IResult.
290
+
- ServiceResultEndpointWithEmptyRequest: Doesn't have a request model and returns a [Result](https://github.com/modabas/ModResults) within HTTP 200 IResult.
291
+
292
+
### WebResultEndpoint
293
+
294
+
A WebResultEndpoint implementation, after handling request, maps the [business result](https://github.com/modabas/ModResults) of HandleAsync method to an IResult depending on the result type, state and failure type (if any). Mapping behaviour can be modified or replaced with a custom one.
295
+
296
+
- WebResultEndpoint<TRequest, TResultValue>: Has a request model, supports request validation and returns a response model as body of Minimal Api IResult if successful.
297
+
- WebResultEndpoint<TRequest>: Has a request model, supports request validation, doesn't have a response model to return within Minimal Api IResult.
298
+
- WebResultEndpointWithEmptyRequest<TResultValue>: Doesn't have a request model and returns a response model as body of Minimal Api IResult if successful.
299
+
- WebResultEndpointWithEmptyRequest: Doesn't have a request model, doesn't have a response model to return within Minimal Api IResult.
300
+
301
+
When result returned from handler method is in Ok state, default WebResultEndpoint response mapping behaviour is:
302
+
- For an [endpoint without a response model](./samples/ShowcaseWebApi/Features/Books/DeleteBook.cs), return HTTP 204 No Content.
303
+
- For an endpoint with a response model, return HTTP 200 OK with response model as body.
304
+
305
+
Response HTTP success status code can be configured by [calling 'Produces' extension method during configuration](./samples/ShowcaseWebApi/Features/Books/CreateBook.cs) of endpoint with one of the following status codes:
306
+
- StatusCodes.Status200OK,
307
+
- StatusCodes.Status201Created,
308
+
- StatusCodes.Status202Accepted,
309
+
- StatusCodes.Status204NoContent,
310
+
- StatusCodes.Status205ResetContent
311
+
312
+
When result returned from handler method is in Failed state, default WebResultEndpoint response mapping will create a Minimal Api IResult with a 4XX or 5XX HTTP Status Code depending on the FailureType of [business result](https://github.com/modabas/ModResults).
313
+
314
+
It is also possible to implement a custom response mapping behaviour for a WebResultEndpoint. To do so:
315
+
- Create an IResultToResponseMapper implementation,
316
+
- Add it to dependency injection service collection with a string key during app startup,
317
+
- Apply ResultToResponseMapper attribute to endpoint classes that will be using custom mapper. Use service registration string key as Name property of attribute.
0 commit comments