Skip to content

Commit fa0add1

Browse files
authored
Merge pull request #85 from marcominerva/develop
Improve documentation and code clarity in README.md
2 parents 3c2daa9 + dc67c3b commit fa0add1

File tree

10 files changed

+209
-125
lines changed

10 files changed

+209
-125
lines changed

.github/copilot-instructions.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
## General
2+
3+
- Make only high confidence suggestions when reviewing code changes.
4+
- Always use the latest version C#, currently C# 13 features.
5+
- Write code that is clean, maintainable, and easy to understand.
6+
- Only add comments rarely to explain why a non-intuitive solution was used. The code should be self-explanatory otherwise.
7+
- Don't add the UTF-8 BOM to files unless they have non-ASCII characters.
8+
- Never change global.json unless explicitly asked to.
9+
- Never change package.json or package-lock.json files unless explicitly asked to.
10+
- Never change NuGet.config files unless explicitly asked to.
11+
12+
## Code Style
13+
14+
### Formatting
15+
16+
- Apply code-formatting style defined in `.editorconfig`.
17+
- Use primary constructors where applicable.
18+
- Prefer file-scoped namespace declarations and single-line using directives.
19+
- Insert a newline before the opening curly brace of any code block (e.g., after `if`, `for`, `while`, `foreach`, `using`, `try`, etc.).
20+
- Ensure that the final return statement of a method is on its own line.
21+
- Use pattern matching and switch expressions wherever possible.
22+
- Prefer using collection expressions when possible
23+
- Use `is` pattern matching instead of `as` and null checks
24+
- Use `nameof` instead of string literals when referring to member names.
25+
- Prefer `?.` if applicable (e.g. `scope?.Dispose()`).
26+
- Use `ObjectDisposedException.ThrowIf` where applicable.
27+
- Use `ArgumentNullException.ThrowIfNull` to validate input paramters.
28+
- If you add new code files, ensure they are listed in the csproj file (if other files in that folder are listed there) so they build.
29+
30+
### Nullable Reference Types
31+
32+
- Declare variables non-nullable, and check for `null` at entry points.
33+
- Always use `is null` or `is not null` instead of `== null` or `!= null`.
34+
- Trust the C# null annotations and don't add null checks when the type system says a value cannot be null.
35+
36+
## Architecture and Design Patterns
37+
38+
### Asynchronous Programming
39+
40+
- Provide both synchronous and asynchronous versions of methods where appropriate.
41+
- Use the `Async` suffix for asynchronous methods.
42+
- Return `Task` or `ValueTask` from asynchronous methods.
43+
- Use `CancellationToken` parameters to support cancellation.
44+
- Avoid async void methods except for event handlers.
45+
- Call `ConfigureAwait(false)` on awaited calls to avoid deadlocks.
46+
47+
### Error Handling
48+
49+
- Use appropriate exception types.
50+
- Include helpful error messages.
51+
- Avoid catching exceptions without rethrowing them.
52+
53+
### Performance Considerations
54+
55+
- Be mindful of performance implications, especially for database operations.
56+
- Avoid unnecessary allocations.
57+
- Consider using more efficient code that is expected to be on the hot path, even if it is less readable.
58+
59+
### Implementation Guidelines
60+
61+
- Write code that is secure by default. Avoid exposing potentially private or sensitive data.
62+
- Make code NativeAOT compatible when possible. This means avoiding dynamic code generation, reflection, and other features that are not compatible. with NativeAOT. If not possible, mark the code with an appropriate annotation or throw an exception.
63+
64+
## Documentation
65+
66+
- Include XML documentation for all public APIs. Mention the purpose, intent, and 'the why' of the code, so developers unfamiliar with the project can better understand it. If comments already exist, update them to meet the before mentioned criteria if needed. Use the full syntax of XML Doc Comments to make them as awesome as possible including references to types. Don't add any documentation that is obvious for even novice developers by reading the code.
67+
- Add proper `<remarks>` tags with links to relevant documentation where helpful.
68+
- For keywords like `null`, `true` or `false` use `<see langword="*" />` tags.
69+
- Include code examples in documentation where appropriate.
70+
- Overriding members should inherit the XML documentation from the base type via `/// <inheritdoc />`.
71+
72+
## Markdown
73+
- Use Markdown for documentation files (e.g., README.md).
74+
- Use triple backticks for code blocks, JSON snippets and bash commands, specifying the language (e.g., ```csharp, ```json and ```bash).
75+
76+
## Testing
77+
78+
- When adding new unit tests, strongly prefer to add them to existing test code files rather than creating new code files.
79+
- We use xUnit SDK v3 for tests.
80+
- Do not emit "Act", "Arrange" or "Assert" comments.
81+
- Use NSubstitute for mocking in tests.
82+
- Copy existing style in nearby files for test method names and capitalization.
83+
- When running tests, if possible use filters and check test run counts, or look at test logs, to ensure they actually ran.
84+
- Do not finish work with any tests commented out or disabled that were not previously commented out or disabled.

.github/workflows/codeql.yml

Lines changed: 0 additions & 73 deletions
This file was deleted.

README.md

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[![Lint Code Base](https://github.com/marcominerva/MinimalHelpers/actions/workflows/linter.yml/badge.svg)](https://github.com/marcominerva/MinimalHelpers/actions/workflows/linter.yml)
44
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/marcominerva/MinimalHelpers/blob/master/LICENSE)
55

6-
A collection of helpers libraries for Minimal API projects.
6+
A collection of helper libraries for Minimal API projects.
77

88
## MinimalHelpers.Routing
99

@@ -22,7 +22,7 @@ dotnet add package MinimalHelpers.Routing
2222

2323
### Usage
2424

25-
Create a class to hold your route handlers registration and make it implementing the `IEndpointRouteHandlerBuilder` interface:
25+
Create a class to hold your route handlers registration and have it implement the `IEndpointRouteHandlerBuilder` interface:
2626

2727
```csharp
2828
public class PeopleEndpoints : MinimalHelpers.Routing.IEndpointRouteHandlerBuilder
@@ -40,7 +40,7 @@ public class PeopleEndpoints : MinimalHelpers.Routing.IEndpointRouteHandlerBuild
4040
}
4141
```
4242

43-
Call the `MapEndpoints()` extension method on the **WebApplication** object inside *Program.cs* before the `Run()` method invocation:
43+
Call the `MapEndpoints()` extension method on the **WebApplication** object inside *Program.cs* before invoking the `Run()` method:
4444

4545
```csharp
4646
// using MinimalHelpers.Routing;
@@ -54,7 +54,7 @@ By default, `MapEndpoints()` will scan the calling Assembly to search for classe
5454
- Use the `MapEndpoints()` overload that takes the Assembly to scan as argument
5555
- Use the `MapEndpointsFromAssemblyContaining<T>()` extension method and specify a type that is contained in the Assembly you want to scan
5656

