Piranha CMS and .NET 7

A brief look at my latest attempt to upgrade a Piranha CMS blog to .NET 7 and thoughts on the upgrade.
Håkan Edling and the good folks over at Piranha CMS have an ambitious slate of features and fixes for upcoming releases of the headless CMS. One could not blame them for withholding a build tailor made for version 7 of Microsoft's .NET Framework while version 6 is still available as a long term, supported product. Still, .NET 7 is supposed to have some performance benefits over its already venerable older sibling. Plus, the updated framework offers a number of new features like rate-limiting middleware and improvements to minimal APIs for ASP.NET Core which, naturally, leaves some developers hoping for a .NET v7 compatible build of Piranha.
Just released: Pirnaha 10.3.0 (ta-dah!)
As luck would have it, Piranha v10.3.0 was published on 18 Jan 2023, specifically, it seems, for Piranha developers who wanted to test out .NET 7. 🎉
Some History
Back in July of 2022, Andreas Ravnestad reported on Github that running a project created with the Piranha MVC Templates using .NET 7 failed due to a known issue with Automapper. In late September, The Automapper team released version 12.0.0 of Automapper which promised to fix the issue. Then, in November of last year, Magnus Baneryd suggested that he had gotten Piranha to work with .NET 7 by simply upgrading Automapper in the Piranha.Data.EF project file and kindly asked the Piranha team if they would be open to a Pull Request. He submitted a PR on the 5th of December 2022 which was merged the same day.
Magnus then politely asked on the 13th of January 2023 if his PR might be rolled into a patch that could be shipped out in advance of the upcoming 10.3.0 release. At the time, the roadmap for Piranha 10.3.0 had many outstanding issues waiting to be resolved and looked as though its publication would be well into 2023. But apparently, the Piranha team agreed to release a build for developers interested in .NET 7 and parked many of the outstanding issues onto later releases. Thanks, guys. 🙏
The 10.3.0 release of Piranha includes the following features and bug fixes:
- Upgrade
Automapper
to support .NET 7 - Slug Expansion
- Bump Newtonsoft.Json from 13.0.1 to 13.0.2
- User is never locked out on failed login attempts
- Field settings for regions are not always provided in JSON
Giving Piranha 10.3.0 with .NET 7 a try
I faced two (✌️) challenges when upgrading Piranha to 10.3 neither of which had anything to do with .NET 7. Instead, these two issues were caused by small changes to Piranha from my previous version (10.0.1).
☝️Changes to ISecurity.SignIn(object, string, string)
If you're using a custom security service to interact with Piranha, you may run into the same issue I did when upgrading from an earlier version of Piranha to 10.3.0. The SignIn
method's return type was changed with commit f6d4ce to help ensure that Piranha locked accounts when it encountered multiple password failures as outlined by Neutrino-Sunset in issue #1905. If, like me, you've run afoul of this change, simply modify your custom ISecurity
implementation to asynchronously return LoginResult
vice bool
in your version of SignIn(). Here's an example.
public async Task<LoginResult> SignIn(
object context,
string username,
string password)
{
var signInResult = await SignInManager.PasswordSignInAsync(
username,
password,
false,
true);
var result = LoginResult.Failed;
if (signInResult.Succeeded)
{
result = LoginResult.Succeeded;
}
else if (signInResult.IsLockedOut)
{
result = LoginResult.Locked;
}
return result;
}
✌️Native support for Webp caused runtime errors
Upon deployment, several (but not all) of my Piranha related web pages failed with the following cryptic error.
System.InvalidOperationException: Sequence contains more than one matching element
at System.Linq.ThrowHelper.ThrowMoreThanOneMatchException()
at System.Linq.Enumerable.TryGetSingle[TSource](IEnumerable`1 source, Func`2 predicate, Boolean& found)
at Piranha.Runtime.MediaManager.GetItem(String filename)
at Piranha.Services.MediaService.EnsureVersionAsync(Media media, Int32 width, Nullable`1 height)
I imagine this error won't affect most Piranha users upgrading to 10.3.0. In my case, however, I had implemented a custom IImageProcessor using the Magick.NET library (which has worked really well, BTW) specifically to support webp.
Webp is a lightweight image format introduced by On2 Technologies back in 2010. On2 was later purchased by Google who subsequently bolstered usage of this lightweight image type by promoting and indexing webp images. Until recently, Piranha did not support webp because (until release 10.2.0) its default implementation of IImageProcessor
was using an older version of the excellent ImageSharp library by SixLabors which didn't support the webp format until its version 2 release.
As part of my custom implementation of IImageProcessor
, I needed to explicitly add support for the webp format using this block of syntax.
// Add supported image formats
App.MediaTypes.Images.Add(".webp", "image/webp", true);
In the stack trace above, this snippet of code Piranha.Runtime.MediaManager.GetItem(string)
is attempting to get the image type from the image extension. In the case of webp type images it found two entries in Piranha's MediaTypeList which matched the "webp" extension. These two entries result in the error above since GetItem()
invokes SingleOrDefault()
which is designed to throw an exception when it encounters more than one of something. To fix the issue, I simply removed my code above which was adding duplicate support for webp to Piranha.
This was tricky for me to figure out (I may have a lesser mind 😊) and I wonder if perhaps a PR using FirstOrDefault()
or throwing a more informative exception would be helpful for other devs struggling with this very odd corner case. It would've helped me. I should probably submit a PR, for consideration at least, to the Piranha team.
In the end, I was pretty happy with Piranha CMS on .NET 7. I did, in fact, notice performance improvements to my website and consider the extra troubleshooting time well worth the effort. Thanks to the contributors and maintainers whose work made the upgrade possible.