Coffee roasters in Sweden – a review

If you are serious about Espresso quality, you know you must buy from a specialty roaster – not from the super market. You will pay more premium price, at least 300kr per kg, and easily up to 500kr per kilo or more, compare to around 100-150kr per kg from super market. In return, you get:

  • The obvious better coffee quality. Most if not all decent roasters only roast specialty coffee, meaning they not only taste good, they have minimal defects, especially small rocks. A bad bean will only ruins one cup, at most. But a pebble can destroy your precious coffee grinder. Your grinder will thank you for the uniformity of specialty coffee beans you buy from roasters.
  • Much better freshness. Most, if not all coffees from super market only have “expired date”, not “roast date”. You can probably guess the roast date by subtracting expired date by 24 months and the most fresh one I could find, was two months old. At this point the coffee already started degrading in quality. In contrast, when I buy from roaster, it is always less than 1 week from roast date, which is clearly printed on the bag. As a rule of thumb, you should finish your coffee in less than 8 weeks from roast date.
  • Much better roasted. Most coffee from super market is roasted with super hot air (800*c) in very short amount of time. This allows the roaster to roast ton after ton, but with the cost of coffee flavor. Specialty coffees are often roasted in much smaller batches, an a longer time, for the flavor can develop properly.
  • Traceability. You only know coffee from super market by their country origin, and that’s it. But for specialty coffee, you will know the region which produced the coffee, and in many cases, even the farm that produced it.
  • Last but not least, support for local businesses. Specialty roasters are small businesses in your city, or even area. Buying from them means you support your local economy. Many roasters also have direct trade with the coffee farms, which means you give more directly support those famers. Most farms that grow specialty coffee also follow practices regarding sustainability (and due to high price of specialty coffee, they can sustain their business with considerable smaller farms). If you care about sustainability and people likelihood, buying from roasters is a better way to support that.

What to look for from Coffee roasters

A coffee bean bag with one way valve is a must (In case you didn’t know, newly roasted coffee bean will release CO2, and that valve is important to let the CO2 out – but not let the air in) . Best if it is resealable. otherwise you would have to move the bean to an airtight container to keep them fresh for longer. Also, buy coffee beans if you can. Ground coffee starts losing their aroma and flavor just 30 minutes after grinding. Airtight container can only slow that down a little bit.

All of the roasters below have good coffees – the beans have consistent color, size and shape. My machines, techniques and taste are not at the level I can distinct each flavor, so I will focus on the services instead.

StockholmRoast (Stockholm Roast – The House of Roasting)

They offers good prices, but no subscription. They ship through DHL to the service point, with free shipping, which is nice, but not the best (compared to other options below)

The bags are well packaged, so you get proper protection of your precious coffee beans. But they also glue a plastic bag on the package (for the shipping information and the receipt), which is quite tiresome to remove for proper recycling.

They also offer better price for 1kg bag, compared to 4 bags of 250. While this is somewhat understandable from a commercial perspective, it means it’s harder to keep your coffee fresh, if you want to save some money. They probably should offer 500gr bag.

Another minus, I don’t recall their bag is resealable. Also the ink on the bag could easily get into you hands, especially if they are a little wet. They are, however, not very easy to wash off.

None of those things are critical, but they would be very nice to be fixed!

LYKKE KAFFEGÅRDAR Nyrostat kaffe | Direkt från gården hem till dig | Lykke Kaffegårdar (lykkegardar.se)

Lykke offers subscriptions, with 10% discount, which is good. Importantly, they ship directly to your mailbox. Order, and in one day or two, you find your favorite coffee bags in your mailbox. Convenient, huh?

You can easily manage subscriptions, including changing it, skip one delivery, or cancel it, which is a huge plus.

Their bag design is beautiful, and I absolutely like it. To make things better, they even included 2 bags of tea in my first shipment – a very good way to advertise.

Their espresso range, however, is quite limited. There is only one Bam! that is dedicated for espresso. Wish they offer more choices.

