Skip to content

Commit

Permalink
Update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
MrDave1999 committed Dec 19, 2023
1 parent 20a5a86 commit 0296c45
Showing 1 changed file with 91 additions and 0 deletions.
91 changes: 91 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ See the [API documentation](https://mrdave1999.github.io/SimpleResults/api/Simpl
- [Using TranslateResultToActionResult as an action filter](#using-translateresulttoactionresult-as-an-action-filter)
- [Add action filter as global](#add-action-filter-as-global)
- [Support for Minimal APIs](#support-for-minimal-apis)
- [Validating with the ModelState property](#validating-with-the-modelstate-property)
- [Translate Result object to HTTP status code](#translate-result-object-to-http-status-code)
- [Integration with Fluent Validation](#integration-with-fluent-validation)
- [Samples](#samples)
Expand Down Expand Up @@ -425,6 +426,96 @@ The endpoint handler returns a `Result<User>`. After the handler is executed, th

[See the source code](https://github.com/MrDave1999/SimpleResults/blob/25387945f57241dadad3baf52886ab59949c98fa/src/AspNetCore/TranslateResultToHttpResultFilter.cs#L26), it is very simple.

#### Validating with the ModelState property

[SimpleResults.AspNetCore](https://www.nuget.org/packages/SimpleResults.AspNetCore) package also adds extension methods for the [ModelStateDictionary](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.modelbinding.modelstatedictionary?view=aspnetcore-7.0) type.

See the [ModelStateDictionaryExtensions](https://mrdave1999.github.io/SimpleResults/api/SimpleResults.SRModelStateDictionaryExtensions.html) class to find all extension methods.

The `ModelStateDictionary` type contains the validation errors that are displayed to the client. Somehow these errors must be included in an instance of type [Result](https://mrdave1999.github.io/SimpleResults/api/SimpleResults.Result.html).

##### Manual validation

Manual validation is performed directly in the controller action.

**Example:**
```cs
[TranslateResultToActionResult]
[Route("[controller]")]
public class OrderController : ControllerBase
{
private readonly OrderService _orderService;
public OrderController(OrderService orderService) => _orderService = orderService;

[HttpPost]
public Result<CreatedGuid> Create([FromBody]CreateOrderRequest request)
{
if (ModelState.IsFailed())
return ModelState.Invalid();

return _orderService.Create(request);
}
}
```
In this example a manual validation is performed with `ModelState.IsFailed()` (an extension method), so if the model state is failed, an invalid result type is returned. What `ModelState.Invalid()` does is to convert the instance of `ModelStateDictionary` to an instance of type [Result](https://mrdave1999.github.io/SimpleResults/api/SimpleResults.Result.html), so in the result object the validation errors will be added.

After the controller action is executed, the `TranslateResultToActionResult` filter will translate the Result object to an instance of type `ActionResult`.

You can also return the ActionResult directly in the controller action instead of using the action filter.

**Example:**
```cs
[Route("[controller]")]
public class OrderController : ControllerBase
{
private readonly OrderService _orderService;
public OrderController(OrderService orderService) => _orderService = orderService;

[HttpPost]
public ActionResult<Result<CreatedGuid>> Create([FromBody]CreateOrderRequest request)
{
if (ModelState.IsFailed())
return ModelState.BadRequest();

return _orderService
.Create(request)
.ToActionResult();
}
}
```
`ModelState.BadRequest()` has a behavior similar to `ModelState.Invalid()`, the difference is that the first one returns an instance of type [BadRequestObjectResult](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.badrequestobjectresult?view=aspnetcore-7.0) in which contains the instance of type [Result](https://mrdave1999.github.io/SimpleResults/api/SimpleResults.Result.html).

##### Automatic validation

You need to make a setting in the `Program.cs` to convert the instance of type `ModelStateDictionary` to an instance of type [Result](https://mrdave1999.github.io/SimpleResults/api/SimpleResults.Result.html) when the model validation fails.

**Example:**
```cs
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.InvalidModelStateResponseFactory = (ActionContext context) => context.ModelState.BadRequest();
});
```
This delegate is only invoked on actions annotated with `ApiControllerAttribute` and will execute the `context.ModelState.BadRequest()` call when a model validation failure occurs. If a validation failure occurs in the model, the controller action will never be executed.

Your controller no longer needs to perform manual validation, for example:
```cs
[ApiController]
[TranslateResultToActionResult]
[Route("[controller]")]
public class OrderController : ControllerBase
{
private readonly OrderService _orderService;
public OrderController(OrderService orderService) => _orderService = orderService;

[HttpPost]
public Result<CreatedGuid> Create([FromBody]CreateOrderRequest request)
=> _orderService.Create(request);
}
```
The [ApiController](https://learn.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-7.0#automatic-http-400-responses) is necessary because it allows to activate the [ModelStateInvalid](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.infrastructure.modelstateinvalidfilter?view=aspnetcore-7.0) filter to perform the model validation before executing the controller action.

### Translate Result object to HTTP status code

[SimpleResults.AspNetCore](https://www.nuget.org/packages/SimpleResults.AspNetCore) package is responsible for translating the status of a Result object into an HTTP status code.
Expand Down

0 comments on commit 0296c45

Please sign in to comment.