A curious case of memory dump diagnostic: How Stackify can cause troubles to your site

It’s been a while since my last blog post, and this time it will be fun time with windbg. One of DXC customers has been having problem with instances of their site hang and restart. We at Episerver takes the availability and performance of DXC sites very seriously, therefore I was asked to help diagnosing the problem. It’s something I’d like to do and to learn anyway, so game is on.

The golden standard for looking at the kind of those problems is still the tried and trusted Windbg. With the help from the Managed Services Engineer, I was able to access several memory dumps from the site. Most of them were taken when the site stalled, which is usually the most useful moment because it should contain the most critical piece of information why the stall happened.

Continue reading “A curious case of memory dump diagnostic: How Stackify can cause troubles to your site”

Episerver Commerce: A problem-solution approach is now draft complete

6 months ago I announced that I was working on a second book on Episerver Commerce. Unlike the first one where I tried to provide a systematic approach about the framework, this book focuses on the bite-size recipes, each one is a solution to solve a real world problem.

It’s one problem solved, at a time.

The world is big and the possibilities are endless, there might be more than one solution to a problem, but I tried to give the best one to my knowledge, experience. I hope that by talking about it, I also give information about how the API:s work, what to use, what should be avoided. what can be better, what are the best practices … , so you can develop solutions to your own problems, or even, come up with better solutions than mine.

If you manage to do that, don’t forget to share your solutions as a blog post on World forums, to help the ones come after you!

The cover I spent a day one. At least it's colorful, right?
People asked me: why foods? Well, because it’s a recipe book.

And now I’m proud to announce that the book is draft complete. Which means I’m happy with the content of the book. I will not stop there, new recipes and/or improvements will be brought from time to time, but if you want to buy the book, this is the time.

As always, writing a book is not an easy task – even with a smaller book like this. I would not have done it without the help and supports from the community. I would like to thank buyers who have bought the book, even from the very early days. I also want to thank people on World who gave me ideas and suggestions for recipes.

Not every news is good news, however. Consider the time and effort I have put into the book, and the new pricing policies of Leanpub (they increased their cut recently from 10% + 50c to 20%), I will increase the asking price of the book to $24.99, from $19.99. If you bought the book, you own the book and there is no extra cost for you. But if you are buying the book now, you would have to spend more money…

But …

… a Commerce book announcement is incomplete without some discount.

Now it’s something special: The book is dedicated to my daughter, who was born today! In the honor of me becoming a father – and to welcome my baby girl to the world, I’m offering 50% off for today: https://leanpub.com/epicommercerecipes/c/HelloWorld which is valid until the end of July 31st, GMT time.

I hope you find something useful from my book, and I welcome all new recipe suggestions and improvements!

Getting all non published variations

I got a question from a colleague today: A customer has multiple languages (8 of them). They need to make sure all variants are published in all languages. That is of course a reasonable request, but there is no feature builtin for such requirement. But good news is that can be done with ease. If you want to try this as practice, go ahead – I think it’s a good exercise for your Episerver Commerce-fu skills.

To do this task, we need the snippet to traverse the catalog from here https://leanpub.com/epicommercerecipes/read_sample

Continue reading “Getting all non published variations”

Watch out for Singletons

If you are a seasoned Episerver developer, you should (and probably, already) know about the foundation of the framework: dependency injection. With the Inversion of control framework (most common, Structuremap, but recent versions of Framework allow much more flexible options), you can easily register your implementations, without having to manually create each and every instance by new operator. Sounds great, right? Yes it is.

And Episerver Framework allows you to make it even easier by this nice ServiceConfiguration attribute:

[ServiceConfiguration]
public class MyClass 
{
}

so your class will be automatically registered, and whenever you need an instance of MyClass, IoC framework will get the best instance for you, automatically, without breaking a sweat. Isn’t it nice? Yes it is.

But I guess you also saw this from place to place

[ServiceConfiguration(LifeCycle = ServiceInstanceScope.Singleton)]
public class MyClass 
{
}

So instead of creating a new instance every time you ask it to, IoC framework only creates the instance once and reuses it every time. You must think to yourself: even nicer, that would save you a lot of time and memory.

But is it (nicer)?

You might want to think again.

Singleton means one thing: shared state (or even worse, Global state). When a class is marked with Singleton, the instance of that class is supposed to be shared across the site. The upside, is, well, if your constructor is expensive to create, you can avoid just that. The downside, of course, shared state can be a real b*tch and it might come back to bite you. What if MyClass holds the customer address of current user. If I set my address to that, and because you get the same instance, you’ll gonna see mine. In Sweden it’s not a real problem as you can easily know where I live (even my birthday if you want to send a gift, or flowers), but I guess in the bigger parts of the world that is a serious privacy problem. And what if it’s not just address?