57-
You can also explicitly decide what types (among the ones that implement the `IRouteEndpointHandlerBuilder` interface) you want to actually map, passing a predicate to the `MapEndpoints` method:
57+
You can also explicitly decide which types (among those that implement the `IEndpointRouteHandlerBuilder` interface) you actually want to map, passing a predicate to the `MapEndpoints` method:
5858

5959
```csharp
6060
app.MapEndpoints(type =>
@@ -69,7 +69,7 @@ app.MapEndpoints(type =>
6969
```
7070

7171
> **Note**
72-
These methods rely on Reflection to scan the Assembly and find the classes that implement the `IEndpointRouteHandlerBuilder` interface. This can have a performance impact, especially in large projects. If you have performance issues, consider using the explicit registration method. Moreover, this solution is incompatibile with Native AOT.
72+
These methods rely on Reflection to scan the Assembly and find the classes that implement the `IEndpointRouteHandlerBuilder` interface. This can have a performance impact, especially in large projects. If you have performance issues, consider using the explicit registration method. Moreover, this solution is incompatible with Native AOT.
7373

7474
## MinimalHelpers.Routing.Analyzers
7575

@@ -88,7 +88,7 @@ dotnet add package MinimalHelpers.Routing.Analyzers
8888

8989
### Usage
9090

91-
Create a class to hold your route handlers registration and make it implementing the `IEndpointRouteHandlerBuilder` interface:
91+
Create a class to hold your route handlers registration and have it implement the `IEndpointRouteHandlerBuilder` interface:
9292

