Skip to content

Mediator v2.0

The Road Here

Only a little over 3 months, I released v1.0 of Mediator. Since then, I’ve been adding features as fast as they come to mind. The focus on making the Mediator pattern upfront for apps (in my opinion) has been a huge success. I’ve been using it in my MAUI apps for offline, caching, & resiliency middleware. The amount of time it saves me is pretty crazy.

Since version the v1 release, I’ve been adding a ton of features including an ASP.NET extension for HTTP endpoints straight to Mediator request handlers. Quite recently - I found a lot of mediated calls would end up just wrapping HTTP calls done with Refit or Kiota. I decided to add my own source generator to deal with this. Check out the HTTP Extension for more on this.

What’s New in 2.0

So what does 2.0 bring that requires a major version bump? The first major feature is that I’ve brought the offline, stream replay, and user error notification middleware to Blazor webassembly. This middleware was already present in MAUI, but Blazor needed a “connectivity” & “storage” service to match MAUI.

The second major feature is that I’ve been moving a lot of the middleware to be configured via Microsoft.Extensions.Configuration. This allows you to configure middleware and handlers in a global way and without polluting your code with attributes everywhere. Below is an example of all configuration we offer now:

{
"Mediator": {
"Http": {
"My.Namespace.Contract": "https://shinylib.net/newbase",
"My.Namespace.*" : "https://shinylib.net/therestofhtenamespace",
"*": "https://shinylib.net/everythingelse"
},
"Performance": {
"*": {
"ErrorThresholdMilliseconds": 5000
}
},
"Offline": {
"Sample.Handlers.OfflineRequestHandler": {
"AvailableAcrossSessions": true
}
},
"ReplayStream": {
"Sample.Handlers.MyRequest": {
"AvailableAcrossSessions": true
}
},
"TimerRefresh": {
"My.Contacts.HttpData": {
"IntervalSeconds": 10
}
},
"Resilience": {
"My.Namespace.ResilientContract": {
"RetryCount": 3,
"RetryDelay": 500
}
},
"Cache": {
"My.Contacts.*": {
"Priority": "High",
"AbsoluteExpirationSeconds": 300,
"SlidingExpirationSeconds": 60
}
},
"UserErrorNotifications": {
"*": {
"*": {
"Title": "ERROR",
"Message" : "Failed to do something"
},
"fr-CA": {
"Title": "ERREUR",
"Message" : "Échec de faire quelque chose"
}
}
}
}
}

So let’s unpack this. The first thing to notice is that we have ”*” to “glob” a namespace or ALL calls. If you want to attack a specific contract, just fully label it. We will find the nearest namespace to your contract before giving up as “not enabled” for a feature to be disabled on a contract.

What’s Next

I’m pretty happy with this release, but I still have a ton of ideas. All the stuff you can do around the handlers with middleware is really exciting. Have an idea for the mediator, head on over to GitHub and add a feature request. I’m always looking for new ideas.