UPDATE: I bought 2 bags of BAM! from them due to their Black Friday sales, and were sent ones which were roasted on October 28th, which means more than 1 month when they arrived. I was disappointed, and sent them a letter. They apologized and offered a 30% coupon for my next order. While receiving one month old coffee bags is no fun, I think the way they handled it was nice. I took the offer.

Kafferosterietkoppar Upptäck vårt nyrostade kaffe | Kafferosteriet Koppar

They offer subscriptions as well, and with 20 SEK discount per bag, which is very nice. However, to change the subscription, you need to email them directly. It’s OK-ish, but I would definitely prefer the Lykke approach.

They also ship directly to mailbox, and their shipping was very fast. I ordered on Wednesday, and two of the bags appeared in my mail box on Thursday. I don’t know if they forgot, or intentionally did not send a notification email, but that was a nice surprise.

One incident with my first purchase: Out of two bags is almost empty (there were like, 30 coffee beans inside them). I mailed them to let they know, and they were happy to ship a replacement to me. In the end, everything is resolved quick and easy, but I’d hope they did have a bit more of quality control for their coffee bag.

Standout coffee https://www.standoutcoffee.com/

Their subscription is 25e (yes, euro, equivalent to about 260kr) for 100gr of coffee, or 2600kr per kilo. The reason for such high price is because it’s “Gesha village”, the most expensive coffee in the world, and they offer worldwide free shipping.

2600kr per kilo is unfortunately way too high for what I can pay for coffee, and with 100gr you might get 1-2 cup of good espresso out of it (considering you have to dial in), so thanks, but no thanks.

Drop Coffee

Apparently they are the most popular in Sweden, so I should try them out soon. They are transparent about their FOB price, which is nice. I was hesitant about their Google reviews (“only” 4.3 on 5.0, so quite lower than other roasters in this list), but it turned out it has to do with their coffee shops (which should be affected by many other things) than their actual roasting business.

Pouring coffee roastery (hallakafferosteri.com)

This is my favorite now. They offer coffees at very good price – especially if you buy in batch (5 or 10 bags of 500gr), and they usually have 10 or 15% off coupon. I buy with a few friends, and we split the bag – and I end up with around 250kr/kg (2x500gr bag), and sometimes even only 220kr. They do ship free to service point for order more than 499kr.

I can’t notice a difference between their coffee and other roasters, so I’m happy with that setup, for now.

Sage/Breville Barista Pro review

This is a super short review of this fairly popular espresso machine. I bought this last year, despite a lot of arguments from my wife. She even threatened to throw it out if I bought. I did. And now she demands latte/cappuccino every day!

My budget was pretty limited at that point, so other decent options (HX or even dual boiler machines) are out of reach. Barista Pro fits in my budget (and kitchen), and when Amazon had a very good discount on them, I pulled the trigger.

I was happy.

When it was new

Don’t laugh.

Pros:

Sage/Breville is feature oriented, and when you open the box, you have everything you need to get going: a milk jug, a 54mm portafilter with 4 different baskets (2 double shots (1 pressurized, 1 non pressurized), 2 single shot), and of course, a grinder built-in. If you are new, this is hugely important. Some sellers do not include the milk jug, or even tamper (looking at you, Lelit!), and it’s bad that you are excited to open your new fancy espresso machine and realize you can’t make a decent cappuccino due to lacking equipment. The UI is intuitive and easy to work with. Once you understand the basics, using the machine, UX wise, is simple and easy.

The flow is well defined, and smooth – you take the portafilter, put it in the holder and click – the grinder grinds coffee for you, in the fineness you chose and the time you pick. Then you take the tamper (attached to the machine using a magnet, a pretty smart design), tamp it, put it in the head, place your cup, and press a button. It is the convenience you are paying for.

Cons:

Once you open the box, you quickly realize this machine is not built to last. It’s a thin layer of stainless steel outside of plastic. Build quality is … fine, but don’t expect the same quality as Italy-made machine. It’s been reported that while Sage/Breville service is very good during warranty, but one you are out of warranty, you have to pay hefty fee for repairs, because they just break down. And repair usually means “replace”.

The machine is advertised as “3s start up time”. You press a button, and the machine is ready. Truth is, however, if you want to get better shots, you need to wait for at least 10m, and flush 1 or 2 cup first. With the empty portafilter inserted, press the double shots button, and let the hot water flows through it. It warms up the head, the portafilter, and make sure you get stabilized temperature in the boiler. Otherwise, your cups will be incredibly sour. Or some times, both sour of bitter!

The machine overall is quite noisy, both the grinder and the pump. it’s not a big deal until you have tried quieter machines. This is even more true when you have empty grinder, it sounds like it gonna break (it is fine to grind in a short amount of time, mind you)

Another downside is that this uses a 54mm portafilter. The portafilter itself is fine, well made and solid, but after a while, you will want to try out new things, like bottomless portafilter. But this is when you realize you are left with either options: 1. buy cheap no brand products from China or 2. absurdly expensive or 3. both. Should it come with a 58mm portafilter which is the “industry standard”, you will have more options from reputable brands, at reasonable prices.

The built-in grinder is merely adequate, it’s step conical burr grinder (some says it’s actual stepless, but you will need some “tricks” for that). You will be able to grind espresso with it, but not with the fineness adjustment needed to extract the best out of your coffee. Whenever you can, upgrade to a good espresso grinder would make a huge difference in your espresso. (Note: a good espresso grinder can easily cost $400 or more!). Also, cleaning it is not the easiest task – it’s doable, but requires additional tools (like a vacuum cleaner) to do it properly.

It’s messy to grind a double shot (18-20gr), because some coffee ground will be left on the portafilter holder, or on the drip tray. Yes you can use a dosing cup, or a funnel, but you will, once again, agonize the limited options of a 54mm portafilter.

So so

The included tamper is “serviceable”. It can be tucked in which is need, and it does it job. But I’d suggest to buy a nice, ergonomic tamper as soon as you can. It’ll make your experience much more enjoyable.

The steam wand is ok, but it is on the weak side, and it produces wetter steam than I would like. It is enough to froth the included milk jug, but if you want to use a bigger jug (so you can make 2 cappuccinos or 1 big latte in 1 go), it’ll not powerful enough.

The included milk jug is OK. Good ergonomic, but the wall is a bit too thin, so it gets hot very quickly. I had hard time holding it when it reaches 55*C. In comparison, my Motta one is only fairly warm even when the milk reaches 60*C (that is however not the perfect thing)

Summary

In the end, Barista Pro is a well rounded, full featured espresso machine. It’s a budget/entry one, capable of making good shots. You have everything you need to start going, but it also does not really excel in neither brewing, nor steaming. Once you horned your skill, upgrading to a better grinder, and a better machine 58mm portafilter will be a big step.

If you want to learn and can spend, of course.

How to spot Facebook Marketplace scams

With the pandemic going for more than 1 year (And still no end in sight), shipping has become a popular option for shopping on Facebook Marketplace. And that’s why scamming skyrocketed. To make the matters worse, Facebook provides little to no shopper protection. Your safety is yours to care about. So how to spot and stay away from scam, beside of other health safety procedures?

If a deal seems to be too good to be true, it is likely is. At this point of writing, PlayStation 5 is most frequently scammed. Anything which is less than 5500 SEK for the standard edition is suspicious. Scalpers who sell high demand product at much higher price than MSRP are another issue, but they are not mutually exclusive. A scammer can try to sell at higher price to make it more “authentic”, but most will try to lure more unsuspecting buyers by low prices.

Photos with low quality are another red flag. It is likely that the seller did not take the photos himself/herself but download from other listing, then upload again. Every time you upload photos to Facebook they reduce the quality a bit to reduce size. Do that a few times and you will notice the artifacts in the photo. If the photo is blurry or pixeled, take that as a warning.

