Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions Wolverine.Http.DataAnnotationsValidation.Tests/Usings.cs

This file was deleted.

This file was deleted.

16 changes: 1 addition & 15 deletions build/build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ class Build : NukeBuild
});

Target HttpTests => _ => _
.DependsOn(CoreHttpTests, DataAnnotationsValidationHttpTests);
.DependsOn(CoreHttpTests);

Target CoreHttpTests => _ => _
.DependsOn(Compile, DockerUp)
Expand All @@ -160,20 +160,6 @@ class Build : NukeBuild
.SetFramework(Framework));
});

Target DataAnnotationsValidationHttpTests => _ => _
.DependsOn(Compile)
.ProceedAfterFailure()
.Executes(() =>
{
DotNetTest(c => c
.SetProjectFile(Solution.Http.Wolverine_Http_DataAnnotationsValidation_Tests)
.SetConfiguration(Configuration)
.EnableNoBuild()
.EnableNoRestore()
.SetFramework(Framework));
});


Target Commands => _ => _
.DependsOn(HelpCommand, DescribeCommand, CodegenPreviewCommand);

Expand Down
2 changes: 1 addition & 1 deletion docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,8 @@ const config: UserConfig<DefaultTheme.Config> = {
{text: 'Uploading Files', link: '/guide/http/files'},
{text: 'Integration with Sagas', link: '/guide/http/sagas'},
{text: 'Integration with Marten', link: '/guide/http/marten'},
{text: 'Validation', link: '/guide/http/validation'},
{text: 'Fluent Validation', link: '/guide/http/fluentvalidation'},
{text: 'DataAnnotations Validation', link: '/guide/http/dataannotationsvalidation'},
{text: 'Problem Details', link: '/guide/http/problemdetails'},
{text: 'Caching', link: '/guide/http/caching'}
]
Expand Down
32 changes: 0 additions & 32 deletions docs/guide/http/dataannotationsvalidation.md

This file was deleted.

132 changes: 1 addition & 131 deletions docs/guide/http/fluentvalidation.md
Original file line number Diff line number Diff line change
@@ -1,133 +1,3 @@
# Fluent Validation Middleware for HTTP

::: warning
If you need to use IoC services in a Fluent Validation `IValidator` that might force Wolverine to use a service locator
pattern in the generated code (basically from `AddScoped<T>(s => build it at runtime)`), we recommend instead using a
more explicit `Validate` or `ValidateAsync()` method directly in your HTTP endpoint class for the data input.
:::

Wolverine.Http has a separate package called `WolverineFx.Http.FluentValidation` that provides a simple middleware
for using [Fluent Validation](https://docs.fluentvalidation.net/en/latest/) in your HTTP endpoints.

To get started, install that Nuget reference:

```bash
dotnet add package WolverineFx.Http.FluentValidation
```

Next, let's assume that you have some Fluent Validation validators registered in your application container for the
request types of your HTTP endpoints -- and the [UseFluentValidation](/guide/handlers/fluent-validation) method from the
`WolverineFx.FluentValidation` package will help find these validators and register them in a way that optimizes this
middleware usage.

Next, add this one single line of code to your Wolverine.Http bootstrapping:

```csharp
opts.UseFluentValidationProblemDetailMiddleware();
```

as shown in context below in an application shown below:

<!-- snippet: sample_using_configure_endpoints -->
<a id='snippet-sample_using_configure_endpoints'></a>
```cs
app.MapWolverineEndpoints(opts =>
{
// This is strictly to test the endpoint policy

opts.ConfigureEndpoints(httpChain =>
{
// The HttpChain model is a configuration time
// model of how the HTTP endpoint handles requests

// This adds metadata for OpenAPI
httpChain.WithMetadata(new CustomMetadata());
});

// more configuration for HTTP...

// Opting into the Fluent Validation middleware from
// Wolverine.Http.FluentValidation
opts.UseFluentValidationProblemDetailMiddleware();
```
<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>
<!-- endSnippet -->

## AsParameters Binding

The Fluent Validation middleware can also be used against the `[AsParameters]` input
of an HTTP endpoint:

<!-- snippet: sample_using_fluent_validation_with_AsParameters -->
<a id='snippet-sample_using_fluent_validation_with_asparameters'></a>
```cs
public static class ValidatedAsParametersEndpoint
{
[WolverineGet("/asparameters/validated")]
public static string Get([AsParameters] ValidatedQuery query)
{
return $"{query.Name} is {query.Age}";
}
}

public class ValidatedQuery
{
[FromQuery]
public string? Name { get; set; }

public int Age { get; set; }

public class ValidatedQueryValidator : AbstractValidator<ValidatedQuery>
{
public ValidatedQueryValidator()
{
RuleFor(x => x.Name).NotNull();
}
}
}
```
<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>
<!-- endSnippet -->

## QueryString Binding <Badge type="tip" text="5.0" />

Wolverine.HTTP can apply the Fluent Validation middleware to complex types that are bound by the `[FromQuery]` behavior:

<!-- snippet: sample_CreateCustomer_endpoint_with_validation -->
<a id='snippet-sample_createcustomer_endpoint_with_validation'></a>
```cs
public record CreateCustomer
(
string FirstName,
string LastName,
string PostalCode
)
{
public class CreateCustomerValidator : AbstractValidator<CreateCustomer>
{
public CreateCustomerValidator()
{
RuleFor(x => x.FirstName).NotNull();
RuleFor(x => x.LastName).NotNull();
RuleFor(x => x.PostalCode).NotNull();
}
}
}

public static class CreateCustomerEndpoint
{
[WolverinePost("/validate/customer")]
public static string Post(CreateCustomer customer)
{
return "Got a new customer";
}

[WolverinePost("/validate/customer2")]
public static string Post2([FromQuery] CreateCustomer customer)
{
return "Got a new customer";
}
}
```
<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>
<!-- endSnippet -->
See the [Validation Page](./validation).
Loading
Loading