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
+15-9Lines changed: 15 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -60,13 +60,13 @@ For version 3.0 we implemented a new way to define the base classes using "fluen
60
60
61
61
[7. Related Articles](#7-related-articles)
62
62
63
-
[8. Videos and Podcasts](#8-videos-podcasts)
63
+
[8. Videos and Podcasts](#8-videos-and-podcasts)
64
64
65
-
[9. Related / Similar Projects](#8-related--similar-projects)
65
+
[9. Related / Similar Projects](#9-related--similar-projects)
66
66
67
-
[10. Projects Using ApiEndpoints](#9-projects-using-apiendpoints)
67
+
[10. Projects Using ApiEndpoints](#10-projects-using-apiendpoints)
68
68
69
-
[11. Success Stories and Testimonials](#10-success-stories-and-testimonials)
69
+
[11. Success Stories and Testimonials](#11-success-stories-and-testimonials)
70
70
71
71
## 1. Motivation
72
72
@@ -97,7 +97,7 @@ Most REST APIs have groups of endpoints for a given resource. In Controller-base
97
97
I'll look to add detailed documentation in the future but for now here's all you need to get started (you can also check the sample project):
98
98
99
99
1. Add the [Ardalis.ApiEndpoints NuGet package](https://www.nuget.org/packages/Ardalis.ApiEndpoints/) to your ASP.NET Core web project.
100
-
2. Create Endpoint classes by inheriting from either `BaseEndpoint<TRequest,TResponse>` (for endpoints that accept a model as input) or `BaseEndpoint<TResponse>` (for endpoints that simply return a response). For example, a POST endpoint that creates a resource and then returns the newly created record would use the version that includes both a Request and a Response. A GET endpoint that just returns a list of records and doesn't accept any arguments would use the second version.
100
+
2. Create Endpoint classes by inheriting from either `EndpointBaseSync<TRequest,TResponse>` (for endpoints that accept a model as input) or `EndpointBaseSync<TResponse>` (for endpoints that simply return a response). For example, a POST endpoint that creates a resource and then returns the newly created record would use the version that includes both a Request and a Response. A GET endpoint that just returns a list of records and doesn't accept any arguments would use the second version.
101
101
3. Implement the base class's abstract `Handle()` method.
102
102
4. Make sure to add a `[HttpGet]` or similar attribute to your `Handle()` method, specifying its route.
103
103
5. Define your `TResponse` type in a file in the same folder as its corresponding endpoint (or in the same file if you prefer).
@@ -197,7 +197,7 @@ Below are what I expect will be some common questions:
197
197
198
198
### How do I use shared routing conventions?
199
199
200
-
~~If you want to create a common route template for all or some subset of your Endpoints, simply create a BaseEndpoint of your own that inherits from `Ardalis.Api.Endpoints.BaseEndpoint` and add a `[Route]` attribute to it.~~
200
+
If you want to create a common route template for all or some subset of your Endpoints, simply create a EndpointBaseSync of your own that inherits from `Ardalis.Api.Endpoints.EndpointBaseSync` and add a `[Route]` attribute to it.
201
201
202
202
After refactoring to use the fluent generics pattern, there is no longer a way to use a base class for a default route. Instead, you should define your routes as constants which you can store in a central file or in each Request DTO (the sample shows this approach).
203
203
@@ -255,9 +255,15 @@ For more information, take a look at [this discussion](https://github.com/ardali
255
255
There's an example in the [sample app](https://github.com/ardalis/ApiEndpoints/blob/main/sample/SampleEndpointApp/Endpoints/Authors/ListJsonFile.cs) that shows how to set this up and return a File actionresult. For the base type, just use the `WithoutResponse` option and in the endpoint handler return `File()`.
256
256
257
257
### How can I use model binding to pull values from multiple places, like `[FromRoute]`, `[FromBody]`, etc.?
258
-
258
+
#172
259
259
The base endpoints only expose a single model type which is used on the Handle method, so you can't easily add additional parameters to the Handle method. However, you can put as many properties on the associated Request DTO as you want, and model binding allows you to set the same attributes per property as you would have set per parameter on the action method. See [Model Binding Docs](https://docs.microsoft.com/en-us/aspnet/core/mvc/models/model-binding) and [discussion here in issue 42](https://github.com/ardalis/ApiEndpoints/issues/42)
260
260
261
+
### How can I use streaming from server to client?
262
+
There's an example in the [sample app](https://github.com/ardalis/ApiEndpoints/blob/main/sample/SampleEndpointApp/Endpoints/Authors/Stream.cs) that shows how to set this up and return an `IAsyncEnumerable<T>`. For the base type, just use the `WithAsyncEnumerableResult<T>` option and in the endpoint handler yeld return after awaiting your async code.
263
+
264
+
> Note: streaming with IAsyncEnumerable does not work within Swagger Ui. Use curl to test this functionality
The following are some things I'd like to add to the project/package.
@@ -268,15 +274,15 @@ Visual Studio and/or CLI item templates would make it much easier to create Endp
268
274
269
275
### Route Conventions
270
276
271
-
One thing that Controllers do have is built-in support in the framework to use their name in routes (e.g. "/[controller]/{id?}"). Currently in the sample app routes are hard-coded strings. It would be nice if there were an easy way to use a convention based on foldername or namespace or something (using foldername would align with how Razor Pages routing works).
277
+
One thing that Controllers do have is built-in support in the framework to use their name in routes (e.g. "`[controller]/{id?}`"). Currently in the sample app routes are hard-coded strings. It would be nice if there were an easy way to use a convention based on foldername or namespace or something (using foldername would align with how Razor Pages routing works).
272
278
273
279
## 7. Related Articles
274
280
275
281
- [Moving from Controllers and Actions to Endpoints](https://ardalis.com/moving-from-controllers-and-actions-to-endpoints-with-mediatr)
276
282
- [Decoupling Controllers with ApiEndpoints](https://betweentwobrackets.dev/posts/2020/09/decoupling-controllers-with-apiendpoints/)
Copy file name to clipboardExpand all lines: docs/index.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,7 +14,7 @@ When working with ASP.NET Core API Endpoints your project won't need any Control
14
14
15
15
Most REST APIs have groups of endpoints for a given resource. In Controller-based projects you would have a controller per resource. When using API Endpoints you can simply create a folder per resource, just as you would use folders to group related pages in Razor Pages.
16
16
17
-
Instead of Model-View-Controller (MVC) the pattern becomes Request-EndPoint-Response(REPR). The REPR (reaper) pattern is much simpler and groups everything that has to do with a particular API endpoint together. It follows SOLID principles, in particular SRP and OCP. It also has all the benefits of feature folders and better follows the Common Closure Principle by grouping together things that change together.
17
+
Instead of Model-View-Controller (MVC) the pattern becomes Request-EndPoint-Response(REPR). The REPR (reaper) pattern is much simpler and groups everything that has to do with a particular API endpoint together. It follows SOLID principles, in particular [SRP](https://en.wikipedia.org/wiki/Single-responsibility_principle) and [OCP](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle). It also has all the benefits of feature folders and better follows the Common Closure Principle by grouping together things that change together.
Copy file name to clipboardExpand all lines: sample/SampleEndpointApp/README.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -24,4 +24,4 @@ dotnet ef database update
24
24
25
25
## Duplicate Code in Endpoints
26
26
27
-
If the duplicate dependency code in the endpoints bothers you, you can avoid it easily by creating your own `BaseAppEndpoint` classes that inherit from `BaseEndpoint`. These can expose as properties any common dependencies like loggers, mappers, or generic repositories, and then use an IOC container's property injection feature to ensure they're always populated when the endpoint is created.
27
+
If the duplicate dependency code in the endpoints bothers you, you can avoid it easily by creating your own `AppEndpointBaseSync` classes that inherit from `EndpointBaseSync`. These can expose as properties any common dependencies like loggers, mappers, or generic repositories, and then use an IOC container's property injection feature to ensure they're always populated when the endpoint is created.
0 commit comments