Commerce profile too new: anything newer than 2019 should be questionable. Especially someone with very few friends. Check their profile if you think they are an actual person behind it.

Only offer shipping is another red flag. While some authentic sellers would prefer less contact, it is uncommon. Shipping means you have to Swish (a quick money transfer method in Sweden) before hand, and that means you have no guarantee once you did. If you Swish

Also, check if that seller is selling multiple items, and for each item, a new location is listed. That means the seller is trying to scam you into thinking he/she is far away, so shipping is required.

An example of a scammer

My not very proud experience is that I was scammed myself. I was browsing the MarketPlace, and saw a game (Ratchet & Clank PS5), for a very good price (250kr compared to normally 450-500kr or even more, because the game was new). Contacted the seller, he was responsive, and even offered 50:50 split on shipping cost. I checked his profile, everything seems to check out, so I took the bait. Swish-ed him 270kr. Waited for a few days. The game never came. Ask him if he shipped it, he said yes. Waited for a few days more and asked him what would he do. He never replied. Only a few days later, another buyer reported him for scamming. Same tactic, only this time he admitted to that buyer he never sent the game (a different one), and promised to refund the money. He never did.

Deep down, I wanted him to not be scammer. I even felt a bit sorry for him. What state would he be in, so he has to scam over that small amount of money. Only after a while, I realized he did it systematically. He scams that amount so most people will just accept it and move on. Even if they report him to the police (as the said buyer did), they will likely not do anything about it. He gets away with scamming multiple people like that.

Facebook protection for buyers is a joke. The most you can do is to report the listing as Scam, and they still do nothing about it. So better be cautious and protect yourself.

HP inkjet printer is a scam

I occasionally need to print something, and based on the reviews in rtings.com, a HP OfficeJet Pro 9013 was probably my best bet for performance/price (given the top choice is not available anywhere in my region – Europe/Sweden). Researching showed some shady business practice by HP for their inkjet printers, but against my best judgement, I decided to try my luck.

My mistake.

The printer worked fine for a while. Nothing particularly good or bad about it. It prints, it scans, it fits what I need. I bought it new at a reasonable price, and got 3 years commercial warranty which seems like a good deal.

But the honeymoon does not last long.

The yellow cartridge went out first. It does not let me print even black and white document.

Why do I need yellow when I only want to print B&W?

This is crappy business, and I was warned, but OK fine. I signed on for this. So I bough the yellow cartridge to replace the old one. All good? No, this time, it’s cyan that is out of ink.

You can see Magenta is still there

Even without printing one page.

I am forced to buy cyan. Just to print one page, in black and white.

And then, when cyan cartridge arrives, I replaced the old one, and guess what, magenta is out!

Until it is magically out

Even without printing one page.

I can’t help but to heavily suspect that HP does that intentionally.

The printer fails to do its job when you need it, sometime sorely. This entirely defeats the convenience of having your own printer at home. I could have just printed it by a service, and be done with it.

I called HP support and told that “the cartridges should be replaced at the same time”, and “just get a new cartridge and it will work”. You can see, that is less than helpful.

This is simply a terrible, terrible practice from HP (and sadly it’s not uncommon in the business)

I learned my lesson – never again.

Announcing Pro Optimizely Commerce Cloud

Yes, you guess it right, it’s a(nother) book

It has been 5 years since I started Pro Episerver Commerce back in early 2016. The book was a success, not as big as I hoped for, but definitely bigger than I expected. Tackling a niche market, it was fairly popular within the community, and it gave me a lot of happiness (and some pocket changes) to see that it helped many developers to understand and use the framework – which I help created, and love – better.

So much has changed in the last 5 years.

I have my first kid, and a second one. I left Commerce development team, to work on my own, then have a small team. Episerver bought Optimizely, then rebrand.

