Items vs Parts and Container

Topics: Writing modules
Jun 20, 2016 at 4:04 AM
Edited Jun 20, 2016 at 4:09 AM
I have a feeling I've stuffed this up completely...

We've got a module that is creating content items "Catalog" that are made up of commonpart, titlepart, and our own speicifc "CatalogPart" part.

1) I have a sneaking suspicion we should have named the ITEM "CatalogPart" also... is this going to cause issues?

2) because ALL the data comes from our webservice, we have created our parts without stores - so our parts are literally just POCOs... "property {get;set;}" on all fields... This seems to work, however it looks like without a RECORD we can't get anything to CONTAIN these items (and we also can't use queries and projections I think?)

Is the solution here to backout and reimplement our webservice access at the RECORD layer (somehow?) or can this be salvaged somehow?
Jun 20, 2016 at 7:28 AM
Edited Jun 20, 2016 at 7:28 AM
If you want to be able to have your Catalog items to be contained by other items (like Lists), you can attach the ContainablePart to your Catalog type. That way, content items that have the ContainerPart attached can contain those items.
Jun 20, 2016 at 2:21 PM
... is this different from making the TypeDefinition "Listable()"?

I can attach tehse parts to other items in ORchard, but I can't attach it to the Catalog "Master" (of which we have multiple)... I guess I should have been a little more specific.

CatalogA (in the webservice) has list of "CatalogItems"
CatalogB (in the webservice) has list of "CatalogItems"
CatalogC (in the webservice) has list of "CatalogItems"

our problem is less in the items and more in the container... it seems that you can't create a LIST from data (at least in our controller...)

However... I've been studying the Blog module and they don't seem to let the "container bother them too much... I will try to use that as a guide... might get further this way...
Jun 21, 2016 at 8:59 AM
Yes, completely different: the "Listable" setting controls whether content items are displayed on the Content Items list screen in the dashboard.

Regarding Orchard Lists and data from your web service: you can only add content items to an Orchard List (by means of the Container/Containable parts).
This means that you can't add arbitrary items using that technique.

However, since you have a custom "CatalogPart", why can't you store the items from the web services there? You could use InfoSet storage (no RECORD required).
Marked as answer by smerlon on 6/24/2016 at 7:31 AM
Jun 24, 2016 at 3:31 PM
yep cool thanks, (so just to clarify, having listable just allows it to be listed/hidden in the admin UI...?)

So (I think) i'm roughly following your advice, just not at the same point (because I'd already started down this part when I read your post...) and I think it works as you've suggested... I wasn't (and am still not) familiar enough with InfoSet to actually grok what you are saying but I've got it (mostly) working with the following setup:

ICatalogSerivce : IDependency
...injected into...
CatalogPartDriver constructor
then when the driver runs it asks the service for the items of data for the CatalogPart (master) in question and shoves the list into an Items list...

Judging from your comment about using and infoset, I'd guess that I've done this too close to the UI so I'm sure I will run into some issues with this setup... but its working for what I need for now... :)

Obviously I have much to understand about infoset now... sigh...
Jun 26, 2016 at 11:31 AM
Exactly, the "listable" just allows it to be listed (or not) in the admin menu.

It sounds like you are on the right track: you have a service providing the items, and its this service that you inject into your driver.
Now, the question is: do you want a copy of your items to be stored with your content part, or do you simply want to display these items when your part is rendered? I mean, if your ICatalogService provides the data and it uses caching, maybe there is no need to persist those items as part of your content part? If so, then all you need to do is stick those items into the shape you are returning from your driver. Those items are then accessible from your part's shape template. E.g.
public DriverResult BuildDisplay(CatalogPart part, string displayType, dynamic shapeHelper) {
   return ContentShape("Parts_Catalog", () => {
      // Get the items from the catalog service.
      var items = _catalogService.GetItems();
      // Return a shape containing the items.
      return shapeHelper.Parts_Catalog(CatalogItems: items);
Your part's shape template (Parts.Catalog.cshtml) then looks like this:
   var items = Model.CatalogItems;
   @foreach(var item in items) {
Marked as answer by smerlon on 7/8/2016 at 6:38 PM
Jul 9, 2016 at 2:38 AM
Yep, thanks for confirming I was on the right track - its almost exactly how I ended up with a working part.
Super thanks!