Added a getting started project for WolverineFx.

This commit is contained in:
2026-06-26 16:12:51 +02:00
parent 3434e9fb91
commit 5b9d8c099b
12 changed files with 171 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
namespace WolverineTutorial;
public record AssignIssue(Guid IssueId, Guid AssigneeId);
+3
View File
@@ -0,0 +1,3 @@
namespace WolverineTutorial;
public record CreateIssue(Guid OriginatorId, string Title, string Description);
@@ -0,0 +1,23 @@
namespace WolverineTutorial;
public class CreateIssueHandler(IssueRepository repository)
{
// The IssueCreated event message being returned will be
// published as a new "cascaded" message by Wolverine after
// the original message and any related middleware has
// succeeded
public IssueCreated Handle(CreateIssue command)
{
var issue = new Issue(Guid.NewGuid(), command.Title, command.Description, true, DateTimeOffset.Now,
command.OriginatorId
);
repository.Store(issue);
return new IssueCreated(issue.Id);
}
}
public record Issue(Guid Id, string Title, string Description, bool IsOpen, DateTimeOffset Opened, Guid OriginatorId);
public record IssueCreated(Guid Id);
@@ -0,0 +1,25 @@
using System.Net.Mail;
namespace WolverineTutorial;
public static class IssueCreatedHandler
{
public static async Task Handle(IssueCreated created, IssueRepository repository)
{
var issue = repository.Get(created.Id);
var message = await BuildEmailMessage(issue);
using var client = new SmtpClient();
client.Send(message);
}
// This is a little helper method I made public
// Wolverine will not expose this as a message handler
private static Task<MailMessage> BuildEmailMessage(Issue issue)
{
// Build up a templated email message, with
// some sort of async method to look up additional
// data just so we can show off an async
// Wolverine Handler
return Task.FromResult(new MailMessage());
}
}
@@ -0,0 +1,14 @@
namespace WolverineTutorial;
public class IssueRepository
{
public void Store(Issue issue)
{
throw new NotImplementedException();
}
public Issue Get(Guid createdId)
{
throw new NotImplementedException();
}
}
+29
View File
@@ -0,0 +1,29 @@
using JasperFx;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Scalar.AspNetCore;
using Wolverine;
using WolverineTutorial;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenApi();
builder.Host.UseWolverine(options => { options.UseRuntimeCompilation(); });
builder.Services.AddSingleton<UserRepository>();
builder.Services.AddSingleton<IssueRepository>();
var app = builder.Build();
app.MapPost("/issues/create", (CreateIssue body, IMessageBus bus) => bus.InvokeAsync(body));
//app.MapPost("/issues/assign", (AssignIssue body, IMessageBus bus) => bus.InvokeAsync(body));
app.MapOpenApi();
app.MapScalarApiReference();
app.MapGet("/", () => Results.Redirect("/scalar"));
app.UseHttpsRedirection();
return await app.RunJasperFxCommands(args);
@@ -0,0 +1,23 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:5043",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "https://localhost:7161;http://localhost:5043",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
@@ -0,0 +1,5 @@
namespace WolverineTutorial;
public class UserRepository
{
}
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>WolverineTutorial</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.8" />
<PackageReference Include="Scalar.AspNetCore" Version="2.16.3" />
<PackageReference Include="WolverineFx" Version="6.8.0" />
<PackageReference Include="WolverineFx.RuntimeCompilation" Version="6.8.0" />
</ItemGroup>
</Project>
@@ -0,0 +1,12 @@
@getting_started_HostAddress = https://localhost:7161
POST {{getting_started_HostAddress}}/issues/create
Content-Type: application/json
{
"originatorId": "e731cf74-0e57-4c91-8fda-6ae5214a9fa4",
"title": "Test Title",
"description": "Test Description"
}
###