9393
```csharp
9494
public class PeopleEndpoints : IEndpointRouteHandlerBuilder
@@ -125,7 +125,7 @@ The `MapEndpoints` method is generated by the Source Generator.
125125
[![Nuget](https://img.shields.io/nuget/v/MinimalHelpers.OpenApi)](https://www.nuget.org/packages/MinimalHelpers.OpenApi)
126126
[![Nuget](https://img.shields.io/nuget/dt/MinimalHelpers.OpenApi)](https://www.nuget.org/packages/MinimalHelpers.OpenApi)
127127

128-
A library that provides OpenApi helpers for Minimal API projects.
128+
A library that provides OpenAPI helpers for Minimal API projects.
129129

130130
### Installation
131131

@@ -139,7 +139,7 @@ dotnet add package MinimalHelpers.OpenApi
139139

140140
***Extension methods for OpenApi***
141141

142-
This library provides some extensions methods that simplify the OpenAPI configuration in Minimal API projects. For example, it is possible to customize the description of a response using its status code:
142+
This library provides several extension methods that simplify the OpenAPI configuration in Minimal API projects. For example, it is possible to customize the description of a response using its status code:
143143

144144
```csharp
145145
endpoints.MapPost("login", LoginAsync)
@@ -164,7 +164,7 @@ endpoints.MapPost("login", LoginAsync)
164164

165165
***Extension methods for RouteHandlerBuilder***
166166

167-
Often we have endpoints with multiple 4xx return values, each of which produces a `ProblemDetails` response:
167+
Often, endpoints have multiple 4xx return values, each producing a `ProblemDetails` response:
168168

169169
```csharp
170170
endpoints.MapGet("/api/people/{id:guid}", Get)
@@ -174,7 +174,7 @@ endpoints.MapPost("login", LoginAsync)
174174
.ProducesProblem(StatusCodes.Status404NotFound);
175175
```
176176

177-
To avoid multiple calls to `ProducesProblem`, we can use the `ProducesDefaultProblem` extension method provided by the library:
177+
To avoid multiple calls to `ProducesProblem`, use the `ProducesDefaultProblem` extension method provided by the library::
178178

179179
```csharp
180180
endpoints.MapGet("/api/people/{id:guid}", Get)
@@ -199,7 +199,7 @@ dotnet add package MinimalHelpers.Validation
199199

200200
### Usage
201201

202-
Decorates a class with attributes to define the validation rules:
202+
Decorate a class with attributes to define the validation rules:
203203

204204
```csharp
205205
using System.ComponentModel.DataAnnotations;
@@ -219,7 +219,7 @@ public class Person
219219
}
220220
```
221221

222-
Add the `WithValidation<T>()` extension method to enable the validation filter:
222+
Use the `WithValidation<TModel>()` extension method to enable the validation filter:
223223

224224
```csharp
225225
using MinimalHelpers.Validation;
@@ -251,7 +251,7 @@ If the validation fails, the response will be a `400 Bad Request` with a `Valida
251251
}
252252
```
253253

254-
If you want to customize validation, you can use the `ConfigureValidation` extension method:
254+
To customize validation, use the `ConfigureValidation` extension method:
255255

256256
```csharp
257257
using MinimalHelpers.Validation;
@@ -267,7 +267,7 @@ builder.Services.ConfigureValidation(options =>
267267
});
268268
```
269269

270-
You can use the `ValidationErrorTitleMessageFactory`, for example, if you want to localized the `title` property of the response using a RESX file.
270+
You can use the `ValidationErrorTitleMessageFactory`, for example, if you want to localize the `title` property of the response using a RESX file.
271271

272272
## MinimalHelpers.FluentValidation
273273

@@ -286,7 +286,7 @@ dotnet add package MinimalHelpers.FluentValidation
286286

287287
### Usage
288288

289-
Create a class that extends AbstractValidator<T> and define the validation rules:
289+
Create a class that extends AbstractValidator<TModel> and define the validation rules:
290290

291291
```csharp
292292
using FluentValidation;
@@ -309,12 +309,12 @@ Register validators in the Service Collection:
309309
```csharp
310310
using FluentValidation;
311311

312-
// Assuming the validators are in the same assembly as the Program class
312+
// Assuming the validators are in the same assembly as the Program class.
313313
builder.Services.AddValidatorsFromAssemblyContaining<Program>();
314314

