Retrieving
Normally when you retrieve a MediaItem you don't get any meta data from the item unless specified. To retrieve meta data for a MediaItem you can use one of the following methods.
Declarative method
The declarative model allows us to setup a model for the data we want to populate. This method is best if you want to reuse the same model several times.
Setup
To retrieve meta data using the declarative model we create a subclass for MediaItem, add a property and decorate it with the with the MetadataAttribute.
public class GalleryImage : MediaItem {
[Metadata(Name = "Title")]
public string Title { get; set; }
}
This will map the property vs a user meta data with the name Title. You can also specify a specific type of meta data, for instance the following code will populate the property with the IPTC Photographer meta data.
[Metadata(Name = "Photographer", Type = MetadataDefinitionTypes.Iptc)]
public string Photographer { get; set; }
When these objects are retrieved, the media items meta data of that definition will populate the property if there exists a value for that meta data and media item.
Querying
To retrieve the populated data you only need to pass type created above as type parameter to the Query method and apply needed filters just like you do with the MediaItem.
var client = ClientFactory.GetSdkClient();
var galleryImages = client.Query<GalleryImage>().Take(100).ToList();
foreach (var galleryImage in galleryImages) {
Console.WriteLine(galleryImage.Title);
}
Direct method
If you want to determine the meta data to retrieve in runtime you can do so by specifying the Include statement and specify a meta data query.
var client = ClientFactory.GetSdkClient();
//includes all metadata (all definitions found in the database
//regardless if there exists a value for the item or not)
var media = client.Query<MediaItem>().Include(m => m.Metadata).ToList();
You can also specify which meta data to populate using the Where clause. In this case we filter out all meta data that are IPTC meta data. See the MetadataDefinitionTypes for a complete list of supported meta data types.
//find all iptc metadata
media = client.Query<MediaItem>()
.Include(m => m.Metadata.Where(i => i.DefinitionType == MetadataDefinitionTypes.Iptc))
.ToList();
//write out the ones with values
foreach (var mediaItem in media) {
foreach (var metadata in mediaItem.Metadata.Where(m => !m.IsNull)) {
Console.WriteLine(@"{0}:{1}", metadata.Name, metadata.Value);
}
}
You can also combine different conditions using AND to narrow your result
//find a named iptc metadata
media = client.Query<MediaItem>()
.Include(m => m.Metadata.Where(i =>
i.DefinitionType == MetadataDefinitionTypes.Iptc &&
i.Name == "Caption"))
.ToList();
If you only want to filter out meta data that contains values for your items use the IsNull property
//find all iptc metadata that has values
media = client.Query<MediaItem>()
.Include(m => m.Metadata.Where(i =>
i.DefinitionType == MetadataDefinitionTypes.Iptc &&
!i.IsNull))
.ToList();
A limitation for the LINQ provider is that you cannot use OR statements in your Where clause. In the example below we try to include both IPTC and Exif meta data but the statement below is not supported and will generate an exception.
//this will generate an exception since or is not supported
media = client.Query<MediaItem>()
.Include(m => m.Metadata
.Where(i =>
i.DefinitionType == MetadataDefinitionTypes.Iptc ||
i.DefinitionType == MetadataDefinitionTypes.Exif
)
)
.ToList();
The correct way is to use multiple include statements instead to get the intended result.
//this will work as intended using two different include statements
media = client.Query<MediaItem>()
.Include(m => m.Metadata.Where(i => i.DefinitionType == MetadataDefinitionTypes.Iptc))
.Include(m => m.Metadata.Where(i => i.DefinitionType == MetadataDefinitionTypes.Exif))
.ToList();