Skip to content

Commit

Permalink
#628 Using before middleware that uses an aggregate does not generate…
Browse files Browse the repository at this point in the history
… code that fetches the aggregate

- A reproduction path. No fix yet
  • Loading branch information
erdtsieck authored and jeremydmiller committed Nov 13, 2023
1 parent c70402e commit ca0ea5a
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 13 deletions.
4 changes: 2 additions & 2 deletions docs/guide/http/endpoints.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ public static OrderShipped Ship(ShipOrder command, Order order)
return new OrderShipped();
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L79-L92' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_emptyresponse' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L102-L115' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_emptyresponse' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

## JSON Handling
Expand Down Expand Up @@ -311,7 +311,7 @@ and register that strategy within our `MapWolverineEndpoints()` set up like so:
// Customizing parameter handling
opts.AddParameterHandlingStrategy<NowParameterStrategy>();
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Program.cs#L145-L150' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_adding_custom_parameter_handling' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Program.cs#L146-L151' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_adding_custom_parameter_handling' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

And lastly, here's the application within an HTTP endpoint for extra context:
Expand Down
29 changes: 27 additions & 2 deletions docs/guide/http/files.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,32 @@
As of 1.11.0, Wolverine supports file uploads through the standard ASP.Net Core `IFile` or `IFileCollection` types. All you need
to do to is to have an input parameter to your Wolverine.HTTP endpoint of these types like so:

snippet: sample_using_file_uploads
<!-- snippet: sample_using_file_uploads -->
<a id='snippet-sample_using_file_uploads'></a>
```cs
public class FileUploadEndpoint
{
// If you have exactly one file upload, take
// in IFormFile
[WolverinePost("/upload/file")]
public static Task Upload(IFormFile file)
{
// access the file data
return Task.CompletedTask;
}

// If you have multiple files at one time,
// use IFormCollection
[WolverinePost("/upload/files")]
public static Task Upload(IFormFileCollection files)
{
// access files
return Task.CompletedTask;
}
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/FileUploadEndpoint.cs#L5-L28' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_file_uploads' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

See [Upload files in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-7.0)
for more information about these types.
for more information about these types.
17 changes: 11 additions & 6 deletions docs/guide/http/marten.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public static OrderShipped Ship(ShipOrder2 command, [Aggregate] Order order)
return new OrderShipped();
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L94-L106' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_aggregate_attribute_1' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L117-L129' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_aggregate_attribute_1' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Using this version of the "aggregate workflow", you no longer have to supply a command in the request body, so you could
Expand All @@ -114,7 +114,7 @@ public static OrderShipped Ship3([Aggregate] Order order)
return new OrderShipped();
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L108-L120' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_aggregate_attribute_2' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L131-L143' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_aggregate_attribute_2' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

A couple other notes:
Expand Down Expand Up @@ -143,7 +143,11 @@ public record MarkItemReady(Guid OrderId, string ItemName, int Version);
public record OrderShipped;
public record OrderCreated(Item[] Items);
public record OrderReady;
public record ShipOrder(Guid OrderId);
public interface IShipOrder
{
Guid OrderId { init; }
}
public record ShipOrder(Guid OrderId) : IShipOrder;
public record ShipOrder2(string Description);
public record ItemReady(string Name);

Expand Down Expand Up @@ -188,9 +192,10 @@ public class Order
return Shipped == null && Items.Values.All(x => x.Ready);
}

public bool IsShipped() => Shipped.HasValue;
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L11-L66' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_order_aggregate_for_http' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L11-L71' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_order_aggregate_for_http' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

To append a single event to an event stream from an HTTP endpoint, you can use a return value like so:
Expand All @@ -209,7 +214,7 @@ public static OrderShipped Ship(ShipOrder command, Order order)
return new OrderShipped();
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L79-L92' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_emptyresponse' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L102-L115' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_emptyresponse' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Or potentially append multiple events using the `Events` type as a return value like this sample:
Expand Down Expand Up @@ -245,6 +250,6 @@ public static (OrderStatus, Events) Post(MarkItemReady command, Order order)
return (new OrderStatus(order.Id, order.IsReadyToShip()), events);
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L170-L200' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_returning_multiple_events_from_http_endpoint' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L193-L223' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_returning_multiple_events_from_http_endpoint' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

2 changes: 1 addition & 1 deletion docs/guide/http/mediator.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ app.MapPostToWolverine<CustomRequest, CustomResponse>("/wolverine/request");
app.MapDeleteToWolverine<CustomRequest, CustomResponse>("/wolverine/request");
app.MapPutToWolverine<CustomRequest, CustomResponse>("/wolverine/request");
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Program.cs#L154-L166' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_optimized_mediator_usage' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Program.cs#L155-L167' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_optimized_mediator_usage' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

With this mechanism, Wolverine is able to optimize the runtime function for Minimal API by eliminating IoC service locations
Expand Down
3 changes: 2 additions & 1 deletion docs/guide/http/middleware.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ Which is registered like this (or as described in [`Registering Middleware by Me
<a id='snippet-sample_register_http_middleware_by_type'></a>
```cs
opts.AddMiddlewareByMessageType(typeof(FakeAuthenticationMiddleware));
opts.AddMiddlewareByMessageType(typeof(CanShipOrderMiddleWare));
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Program.cs#L132-L134' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_register_http_middleware_by_type' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Program.cs#L132-L135' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_register_http_middleware_by_type' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

The key point to notice there is that `IResult` is a "return value" of the middleware. In the case of an HTTP endpoint,
Expand Down
23 changes: 23 additions & 0 deletions docs/guide/http/problemdetails.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,26 @@ with your own metadata if you need to use a different status code like this:
[ProducesResponseType(typeof(ProblemDetails), 418)]
```