And so much more has happened with Episerver Commerce, more than just being renamed to Optimizely Commerce Cloud.

It deserves a new book!

To celebrate my 10th anniversary with Episerver (now Optimizely), I am proud, and excited to announce the second edition of Pro Episerver Commerce – Pro Optimizely Commerce Cloud. Most of the content written in Pro Episerver Commerce is still very much applicable, but I feel there is a need to refocus and expand on important parts.

You can register your interests today at https://leanpub.com/prooptimizelycommercecloud

Purchasers of Pro Episerver Commerce – even if you obtained the free version – will receive a 40% discount code for the new book – so don’t miss it.

I will see you there!

Lessons learned about exception handling and logging

Exception handling and logging is essential part of any site. Your site will eventually run into problems, and as a developer it’s your job to make sure that you have enough – or at least helpful – information to look into problems. From my years of diagnosing and root cause analysis, these are the most common problems about exception handling and logging. You (or any developers that come after you) can thank yourself later.

Empty try catch is almost always bad

In my early days of professional programming, I saw a colleague – several years senior to me, fortunately, not at Episerver – write a lot of this code, basically in each and every method:

try { 

//do stuffs

}

catch {}

You surely don’t want to show a YSOD screen to your visitors, but keep this in mind – this is almost always bad. You are trying to hide errors, and even worse, trying to swallow it. This should be a red flag for any code review.

There are cases when you truly, really want to swallow an exception. It’s rare, but it’s a reality. In such case, make sure to explain why you have an empty catch in comments.

Don’t catch exception only to throw it

Does this look familiar to you, if yes, then your code base have a problem (or actually, two)

try 
{
//do stuffs
}
catch {Exception ex}
{
throw ex;
}

