I have a number of reusable business logic steps which will be re-used in various web endpoints. I’m trying to see if there’s a nice way in .NET 6 to ‘chain’ these reusable business logic code (think, classes where each class does just one logic step).
It’s like how .NET has ‘middleware’ for web apps. Only in this instance, I wish to hit an endpoint then do all the steps in my custom pipeline, with the steps hardcoded for that endpoint.
here’s a high level summary.
- Each ‘flow’ has a number of steps
- A single endpoint ‘invokes’ as specific flow .. which then steps through each step -until some business logic fails some check- which stops continuing and bubbles back with the error message or view.
for example.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<IUserRegistration>(_ =>
{
new MyPipeline()
.AddStep(newUser => ValidateUserData(newUser)) // userData is from the POST request body.
.AddStep(user => CheckIfUserExists(user)) // Check if the user exists in the db
.AddStep(user => CreateUser(user));
});
builder.Services.AddScoped<IEnrollForCourse>(_ =>
{
new MyPipeline()
.AddStep(user => CheckIfUserExists(user)) // Check if the user exists in the db
.AddStep(course => CheckIfTheCourseExists(course)) // Does the uni course, exist?
.AddStep((user, course) => EnrollUserToCourse(user, course));
});
var app = builder.Build();
app.MapPost("/register", async (NewUserModel newUser, IUserRegistration userRegistration) =>
{
var viewResult = await userRegistration.Execute(newUser);
return viewResult; // 200-OK | 400-BadRequest
});
app.MapPost("/enroll", async (EnrollModel enroll, IEnrollForCourse enrollForCourse) =>
{
var viewResult = await enrollForCourse.Execute(enroll);
retyrn viewResult; // 204-NoContent | 400-BadRequest
});
app.Run();
So there’s heaps of problems with the above, but the general idea there.
Is this a solved problem, in .NET already? Surely this isn’t new.
EDIT: Of course, I would usually just use a single class with if/else checks .. which then call the various business logic. Yes, I know. We have that -now- and if just feels really large and unwieldy and I’m trying to see if this can be refactored into nicer, re-usable components.
Also, I don’t want to use Logic Apps .. which is a similar concept by Microsoft.
NOTE: I’m using users/course/uni etc as a simplistic example for demo/question purposes.
2
Answers
A delegate sequence builder might do the trick.
Check out this blog:
https://odetocode.com/blogs/scott/archive/2018/09/17/how-the-next-delegate-works-in-asp-net-core-middleware.aspx
Here’s a good walkthrough of the builder pattern: https://youtu.be/1JAdZul-aRQ.
Take a look at Jimmy Bogard’s MediatR library. You can use it to implement commands with validators and decorators.
https://github.com/jbogard/MediatR