### Using ProblemDetails with Marten aggregates

Of course, if you are using [Marten's aggregates within your Wolverine http handlers](./marten), you also want to be able to validation using the aggregate's details in your middleware and this is perfectly possible like this:

<!-- snippet: sample_using_before_on_http_aggregate -->
<a id='snippet-sample_using_before_on_http_aggregate'></a>
```cs
[AggregateHandler]
public static ProblemDetails Before(IShipOrder command, Order order)
{
if (order.IsShipped())
{
return new ProblemDetails
{
Detail = "Order already shipped",
Status = 428
};
}
return WolverineContinue.NoProblems;
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/WolverineWebApi/Marten/Orders.cs#L83-L97' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_before_on_http_aggregate' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
25 changes: 24 additions & 1 deletion src/Http/WolverineWebApi/Marten/Orders.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ public record MarkItemReady(Guid OrderId, string ItemName, int Version);
public record OrderShipped;
public record OrderCreated(Item[] Items);
public record OrderReady;
public record ShipOrder(Guid OrderId);
public interface IShipOrder
{
Guid OrderId { init; }
}
public record ShipOrder(Guid OrderId) : IShipOrder;
public record ShipOrder2(string Description);
public record ItemReady(string Name);

Expand Down Expand Up @@ -61,6 +65,7 @@ public bool IsReadyToShip()
return Shipped == null && Items.Values.All(x => x.Ready);
}

public bool IsShipped() => Shipped.HasValue;
}

#endregion
Expand All @@ -73,6 +78,24 @@ public record StartOrder(string[] Items);

public record StartOrderWithId(Guid Id, string[] Items);

public static class CanShipOrderMiddleWare
{
#region sample_using_before_on_http_aggregate
[AggregateHandler]
public static ProblemDetails Before(IShipOrder command, Order order)
{
if (order.IsShipped())
{
return new ProblemDetails
{
Detail = "Order already shipped",
Status = 428
};
}
return WolverineContinue.NoProblems;
}
#endregion
}

public static class MarkItemEndpoint
{
Expand Down
1 change: 1 addition & 0 deletions src/Http/WolverineWebApi/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@

#region sample_register_http_middleware_by_type
opts.AddMiddlewareByMessageType(typeof(FakeAuthenticationMiddleware));
opts.AddMiddlewareByMessageType(typeof(CanShipOrderMiddleWare));
#endregion

// Publish messages coming from
Expand Down

0 comments on commit ca0ea5a

Please sign in to comment.