But why?

  • It is wasting a try catch doing nothing of value. Log in, wrap it in a different type of exception (with probably more information, not just rethrow the exception
  • throw ex; actually reset the stacktrace. If you simply want to rethrow the exception (after doing meaningful stuffs with it), use throw; instead. That will preserve the precious stacktrace for exception handling at higher level.

Logging only the message is a crime

Someday, you will find an entry in your log looks like this

Object reference not set to an instance of an object.

And that’s it. This is even worse than no message – you know something is wrong, but you don’t know why, or how to fix it. It’s important to always log the full stacktrace of the exception, instead of just the message, unless you have a very good reason (I can’t think of one, can you?) not to.

Verbose is better than concise

This is an extension of the above lesson. You are already logging the entire stacktrace, but is your exception message helpful? One example is this

[InvalidOperationException: There is already a content type registered with name: PdfFile]
   EPiServer.DataAbstraction.Internal.DefaultContentTypeRepository.ValidateUniqueness(ContentType contentType) +222
   

Which other type was registered with same name? Is it a built-in (i.e. system) type, or a type from a 3rd party library, or a type that you added but forgot yourself?

In this case, a much better exception message would be:

There are two or more content types registered with name PdfFile

Assembly1.Namespace1.PdfFile
Assembly2.Namespace2.PdfFile

Exception message is not only showing an error/unwanted situation has happened, but it needs to be helpful as well. When you log a message, you should try to add as much information as you can so the ones who will be looking into the issue can make a good guess of what is wrong, and how to fix it. There is virtually no limit on how verbose you can be, so feel free to add as much information as you need (I’m not asking you to add the entire “War and Peace” novel here, of course). You can thank me later.

Commerce relation(ship), a story

There are two big types of relations in Episerver (Optimizely) B2C Commerce: relations between entries and nodes, and between nodes. As you will most likely have to touch one or another, or both, sooner or later, this post aims to give you some understanding on how they are structured/work.

Node-Entry relation

When you add a product (or variant, or package, or bundle) to a category, you are creating a NodeEntryRelation. And there are a two types of NodeEntryRelation

  • Primary NodeEntryRelation, which means the category is counted as true parent of the entry. Each entry can only have at most one primary NodeEntryRelation (Which means it can have no primary NodeEntryRelation at all).
  • Secondary NodeEntryRelation, which means the entry is linked to the category. You do that when it makes sense for the product to be in additional categories. for example, a GoPro can be in Camera (primary category), but can also be in Sport Gears (linked). An entry can have no, or multiple secondary NodeEntryRelation.

The concept of primary NodeEntryRelation was added to Commerce 11. Before that, it’s a bit more of a guess work – the “main” category is determined by the sort order – the relation with lowest sort order is considered “main relation”. That introduces some inconsistency, which prompted the rework on that.

What is the main different between those two things? For one thing, access rights. For Commerce, you can set access rights down to categories, but not entries. The entries will inherit access rights from their true parents (i.e. primary nodes). An entry without primary node-entry relation is considered the direct children of a catalog, and inherits its access right settings.

Another smaller difference is that if you delete a category, true children entries will be deleted. Linked entries will only be detached from that category.

NodeEntryRelation can be managed fully by IRelationRepository, using the NodeEntryRelation type, and you can use a few extension methods to make it easier – for example EntryContentBase.GetCategories().

How are your actions in Catalog UI reflected on a data level:

  • When you create a new entry (product/SKU/etc.) in a category, you create a primary node-entry relation for them
  • When you move (cut then paste) an entry to a new category, you are creating a new primary node-entry relation. If the entry already has a primary node-entry relation, the new one will take over.
  • When you link/detach an entry to/from a new category, you are creating/removing a non-primary node-entry relation

Node-Node Relation

Like Node-Entry relation, a node can be a true parent of a node, or just be a “linked” parent.

Unlike Node-Entry relation, Node-Node relation is quite different that it’s separated in two places.

  • Linked nodes are represented by NodeRelation(s) (it might be interesting to know that NodeRelation is the parent class of NodeEntryRelation. The interpretation is that a NodeRelation is – a relation of a node, which can be with another node, or an entry)
  • There is no primary NodeRelation, the true parent node is identified by a property of the category itself. When you have a NodeContent content, then the ParentLink property points to the true parent.

For that reason, a node will always have a true parent, either a catalog, or a node. You can’t use IRelationRepository (and therefore, ServiceAPI) to manage (delete or update) a true parent of a node , you would have to:

  • Set its ParentLink to something else
  • Use IContentRepository.Move to move it to a new parent.

Note that this is the limitation of the Relations API in ServiceAPI. You can technically change the ParentLink of a node and update via POST. It’s just more work and not as intuitive as the Relations API.

Why the disparity, you might ask? Well, a lot of design decisions in Commerce comes from historical reasons, and after that, constrained resources (time/man power) and priority. While the disparity is probably not the best thing you want, it still works fairly well, and if you understand the quirk then it is all well.

Get contact by email address

If you are using Episerver Commerce (or should I say, Optimizely B2C Commerce), you will, at some point, need to get the contact by an email address. That sounds like an easy enough task, until you realize that the class to manage customer contacts CustomerContext has no such method. You will need to find another way, and this is one way you can do it

CustomerContact contact = customerContext.GetContacts().Where(m => m.Email == email)?.FirstOrDefault();

Of course this is not the optimal – avoid it if you can. First of all it loads a lot of contact just to find one. Also while it looks like you are getting all contacts (which is of course something to avoid), you are only get the first 1000 contacts by default, so the code above would return inaccurate result.

Is there a better way?

Yes of course.

Contact was built on “Business Foundation” – think of it as an ORM with extensions. Business Foundation allows great flexibility, with a few caveats. This is how you can find contact by email address:

            try
            {
                var filterEl = new FilterElement("Email", FilterElementType.Equal, email);
                return
                    BusinessManager.List(ContactEntity.ClassName, new[] { filterEl })
                        .OfType<CustomerContact>()
                        .FirstOrDefault();
            }
            catch (ObjectNotFoundException)
            {
                //Safe guard
                return null;
            }

BusinessManager does not have a Get method, so we are use List instead. Note that Email is supposed to be unique, so this should not have any down side with performance (see note below).

This is not limited to email, or to contact. You can find contacts by other properties, or get an Organization with same technique.

It is very important to note, however, this need a proper index on Contact tables, to make sure you are not killing your database.

Don’t share HttpContext between threads

HttpContext is not designed to be thread-safe, which means you can run into nasty things if you share a HttpContext between thread. For example, this is one of the things that can happen: One (or more) thread is stuck in this:

mscorlib_ni!System.Collections.Generic.Dictionary`2[[System.__Canon, mscorlib],[System.__Canon, mscorlib]].FindEntry(System.__Canon)+ed
EPiServer.Web.Routing.Segments.Internal.RequestSegmentContext.GetOrResolveContextMode(System.Web.HttpContextBase)+9b
EPiServer.DataAbstraction.Internal.ProjectResolver.IsInEditMode()+17
EPiServer.DataAbstraction.Internal.ProjectResolver.GetCurrentProjects()+17
EPiServer.Core.Internal.ProjectPipeline.Pipe(EPiServer.Core.ContentReference, System.Globalization.CultureInfo, EPiServer.Core.LoaderOptions)+1c
EPiServer.Core.Internal.ProviderPipelineImplementation.GetItem(EPiServer.Core.ContentProvider, EPiServer.Core.ContentReference, EPiServer.Core.LoaderOptions)+109
EPiServer.Core.Internal.DefaultContentLoader.TryGet[[System.__Canon, mscorlib]](EPiServer.Core.ContentReference, EPiServer.Core.LoaderOptions, System.__Canon ByRef)+11e
[[StubHelperFrame]]
EPiServer.Core.Internal.DefaultContentLoader.Get[[System.__Canon, mscorlib]](EPiServer.Core.ContentReference, EPiServer.Core.LoaderOptions)+63

If you don’t know why this is scary, this is any infinite loop, meaning your CPU will be spent 100% in to this Dictionary.FindEntry, unable to do anything else. The only way to solve this problem is to restart the instance.

That is caused by unsafe accessing of a Dictionary – if you have a thread that is enumerating it, and another thread trying to write to it, it is possible to run into a dead end like this.

And HttpContext just happens to have many Dictionary properties and sub-properties. HttpContext.Request.RequestContext.RouteData.DataTokens is one of them (And a reason the code above ended in a disaster), making it vulnerable for this kind of problem. Which is exactly why it is not recommended to share a HttpContext between threads.

Sometimes, you can just set HttpContext.Current to null. Sometimes, you need to take a step back and ask yourself that do you really need to run things in parallel?

Get exported Personalization catalog feeds

There are cases that you want to get your Personalization catalog feeds in zip format, maybe to make sure the customizations you have done are there (and are exactly what you want to), or you need to send them to developer support service for further assistance (like why your catalog feeds are not properly imported). Theoretically you can log in as an admin, and go to https://<yoursite>/episerverapi/downloadcatalogfeed to download the feed. But there are few problems with that.

First of all you might have more than one catalog, and the link above only allows you to download the latest one. Secondly it might fail to give you any catalog feed at all (With “There is no product feed available. Try run the scheduled job first.” error, even if you already ran the Export Catalog Feed job. There is currently no known fix for that). Is there a way to simply get the data?

Yes, there is. It’s not fancy, but it works. All your catalog feeds will be put in appdata\blobs\d4a76096689649908bce5881979b7c1a folder, so just go there and grab the latest ones. appdata is the path defined in your <episerver.framework>\<appData> section.

What if you are running on Azure? It is the same “folder”. Use Azure Storage Explorer to locate the blob. If you are running on DXP, get in touch with developer support service and they’d be happy to help.

I originally planned to write a small tool to easily download the catalog feeds, but it turned out the Episerver Blob APIs have no way to list content of a container, so a manual, simple way is better this time.