315315
```
316316

317-
Add the `WithValidation<T>()` extension method to enable the validation filter:
317+
Use the `WithValidation<TModel>()` extension method to enable the validation filter:
318318

319319
```csharp
320320
using MinimalHelpers.FluentValidation;
@@ -340,13 +340,13 @@ If the validation fails, the response will be a `400 Bad Request` with a `Valida
340340
"'Name' cannot be empty."
341341
],
342342
"UnitPrice": [
343-
"'Unit Price' must be grater than '0'."
343+
"'Unit Price' must be greater than '0'."
344344
]
345345
}
346346
}
347347
```
348348

349-
If you want to customize validation, you can use the `ConfigureValidation` extension method:
349+
To customize validation, use the `ConfigureValidation` extension method:
350350

351351
```csharp
352352
using MinimalHelpers.Validation;
@@ -362,9 +362,9 @@ builder.Services.ConfigureValidation(options =>
362362
});
363363
```
364364

365-
You can use the `ValidationErrorTitleMessageFactory`, for example, if you want to localized the `title` property of the response using a RESX file.
365+
You can use the `ValidationErrorTitleMessageFactory`, for example, if you want to localize the `title` property of the response using a RESX file.
366366

367367

368-
**Contribute**
368+
**Contributing**
369369

370-
The project is constantly evolving. Contributions are welcome. Feel free to file issues and pull requests on the repo and we'll address them as we can.
370+
The project is constantly evolving. Contributions are welcome! Please file issues or pull requests in the repository and they will be addressed as soon as possible.

src/MinimalHelpers.FluentValidation/RouteHandlerBuilderExtensions.cs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,36 @@
44
namespace MinimalHelpers.FluentValidation;
55

66
/// <summary>
7-
/// Extension methods for <see cref="RouteHandlerBuilder"/> to add validation.
7+
/// Extension methods for <see cref="RouteHandlerBuilder"/> to add validation to Minimal API endpoints using FluentValidation.
88
/// </summary>
9+
/// <remarks>
10+
/// These methods allow you to easily add FluentValidation-based validation filters to your Minimal API routes. See <see href="https://fluentvalidation.net">FluentValidation documentation</see> and <see href="https://github.com/marcominerva/MinimalHelpers">project documentation</see> for more details.
11+
/// </remarks>
912
/// <seealso cref="RouteHandlerBuilder"/>
1013
public static class RouteHandlerBuilderExtensions
1114
{
1215
/// <summary>
13-
/// Registers a <seealso cref="ValidatorFilter{T}"/> of type <typeparamref name="T"/> onto the route handler to validate the <typeparamref name="T"/> object.
16+
/// Registers a <see cref="ValidatorFilter{TModel}"/> of type <typeparamref name="TModel"/> onto the route handler to validate the <typeparamref name="TModel"/> object using FluentValidation.
1417
/// </summary>
15-
/// <typeparam name="T">The type of the object to validate.</typeparam>
16-
/// <param name="builder">The <see cref="RouteHandlerBuilder"/> to add validation filter to.</param>
18+
/// <typeparam name="TModel">The type of the object to validate.</typeparam>
19+
/// <param name="builder">The <see cref="RouteHandlerBuilder"/> to add the validation filter to.</param>
1720
/// <returns>A <see cref="RouteHandlerBuilder"/> that can be used to further customize the route handler.</returns>
18-
/// <remarks>The validation is performed using <a href="https://fluentvalidation.net">FluentValidation</a>.</remarks>
19-
/// <seealso cref="ValidatorFilter{T}"/>
20-
public static RouteHandlerBuilder WithValidation<T>(this RouteHandlerBuilder builder) where T : class
21+
/// <remarks>
22+
/// The validation is performed using <see href="https://fluentvalidation.net">FluentValidation</see>.
23+
/// <example>
24+
/// <code language="csharp">
25+
/// app.MapPost("/api/products", (Product product) =>
26+
/// {
27+
/// // ...
28+
/// })
29+
/// .WithValidation&lt;Product&gt;();
30+
/// </code>
31+
/// </example>
32+
/// </remarks>
33+
/// <seealso cref="ValidatorFilter{TModel}"/>
34+
public static RouteHandlerBuilder WithValidation<TModel>(this RouteHandlerBuilder builder) where TModel : class
2135
{
22-
builder.AddEndpointFilter<ValidatorFilter<T>>()
36+
builder.AddEndpointFilter<ValidatorFilter<TModel>>()
2337
.ProducesValidationProblem();
2438

2539
return builder;

0 commit comments

Comments
 (0)