Today, my friend Craig asked me for some help with changing the currency in his Umbraco Commerce (Vendr) website.
He already had the code to change the currency, and was trying to use that code in the master template of his site. The problem was that when the code was called in the master it was too late in the pipeline and so the the currency didn't change until the next time the page was reloaded.
With that in mind, I realised we needed to use a notification handler to call the code earlier in the pipeline.
This is the Notification Handler that he wrote which hooks into the Routing Request Notification:
using System.Globalization;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Notifications;
using Umbraco.Cms.Web.Common.PublishedModels;
using Vendr.Core.Services;
using Vendr.Core.Session;
namespace UmbracoProject.Core.Notifications;
public class CurrencyChangeNotificationHandler : INotificationHandler<RoutingRequestNotification>
{
private readonly ICurrencyService _currencyService;
private readonly ICountryService _countryService;
private readonly SessionManagerAccessor _sessionManagerAccessor;
public CurrencyChangeNotificationHandler(ICurrencyService currencyService, ICountryService countryService, SessionManagerAccessor sessionManagerAccessor) {
_currencyService = currencyService;
_countryService = countryService;
_sessionManagerAccessor = sessionManagerAccessor;
}
public void Handle(RoutingRequestNotification notification)
{
// Change currency
var requestBuilder = notification.RequestBuilder;
var content = requestBuilder.PublishedContent;
Guid storeId = content.AncestorOrSelf<Home>().Store.Id;
var countryCode = requestBuilder.Culture.ToString().Split("-")[1];
var sessionManager = _sessionManagerAccessor.Instance;
var countries = _countryService.GetCountries(storeId);
var cultureCountry = countries.FirstOrDefault(country =>
country.Code.Equals(countryCode, StringComparison.CurrentCultureIgnoreCase));
var currency = _currencyService.GetCurrency(cultureCountry.DefaultCurrencyId.Value);
sessionManager.SetDefaultPaymentCountry(storeId, cultureCountry);
sessionManager.SetDefaultCurrency(storeId, currency, true);
}
}
And this was the Composer which he wrote to make sure that the notification handler was registered:
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.Notifications;
using UmbracoProject.Core.Lib;
using UmbracoProject.Core.Notifications;
namespace UmbracoProject.Core.Composers;
public class Composers: IComposer
{
public void Compose(IUmbracoBuilder builder)
{
// Custom Change Currency routines
builder.AddNotificationHandler<RoutingRequestNotification, CurrencyChangeNotificationHandler>();
}
}
Now on each page request it makes sure that the correct country code and store Id is set, which in turn sets the default currency for that country.