...
In cases such as these you might want to consider doing a custom query for assets. Luckily the EpiserverOptimizely/Digizuite integration is prepared for this and supports it fully.
Querying
In order to search, you basically have to construct an AssetQueryParameters object.
...
- AssetIds (IList<int>). A list of specific asset ID's you want to retrieve. There is method to help you set this, AssetsById(ContentReference) that will also convert the Episerver ContentReference OptimizelyContentReference into an AssetID.
- FoldersToSearch (IList<ContentReference>). If this is set, only assets in those folders will be searched.
- AssetTypes (IList<int>). A list of Asset Type ID's. If this is set, only assets of those types will be searched.
- CropName (String). The name (or partial name) of a specific cropping. If this is set, only those crops will be returned.
- Sort (string). The sorting scheme to use.
- FreeText (string). A free text search query. By default this will do a free text search against the title, description, keywords and note field - but it can of course be configured.
- OptionalFilters (Dictionary<string,string>). Any additional fields to filter for. For this to work, the custom filter should have been added to the DAM Center search as an input parameter. Read more: DFE DFO 3.0.0 - 6 Customizing input and output metadata
- Limit (int). How many assets to return.
- Page (int). The page of assets to start from. Starts at 1.
- QueryCacheDuraction (TimeSpan). The timespan to cache the results for. This is very important in order to ensure decent performance on your site and DAM Center. This can also be set through the method CacheFor.
...
The same Search method can also be called with a string query instead, which is in turn parsed to AssetQueryParameters as described below.
Figuring out which values to use for Crops, Sorting and Asset Types
When setting the above search parameters it's important to know which options is available to set. You can of course see this in your DAM Center's configuration, but that might not be available to the typical web site editor.
Luckily, whenever the Digizuite Client class (DFO 3.0.0 - 1 Understanding DAM For Optimizely) initializes, it connects to the DAM and retrieves lists of the various settings like Asset Types, Crop Names, Sorting methods and Media formats. They are then available in the "Configuration" object of the Client and can be called like myClient.Configuration.AssetTypes, myClient.Configuration.MediaFormats, myClient.Configuration.Crops, myClient.Configuration.SortFields.
Selection factories
To make it even easier to use the values from the DAM Center in custom property drop down lists - for example in a block to hold a dynamic gallery, the integration also provides SelectionFactories for AssetType, Crops and MediaFormats in the Digizuite.Episerver.Helpers namespace, ready to use in attributes on properties like this:
...
See a full example further down!
Anchor | ||||
---|---|---|---|---|
|
The AssetQueryParameters has a Parse(string) method that can transform any string into an AssetQueryParameters object.
...
Since this is exactly the same mechanism that is configured for the Digizuite Search Provider, you can actually try to search in the Digizuite Media tab and use this syntax!
Example: Building a Gallery Block
Putting it all together, let's create a gallery block that shows a dynamic gallery of images from Digizuite, based on editorial preferences.
First, we'll create the block definition. Note, that on this DAM Center we have a custom input (and output) parameter defined called "Status" that can either be "Creative", "Approved" or "Expired". It's added through the process described here: DFE 3.0.0 - 6 Customizing input and output metadata.
We will also make it optional which folders to search in, a Free text query, how many assets to show and so on. However, we won't worry about paging for now.
...
Code Block | ||
---|---|---|
| ||
[ContentType(DisplayName = "Gallery", GUID = "b05d16f0-877d-4784-8bf1-4a0ee2e57fd1", Description = "Shows a gallery of DAM assets")] [ImageUrl("~/Static/img/logo120x90.png")] public class GalleryBlock : BlockData { [CultureSpecific] [Display( Name = "Headline", Description = "Headline", GroupName = SystemTabNames.Content, Order = 1)] public virtual string Headline { get; set; } [Display( Name = "Max number of assets", Description = "", GroupName = SystemTabNames.Content, Order = 10)] public virtual int MaxNumberOfAssets { get; set; } [Display( Name = "Asset Folders", Description = "", GroupName = SystemTabNames.Content, Order = 20)] [UIHint(UIHint.AssetsFolder)] public virtual IList<ContentReference> Folders { get; set; } [Display( Name = "Free Text", Description = "", GroupName = SystemTabNames.Content, Order = 30)] public virtual string FreeText { get; set; } [Display( Name = "Crop Name", Description = "", GroupName = SystemTabNames.Content, Order = 40)] [SelectOne(SelectionFactoryType = typeof(CropSelectionFactory))] public virtual string CropName { get; set; } [Display( Name = "Media Format", Description = "", GroupName = SystemTabNames.Content, Order = 40)] [SelectOne(SelectionFactoryType = typeof(MediaFormatSelectionFactory))] public virtual string MediaFormat { get; set; } [Display( Name = "Status", Description = "", GroupName = SystemTabNames.Content, Order = 50)] [SelectOne(SelectionFactoryType = typeof(StatusSelectionFactory))] public virtual string Status { get; set; } public override void SetDefaultValues(ContentType contentType) { base.SetDefaultValues(contentType); this.MaxNumberOfAssets = 20; } } public class StatusSelectionFactory : ISelectionFactory { public IEnumerable<ISelectItem> GetSelections(ExtendedMetadata metadata) { return new ISelectItem[] { new SelectItem() { Text = "(Not set)", Value = "" }, new SelectItem() { Text = "Creative", Value = "Creative" }, new SelectItem() { Text = "Approved", Value = "Approved" }, new SelectItem() { Text = "Expired", Value = "Expired" } }; } } |
When we display this to the editors in edit-mode, this is what they'll see:
...
We also have to have a standard controller that will popular a View Model with the assets to show. We do that here:
Code Block | ||
---|---|---|
| ||
publicprotected override ActionResultIViewComponentResult IndexInvokeComponent(GalleryBlock currentBlockcurrentContent) { GalleryBlockViewModel gvm = new GalleryBlockViewModel(); gvm.CurrentBlock = currentBlockcurrentContent; AssetQueryParameters aqm = new AssetQueryParameters(); aqm.FoldersToSearch = currentBlockcurrentContent.Folders ?? new List<ContentReference>(); aqm.Limit = currentBlockcurrentContent.MaxNumberOfAssets; aqm.Page = 1; aqm.AssetTypes = GlobalConstants.AssetTypes.Image.MakeIntList(); aqm.CropName = currentBlockcurrentContent.CropName; aqm.OptionalFilters = new Dictionary<string, string>(); if (!string.IsNullOrEmpty(currentBlockcurrentContent.FreeText)) aqm.OptionalFilters.Add("freetext", currentBlock.FreeText); if (!string.IsNullOrEmpty(currentBlock.Status)) aqm.OptionalFilters.Add("status", currentBlock.Status)= currentContent.FreeText; gvm.Images = _client.Search(aqm.CacheFor(TimeSpan.FromMinutes(1))).Cast<IDigizuiteImage>().ToList(); return PartialViewView(gvm); } |
Notice how we also make sure to set a cache timeout of 1 minute when doing the searching? That ensures a pretty updated image list, while not cause load to the DAM server for every page view. We could probably safely increase this number a lot.
...