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
17 changes: 12 additions & 5 deletions docs/guide/durability/marten/event-sourcing.md
Original file line number Diff line number Diff line change
Expand Up @@ -876,16 +876,23 @@ public class when_transfering_money
{
// StubEventStream<T> is a type that was recently added to Marten
// specifically to facilitate testing logic like this
var fromAccount = new StubEventStream<Account>(new Account { Amount = 1000 }){Id = Guid.NewGuid()};
var toAccount = new StubEventStream<Account>(new Account { Amount = 100}){Id = Guid.NewGuid()});
var fromAccount = new StubEventStream<Account>(new Account { Amount = 1000 })
{
Id = Guid.NewGuid()
};

var toAccount = new StubEventStream<Account>(new Account { Amount = 100})
{
Id = Guid.NewGuid()
};

TransferMoneyHandler.Handle(new TransferMoney(fromAccount.Id, toAccount.Id, 100), fromAccount, toAccount);

// Now check the events we expected to be appended
fromAccount.Events.Single().ShouldBeOfType<Withdrawn>().Amount.ShouldBe(100);
toAccount.Events.Single().ShouldBeOfType<Debited>().Amount.ShouldBe(100);
fromAccount.Events.Single().Data.ShouldBeOfType<Withdrawn>().Amount.ShouldBe(100);
toAccount.Events.Single().Data.ShouldBeOfType<Debited>().Amount.ShouldBe(100);
}
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/Wolverine.Http.Tests/Marten/working_against_multiple_streams.cs#L89-L109' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_when_transfering_money' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/Wolverine.Http.Tests/Marten/working_against_multiple_streams.cs#L89-L116' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_when_transfering_money' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
43 changes: 39 additions & 4 deletions docs/guide/http/as-parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public class AsParametersQuery{
public int? NullableHeader { get; set; }
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/FormEndpoints.cs#L98-L144' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_as_parameters_binding' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/FormEndpoints.cs#L99-L145' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_as_parameters_binding' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

And the corresponding test case for utilizing this:
Expand Down Expand Up @@ -110,7 +110,7 @@ response.IntegerNotUsed.ShouldBe(default);
response.FloatNotUsed.ShouldBe(default);
response.BooleanNotUsed.ShouldBe(default);
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/Wolverine.Http.Tests/asparameters_binding.cs#L24-L61' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_asparameters_test' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/Wolverine.Http.Tests/asparameters_binding.cs#L17-L54' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_asparameters_test' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Wolverine.HTTP is also able to support `[FromServices]`, `[FromBody]`, and `[FromRoute]` bindings as well
Expand Down Expand Up @@ -152,7 +152,7 @@ public static class AsParametersEndpoints2{
}
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/FormEndpoints.cs#L146-L181' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_as_parameter_for_services_and_body' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/FormEndpoints.cs#L147-L182' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_as_parameter_for_services_and_body' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

And lastly, you can use C# records or really just any constructor function as well
Expand All @@ -173,5 +173,40 @@ public static class AsParameterRecordEndpoint
public static AsParameterRecord Post([AsParameters] AsParameterRecord input) => input;
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/FormEndpoints.cs#L183-L197' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_as_parameter_record' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/FormEndpoints.cs#L184-L198' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_as_parameter_record' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


The [Fluent Validation middleware](./fluentvalidation) for Wolverine.HTTP is able to validate against request types
bound with `[AsParameters]`:

<!-- 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/FormEndpoints.cs#L201-L228' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_fluent_validation_with_asparameters' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
36 changes: 36 additions & 0 deletions docs/guide/http/fluentvalidation.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,39 @@ app.MapWolverineEndpoints(opts =>
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Program.cs#L216-L237' 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/FormEndpoints.cs#L201-L228' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_fluent_validation_with_asparameters' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
2 changes: 1 addition & 1 deletion docs/guide/http/forms.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ You can also use the FromForm attribute on a complex type, Wolverine will then a
[WolverinePost("/api/fromformbigquery")]
public static BigQuery Post([FromForm] BigQuery query) => query;
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/FormEndpoints.cs#L92-L95' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_[fromform]_binding' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/FormEndpoints.cs#L93-L96' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_[fromform]_binding' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Individual properties on the class can be aliased using ``[FromForm(Name = "aliased")]``
30 changes: 22 additions & 8 deletions src/Http/Wolverine.Http.Tests/asparameters_binding.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Alba;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using WolverineWebApi;
Expand All @@ -10,14 +11,6 @@ public asparameters_binding(AppFixture fixture) : base(fixture)
{
}

/*
* TODOs
* Bind the body, and when you do that, set the request type
* Bind a service
* Bind a route argument
*/


[Fact]
public async Task fill_all_fields()
{
Expand Down Expand Up @@ -169,4 +162,25 @@ public async Task use_record_for_as_parameters()
value.Direction.ShouldBe(Direction.East);
value.IsTrue.ShouldBeTrue();
}

[Fact]
public async Task using_with_FluentValidation_middleware()
{
// Happy path
await Scenario(x =>
{
x.Get.Url("/asparameters/validated")
.QueryString("Name", "Jeremy")
.QueryString("Age", "51");
});

var result = await Scenario(x =>
{
x.Get.Url("/asparameters/validated")
.QueryString("Age", "51");

x.StatusCodeShouldBe(400);
x.ContentTypeShouldBe("application/problem+json");
});
}
}
31 changes: 31 additions & 0 deletions src/Http/WolverineWebApi/FormEndpoints.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text.Json.Serialization;
using FluentValidation;
using JasperFx.Core;
using Marten;
using Microsoft.AspNetCore.Mvc;
Expand Down Expand Up @@ -196,3 +197,33 @@ public static class AsParameterRecordEndpoint

#endregion


#region sample_using_fluent_validation_with_AsParameters

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();
}
}
}

#endregion

Loading