And it’s not just that, Singleton also make things complicated with “inherited singleton”. Let’s take a look at previous example. Now we see Singleton is bad, so let’s remove that on our class. But what if other class depends on our little MyClass:

[ServiceConfiguration(LifeCycle = ServiceInstanceScope.Singleton)]
public class MyOtherClass 
{
   private MyClass _myClass;
   public MyOtherClass(MyClass myClass)
   {
        _myClass = myClass;
   }
}

Now I hope you see where the problem is. One instance of MyOtherClass is shared inside the side. And it comes with an attached MyClass instance. Even if you don’t intend to, that MyClass instance will also be shared. Same problem after all.

Singleton was there to solve one problem (or two), but it can also introduce other problems if you don’t really think about if your instance should be shared or not. And not just your class, the classes which have dependency on your class as well.

And it’s not just Singleton , HttpContext and Hybrid might also subject to same problem, but to a lesser extend. Any lifecycle that shares state should be considered: if you really need it and what you are sharing.

Lifecycle is hard, but it can also work wonder, so please take your time to make it right. It’s worth it.

Multiple catalogs: Without catalog name(s)

My previous blog posts about multiple catalogs in multiple sites setting here and here has helped one customer (hopefully more) to address their problem. They tried the approach and it works for them. Now they came back and ask if they can remove the catalog name from the URL entirely. Is that something that can be done. Fortunately, yes.

Before moving on, let’s be clear: this is obviously custom development and is not officially supported by Episerver. I.e. it’s neither tested and documented. Normally you would have to go to Expert Services for such requirement. For this blog, I provide those samples for free (you don’t even have to buy my book 😉 ), but remember I can only do that much. You have to test to see if it works for you (I of course do the basic testing), and if you run into problems later, I might not be able/available to help.

Now get back to the problem. Previously the router looks like this

    
protected override CatalogContentBase FindNextContentInSegmentPair(CatalogContentBase catalogContent, SegmentPair segmentPair,
        SegmentContext segmentContext, CultureInfo cultureInfo)
    {
        if (catalogContent.ContentType == CatalogContentType.Root)
        {
            CatalogContent definedCatalogContent;
            var definedCatalogLink = _contentLoader.Get(RouteStartingPoint).CatalogLink;
            if (_contentLoader.TryGet(definedCatalogLink, cultureInfo, out definedCatalogContent))
            {
                return definedCatalogContent;
            }
        }
        return base.FindNextContentInSegmentPair(catalogContent, segmentPair, segmentContext, cultureInfo);
    }

And it works great with  http://commerceref/en/fashion/mens/mens-shoes/p-36127195/ or http://commerceref/en/products/mens/mens-shoes/p-36127195/. But now they want to completely remove the catalog name from the url. They can’t make it works with http://commerceref/en/mens/mens-shoes/p-36127195/.

Why? Because the router is returning the catalog for /mens/ segment. In next segment (mens-shoes), we fallback to the default implementation, which can’t find any matching content as children of that definedCatalogContent .

The solution: Because we want the first-level category to appear as direct child of the catalog root, we would have to return it ourselves. Instead of returning the catalog, we return the first node that matches /mens/ segment.

        protected override CatalogContentBase FindNextContentInSegmentPair(CatalogContentBase catalogContent, SegmentPair segmentPair,
            SegmentContext segmentContext, CultureInfo cultureInfo)
        {
            if (catalogContent.ContentType == CatalogContentType.Root)
            {
                CatalogContent definedCatalogContent;
                var definedCatalogLink = _contentLoader.Get<StartPage>(RouteStartingPoint).CatalogLink;
                if (_contentLoader.TryGet<CatalogContent>(definedCatalogLink, cultureInfo, out definedCatalogContent))
                {
                    var nodes = _contentLoader.GetChildren<NodeContent>(definedCatalogLink);
                    return nodes.FirstOrDefault(n => n.RouteSegment.Equals(segmentPair.Next, StringComparison.OrdinalIgnoreCase));
                }

                return null;
            }
            return base.FindNextContentInSegmentPair(catalogContent, segmentPair, segmentContext, cultureInfo);
        }

And it just works:

Now that’s just one part of the solution. We still need to make sure outgoing URLs respect that. I’ll leave that to you, as practice.

Index or no index, that’s the question

If you do (and you should) care about your Episerver Commerce site performance, you probably know that database access is usually the bottleneck. Allowing SQL Server works smoothly and effectively is a very important key to the great performance.

We are of course, very well aware of this fact, and we have spent a considerable amount of time making sure Commerce database works as fast as we could. Better table schema, better stored procedures, better indexes, … we have done all of that and will continue doing so when we have the chances. (And if you find anything that can be improved, you are very welcome to share your finding with us)

But there are places where the database performance improvement is in your hand.

Continue reading “Index or no index, that’s the question”

Multiple sites: Building the outgoing URLs

In previous recipe we talked about multiple catalogs with same “UriSegment” – which we had a working implementation for incoming URL, i.e. when a customer visit a product url, we know which catalog we should choose from. But we still need to cover the generation of outgoing URL. I.e. when we link a product (For example, from a campaign page), we need to generate an URL which take the “catalog-less” pattern into account.

We need to understand how the outgoing URL is built. The hierarchical router builds the URL by the `RouteSegment` of contents. However, we want to the urls appear to have same catalog, so the `RouteSegment` part for the catalogs must be the same, regardless of the true catalogs. Because all catalogs are on same level, their `RouteSegment` must be unique – and this is enforced from Framework level (which is understandable, otherwise, how can it know which content to choose).

Continue reading “Multiple sites: Building the outgoing URLs”

Multiple catalogs with same url

This is an excerpt from my second book . The first chapter is available to read for free.

A business is having an Episerver Commerce instance with multiple sites and multiple catalogs set up. They want to make sure each site will use one catalog, and all of them will share the same url for catalog structure. So it’ll be “https://site-a.com/products/category/”, and “https://site-b.com/products/category/”. Site A and site B are using different catalogs.

Is this doable? Yes! It’s just a matter of magic with the routing. This time, we would need to do an implementation of HierarchicalCatalogPartialRouter ourselves. First, let’s create a template for it:

    
public class MultipleSiteCatalogPartialRouter : HierarchicalCatalogPartialRouter
    {
        private readonly IContentLoader _contentLoader;

        public MultipleSiteCatalogPartialRouter(Func routeStartingPoint, CatalogContentBase commerceRoot, bool enableOutgoingSeoUri, IContentLoader contentLoader) 
            : base(routeStartingPoint, commerceRoot, enableOutgoingSeoUri)
        {
            _contentLoader = contentLoader;
        }
    }

Continue reading “Multiple catalogs with same url”

Adding backslash ending to your URLs by UrlRewrite

It’s generally a best practice to add a backslash to your URLs, for performance reasons (let’s get back to that later in another post). There are several ways to do it, but the best/simplest way, IMO, is using UrlRewrite module. In most of the case, processing the Urls before it reaching the server code will be most effective, and here by using UrlRewrite we trust IIS to do the right thing. Our application does not even need to know about it. It’s also a matter of reusable. You can simply copy a working, well tested rule to another sites without having to worry much about compatibility.

Before getting started, it’s worth noting that UrlRewrite is an IIS module which is not installed by default, if you want to use it, then you would have to install it explicitly. Download and install it from https://www.iis.net/downloads/microsoft/url-rewrite .

And then we can simple add rules to <system.webServer><rewrite><rules> section in web.config. For the purpose of this post, this rule should be enough:

<rule name="Add trailing slash" stopProcessing="true">
  <match url="(.*[^/])$" />
  <conditions>
    <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
    <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
  </conditions>
  <action type="Redirect" redirectType="Permanent" url="{R:1}/" />
</rule>

If you are new to UrlRewrite, may be it’s useful to explain a bit on the rule. Here we want to add a rule which matches every url, except the urls which already end with backslash (/) already.

Continue reading “Adding backslash ending to your URLs by UrlRewrite”

Package equivalent promotion type in Episerver Commerce

Recently we got this question on how to create package-equivalent promotion type in Episerver Commerce, from https://world.episerver.com/forum/developer-forum/Episerver-Commerce/Thread-Container/2018/2/is-there-a-built-in-group-discount/

I already recommended to use package for such purpose, because of several reasons:

  • Package is a builtin feature, and is fully supported by the framework, both on UI level and API level.
  • It has been well tested and is very reliable to use.

However in a real world implementation, it might not be easy to just add package implementation. One reason would be if you rely on an external PIM to handle your catalog. Configuring it to support package can not be trivial.

So why not try to implement a package equivalent promotion in the promotion engine, to see if it works.

Continue reading “Package equivalent promotion type in Episerver Commerce”