|
1 | 1 | # Fluent Validation Middleware for HTTP |
2 | 2 |
|
3 | | -::: warning |
4 | | -If you need to use IoC services in a Fluent Validation `IValidator` that might force Wolverine to use a service locator |
5 | | -pattern in the generated code (basically from `AddScoped<T>(s => build it at runtime)`), we recommend instead using a |
6 | | -more explicit `Validate` or `ValidateAsync()` method directly in your HTTP endpoint class for the data input. |
7 | | -::: |
8 | | - |
9 | | -Wolverine.Http has a separate package called `WolverineFx.Http.FluentValidation` that provides a simple middleware |
10 | | -for using [Fluent Validation](https://docs.fluentvalidation.net/en/latest/) in your HTTP endpoints. |
11 | | - |
12 | | -To get started, install that Nuget reference: |
13 | | - |
14 | | -```bash |
15 | | -dotnet add package WolverineFx.Http.FluentValidation |
16 | | -``` |
17 | | - |
18 | | -Next, let's assume that you have some Fluent Validation validators registered in your application container for the |
19 | | -request types of your HTTP endpoints -- and the [UseFluentValidation](/guide/handlers/fluent-validation) method from the |
20 | | -`WolverineFx.FluentValidation` package will help find these validators and register them in a way that optimizes this |
21 | | -middleware usage. |
22 | | - |
23 | | -Next, add this one single line of code to your Wolverine.Http bootstrapping: |
24 | | - |
25 | | -```csharp |
26 | | -opts.UseFluentValidationProblemDetailMiddleware(); |
27 | | -``` |
28 | | - |
29 | | -as shown in context below in an application shown below: |
30 | | - |
31 | | -<!-- snippet: sample_using_configure_endpoints --> |
32 | | -<a id='snippet-sample_using_configure_endpoints'></a> |
33 | | -```cs |
34 | | -app.MapWolverineEndpoints(opts => |
35 | | -{ |
36 | | - // This is strictly to test the endpoint policy |
37 | | -
|
38 | | - opts.ConfigureEndpoints(httpChain => |
39 | | - { |
40 | | - // The HttpChain model is a configuration time |
41 | | - // model of how the HTTP endpoint handles requests |
42 | | -
|
43 | | - // This adds metadata for OpenAPI |
44 | | - httpChain.WithMetadata(new CustomMetadata()); |
45 | | - }); |
46 | | - |
47 | | - // more configuration for HTTP... |
48 | | -
|
49 | | - // Opting into the Fluent Validation middleware from |
50 | | - // Wolverine.Http.FluentValidation |
51 | | - opts.UseFluentValidationProblemDetailMiddleware(); |
52 | | -``` |
53 | | -<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Program.cs#L214-L235' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_configure_endpoints' title='Start of snippet'>anchor</a></sup> |
54 | | -<!-- endSnippet --> |
55 | | - |
56 | | -## AsParameters Binding |
57 | | - |
58 | | -The Fluent Validation middleware can also be used against the `[AsParameters]` input |
59 | | -of an HTTP endpoint: |
60 | | - |
61 | | -<!-- snippet: sample_using_fluent_validation_with_AsParameters --> |
62 | | -<a id='snippet-sample_using_fluent_validation_with_asparameters'></a> |
63 | | -```cs |
64 | | -public static class ValidatedAsParametersEndpoint |
65 | | -{ |
66 | | - [WolverineGet("/asparameters/validated")] |
67 | | - public static string Get([AsParameters] ValidatedQuery query) |
68 | | - { |
69 | | - return $"{query.Name} is {query.Age}"; |
70 | | - } |
71 | | -} |
72 | | - |
73 | | -public class ValidatedQuery |
74 | | -{ |
75 | | - [FromQuery] |
76 | | - public string? Name { get; set; } |
77 | | - |
78 | | - public int Age { get; set; } |
79 | | - |
80 | | - public class ValidatedQueryValidator : AbstractValidator<ValidatedQuery> |
81 | | - { |
82 | | - public ValidatedQueryValidator() |
83 | | - { |
84 | | - RuleFor(x => x.Name).NotNull(); |
85 | | - } |
86 | | - } |
87 | | -} |
88 | | -``` |
89 | | -<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Forms/FormEndpoints.cs#L200-L227' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_fluent_validation_with_asparameters' title='Start of snippet'>anchor</a></sup> |
90 | | -<!-- endSnippet --> |
91 | | - |
92 | | -## QueryString Binding <Badge type="tip" text="5.0" /> |
93 | | - |
94 | | -Wolverine.HTTP can apply the Fluent Validation middleware to complex types that are bound by the `[FromQuery]` behavior: |
95 | | - |
96 | | -<!-- snippet: sample_CreateCustomer_endpoint_with_validation --> |
97 | | -<a id='snippet-sample_createcustomer_endpoint_with_validation'></a> |
98 | | -```cs |
99 | | -public record CreateCustomer |
100 | | -( |
101 | | - string FirstName, |
102 | | - string LastName, |
103 | | - string PostalCode |
104 | | -) |
105 | | -{ |
106 | | - public class CreateCustomerValidator : AbstractValidator<CreateCustomer> |
107 | | - { |
108 | | - public CreateCustomerValidator() |
109 | | - { |
110 | | - RuleFor(x => x.FirstName).NotNull(); |
111 | | - RuleFor(x => x.LastName).NotNull(); |
112 | | - RuleFor(x => x.PostalCode).NotNull(); |
113 | | - } |
114 | | - } |
115 | | -} |
116 | | - |
117 | | -public static class CreateCustomerEndpoint |
118 | | -{ |
119 | | - [WolverinePost("/validate/customer")] |
120 | | - public static string Post(CreateCustomer customer) |
121 | | - { |
122 | | - return "Got a new customer"; |
123 | | - } |
124 | | - |
125 | | - [WolverinePost("/validate/customer2")] |
126 | | - public static string Post2([FromQuery] CreateCustomer customer) |
127 | | - { |
128 | | - return "Got a new customer"; |
129 | | - } |
130 | | -} |
131 | | -``` |
132 | | -<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Validation/CreateCustomerEndpoint.cs#L8-L43' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_createcustomer_endpoint_with_validation' title='Start of snippet'>anchor</a></sup> |
133 | | -<!-- endSnippet --> |
| 3 | +See the [Validation Page](./validation). |
0 commit comments