Random Image from Media Folder (Tricky Folder Selection?)

Topics: General, Troubleshooting, XSLT
Apr 22, 2011 at 4:08 AM

I'm sure I've seen it somewhere, either here or in the documentation, but I want to create a Function that displays a random image from a "C1 Media Folder" DataReference that has been passed into the function. So, the user puts the function on the page, and just selects the Folder from which to Get a Random Image.

I think I figured out how to do it with a C1 Image:

Create RandomImage Function

InputParameter:

  DataReference<C1 Media Folder> named it MyImageFolder

Function Calls:

  GetIMediaFileFolderXml

     Selected Fields:   KeyPath, CompositePath

     Filter: Composite.Data.Types.IMediaFileFolder.DataReferenceFilter -> Choose Input Parameter "MyImageFolder"

     Page Size: 1

     Randomized: True

Then, you just do the template magic.

 

HOWEVER, there's a twist. I have Create an IData datatype called BannerImage which contains as Fields:

     C1 Image File  MyImage

     PageLink         MyPageLink

The idea behind this is that there are Images, like a coupon for example, which will always point to a certain page and are reused throughout the site. The datatype allows these "BannerImages" to be created including a link and reused.

I'm struggling as to how to Access the BannerImage.MyImage inside the function space so I can filter only the BannerImage Objects that contain an Image that is in the MyImageFolder Input parameter.

Essentially, I need to access the embedded Image's C1 Image Folder  inside C1 Image which is a field of the BannerImage datatype.

I hope this is clear as to what I'm trying to accomplish.

Apr 22, 2011 at 11:44 AM

When you need to have some tricky data selection/filtration which isn't a part of standard GetXml functionality, there're usually 2 ways of doing it:

1. Build input xml in a "C# functinon"

In this case that function would

a) accept image folder as a parameter,

b) find all images under the folder,

c) iterate over BannerImage and find those images that are in the "b" also

d) return an XElement, with image information

 

2. Create your own "field predicate filter"

If you create a function that returns Expression<Func<Guid, bool>> you can set it as a filter for MyImage field on GetBannerImageXml call.

 

I would recommend you to use the first way, even though it looks less "cool", there're much less space to make a mistake there, and therefore quicker to implement

Apr 22, 2011 at 2:04 PM

Thanks for the suggestion.

One question, though. I  can't find much documentation on any of the C1 DataTypes. I assumed that I needed to use Composite.Data.Types.IMediaFolderData as the parameter, but C1 defines a MediaFolder as DataReference<C1 Media File> which is what is being passed in through the parameter.

How does one reference the Composite Built-in Types?

Apr 26, 2011 at 10:45 AM

If I understand you correctly, you have images and "banner image" elements adding a URL to images, and you then let users select a media folder (containing images) from which a random image (having a related BannerImage element) is selected.

First of, I'd get the media folder out of the equation here (because the user could potentially select a media folder, where there are either no images or no images with a related BannerImage element). My inner Asberger child always try to avoid situations like that :) Instead I'd create a BannerImageGroup which BannerImage elements relate to, and have the user select such a group. Once there the problem you experience here is probably gone.

But back to your question; given a reference to a media folder, you would need to do a join across image file and BannerImage which you can do using LINQ C# (the visual tools in the C1 Console are not complex enough to do this). You can write a C# Function that does the joining required and either return the actual data you need or a predicate filter (a Expression<Func<T,bool>> ) that you can hook onto your GetBannerImageXml call.

If you are using VisualStudio and relying on Intellisense when writing up the LINQ query for this, you will experience that you are not getting any Intellisense on the core types like IMediaFile, IMediaFileFolder etc. I suggest that you examine the sources to see the properties available on the types and then do the LINQ 'old school' without Intellisense. (When we went open source last fall we hid 95% of the API, planning to open up slowly to ensure stability/quality. Not a 100% perfect decision - we will have them visible to Intellisense and documented in the next release.)

But - you won't have intellisense, but you can reference the build in types without problems.

 

Apr 26, 2011 at 12:23 PM

Thanks Mawtex... that's some pretty solid advice. Actually, in the end that's pretty much what I did. The BannerGroups also allowed a bit more organization as well. I was trying to get too smart with the code and getting a bit too complex... which in the end may confuse the user and end up with situations exactly as you described. Users come back to me and say it's broken because they selected an image folder with images in it... and it doesn't show up (because they didn't add any images to Banners (which may or may not have a link in them).

I also noticed that the intellisense was missing. I found IMediaFileFolder class from investigating what the UI was expecting and your explanation makes sense. Thanks for your help. The deeper I get into C1 the more I like it!

Apr 26, 2011 at 12:44 PM

> The deeper I get into C1 the more I like it!

Don't be to shy to rate us - we are complete rating suckers in the core group ;-)