Moving away from ICatalogSystem, part 0
I’m no fan of ICatalogSystem. Since the first day when I used it three years ago, I’ve always confused myself of which methods to use (Remember the confusing CatalogEntryResponseGroup?). The worst part was most of method returning CatalogEntryDto/CatalogNodeDto …, which is not a really nice way to access the property we need. Well, somebody might find love with ICatalogSystem, but definitely not me.
Then EPiServer Commerce 7.5 comes to rescue. Thanks to CatalogContentProvider, we now can use a new, better way, to work with Catalog content, with the way CMS guys have been doing since EPiServer 7.
This blog spot is intended to guide Commerce developer who is familiar with ICatalogSystem (you’re likely to move from Commerce R3 or prior release to 7.5. This is supposed to be a first part of a series, which I hopefully can finish!
Why will you love the content way
Firstly, this is the way being used in CMS. Working on a unified API:s allow you to increase the code- recognition. Once you’re familiar with the API:s, it’ll be much quicker for you to know what the intention the code are doing to do (code-read), and much unlikely for you to use wrong method (code-write). Let’s see an example:
As I mentioned above, the ability to work with Catalog entities in a content way is provided by CatalogContentProvider, but you’ll hardly need to work with it directly. Instead, you’ll work with repository pattern, provided via IContentRepository. If you’re going to work with catalog content, it should be one of your dependencies, but I’m using the Service locator here, for the simplicity.
var contentRepo = ServiceLocator.Instance.Get<IContentRepository>();
That’s it. Now let’s try to get an entry, given the catalog entry Id, edit it name, and then save it back:
With ICatalogSystem, it will likely be this:
var entry = CatalogContext.Current.GetCatalogEntryDto(1, new Mediachase.Commerce.Catalog.Managers.CatalogEntryResponseGroup(Mediachase.Commerce.Catalog.Managers.CatalogEntryResponseGroup.ResponseGroup.CatalogEntryFull); entry.CatalogEntry.Name = entry.CatalogEntry.Name + "edited"; CatalogContext.Current.SaveCatalogEntry(entry);
While you can write in content way:
var contentRepo = ServiceLocator.Current.GetInstance<IContentRepository>(); var referenceConverter = ServiceLocator.Current.GetInstance<ReferenceConverter>(); var variantContent = contentRepo.Get<MyVariationContent>(referenceConverter.GetContentLink(1, CatalogContentType.CatalogEntry, 0)); variantContent.Name = variantContent.Name + "edited"; contentRepo.Save(variantContent, DataAccess.SaveAction.Publish);
You might feel not “convinced” in the content way. Wait. Just try to edit a metafield. You’ll see that there’s no easy way to do it with CatalogEntryDto. Instead, you’ll need to use Entry (Damn!) to access the ItemAttributes property. Think went fine until you find out that there’s no way to save an Entry, you’ll need to manipulate MetaObject instead.
And you’re screaming …
While with the content way, all you need to do is a little change of above code:
If you did not define property for your metafield:
variantContent.Property["Something"] = new PropertyString("Hello world");
and if you defined the property (which we recommend to do), you can use the strongly typed property instead:
variantContent.Something = new PropertyString("Hello world");
And it’s done. Yay!
The convenient code is not only reason to go for content way. CMS also have better caching implementation than the one go with eCF, especially for remote cache (in a load-balancing configuration, for example). You can have performance benefits over eCF caching.
The third and the last one is that content way comes with strongly typed type. You can avoid calling wrong metafield name, as C# compiler will check it for you. Instead of entry.ItemAttributes[“SomeVeryLongMetaFeild”] as decimal , you now can use entry.SomeVeryLongMetaField directly. Notice the typo I had with the old way?
Getting familiar with ReferenceConverter
If you want to work with catalog content, you’ll need to know this guy. Seriously. He’s the bridge between eCF catalog and the content system. You might already know it – Catalogs, nodes and entries are stored in separated tables, with an IDENTITY column as the ID. So a catalog id value can also be an entry Id value, and so on. Content system requires that every content needs to have a unique ContentReference, and it’s up to ReferenceConverter to do the hard work.
ReferenceConverter can work two ways, i.e. from catalog entry id to ContentReference, and from ContentReference back to content type and object Id.
Take a look at the method signatures and you’ll be able to get it up and running in matter of minute.
ContentReference GetContentLink(int objectId, CatalogContentType contentType, int versionId) ContentReference GetContentLink(int contentId, int versionId) int GetObjectId(ContentReference contentLink) CatalogContentType GetContentType(ContentReference contentLink) ContentReference GetContentLink(string code)
Just one thing to note with ReferenceConverter is beware of method with take the entry/node code and returns a ContentReference. Unlike the other methods, which only work in memory, which are very fast, this one need to connect to database to get the id before converting it into ContentReference. Nothing wrong with it, but if performance is your concern, then you should minimize using this. This is one of drawback of ReferenceConverter and until EPiServer introduce some nicer way to map between a code and an id of catalog content, we’ll have to live with it.
I hope this will give you some excitement about the content way when working with catalog content. In next posts, I’ll try to cover up how to move away from ICatalogSystem to IContentRepository. Stay tuned with the updates!