A quick blog post about Content Testing feature of Sitecore and its unfriendliness towards Context.Site
I went through a few content testing scenarios recently and one thing really puzzled me: Content Testing dialogs stumble upon Context.Site.
Reference Storefront
If you try to set up a test in the Sitecore Commerce reference storefront and send the page through the workflow, here’s how the variants screenshots will look like:
The base controller is using Context.Site for view path resolution:
1 2 3 4 5 6 7 8 9 10 11 12
protectedstringGetRenderingView(string renderingViewName = null) { /* ShopName is a property on the CommerceStorefront object that is represented by an item at Context.Site.RootPath + Context.Site.StartItem */ var shopName = StorefrontManager.CurrentStorefront.ShopName; // ... conststring RenderingViewPathFormatString = "~/Views/{0}/{1}/{2}.cshtml"; // ... returnstring.Format(RenderingViewPathFormatString, shopName, "Shared", renderingViewName); }
And it won’t find anything in the shell site:
1 2 3 4 5 6 7 8 9
Nested Exception
Exception: System.InvalidOperationException Message: The view '~/Views/shell/Shared/Structures/TopStructure.cshtml' or its master was not found or no view engine supports the searched locations. The following locations were searched: ~/Views/shell/Shared/Structures/TopStructure.cshtml Source: System.Web.Mvc at System.Web.Mvc.ViewResult.FindView(ControllerContext context) at System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) ...
Habitat
Trying the same workflow with test in Habitat stumbles upon the validation step:
Here the Context.Site is being used for custom dictionary functionality:
1 2 3 4 5 6 7 8 9 10 11 12
private Item GetDictionaryRoot(SiteContext site) { var dictionaryPath = site.Properties["dictionaryPath"]; if (dictionaryPath == null) { thrownew ConfigurationErrorsException("No dictionaryPath was specified on the <site> definition."); }
// ... return rootItem; }
And it also errors out in shell:
1 2 3 4 5 6 7 8 9
Nested Exception
Exception: System.Configuration.ConfigurationErrorsException Message: 'No dictionaryPath was specified on the <site> definition'. Source: Sitecore.Foundation.Dictionary at Sitecore.Foundation.Dictionary.Repositories.DictionaryRepository.GetDictionaryRoot(SiteContext site) at Sitecore.Foundation.Dictionary.Repositories.DictionaryRepository.Get(SiteContext site) at Sitecore.Foundation.Dictionary.Repositories.DictionaryRepository.get_Current() ...
Alistair Deneys explained that Content Testing needs to run screenshot generation in context of shell to render unpublished content of different versions.
Content Testing needs to quickly learn how to do everything it needs in the context of the current site while getting everything from the master database.
While you probably shouldn’t use Context.Site for view path resolution - we now have official support for MVC areas, and probably shouldn’t use custom dictionary implementation - here’s my blog post on how to make standard dictionary items editable in Experience Editor, you should be allowed to use Context.Site in your page rendering logic if you need it.
Name __Display name Category ---- -------------- -------- 22565422120 Gift Card Departments AW007-08 Black Diamond Quicksilver II Carabiners AW009-08 Black Diamond Quicksilver II SaleItems AW013-08 Petzl Spirit Adventure Works Catalog ...
Adding Features
Features need to be exported in a special format. Different products in a given catalog may have different features and even have different number of them. Azure solves this by requiring features as a comma separated list of name value pairs:
PSObject is a dynamic type that you can modify on the fly. First, I extracted a collection of features into a new Features property. Then I applied features to become new properties on the product object. CSV export will be able to pick it up transparently. I hope.
CSV
It should now be easy to export the list as CSV. There’s a caveat though.
Both ConvertTo-CSV and Export-CSV will happily export the list for you but will normalize every record to the common set of fields.
You won’t see the features in the list. Here’s a trick to get every product in the export have its own features:
Instead of piping the entire set to the ConvertTo-CSV, I basically processed the list one by one in the foreach loop. I also removed the type info and the CSV headers. Azure doesn’t need labels anyway. Works like a charm!
There’s one more thing that I needed to do for Azure Recommendations API to absorb the catalog. As you could tell, the catalog format is not exactly CSV. Every line can have different number of fields basically. Neither does Azure backend use CSV parsing to read it.
The double quotes in the export above were taken literally. Azure would think that the SKU # is "AW007-08", for example. And then the commas in the descriptions where messing up the parsing as well. My next post will be about the Recommendations API itself and I will write more about it, but here’s the final version that produces a clean catalog export ready to go: