An interesting question popped up in CS forums recently on how to obtain the categoryID from the Photo GalleryPost object. There are several interesting aspects in approaching this that I felt were Nuglet worthy. We'll look at how a picture list is created on the gallery PictureListing control and on the home page aggregate picture listing in regards to category access and filtering.
The standardized component model across the various Community Server applications helps understand processes like displaying a picture list by category. Like other applications, the picture GalleryPost object derives from a CS Post object. The GalleryPost object has a Categories[] string array to support multiple categories, but it is not populated when generating a photo list. The CategoryID is applicable to the query object, not the post object.
Let's look at the PictureListing control in Photo Galleries as an example of how CS displays a picture list by category. A CS query object is created with a categoryID passed in this case in the Url ViewCategory.aspx?app=appkey&CategoryID=### and stored in the csContext object by a base CS class.
GalleryThreadQuery query = new GalleryThreadQuery();
query.SectionID = CurrentGallery.SectionID;
query.CategoryID = csContext.CategoryID;
....
One of the parameters that gets passed to the cs_shared_threads_getthreadset is a @sqlPopulate nText value which would look something like the following. Notice two things, we're querying cs_posts and filtering by CategoryID off cs_Posts/cs_Posts_Categories.
"SET Transaction Isolation Level Read UNCOMMITTED Select P.PostID From dbo.cs_Posts P right join dbo.cs_Threads t on (P.ThreadID = T.ThreadID) inner join dbo.cs_Sections S on S.SectionID = P.SectionID left outer join dbo.cs_Posts_InCategories PC on PC.PostID = P.PostID left outer join dbo.cs_Post_Categories C on PC.CategoryID = C.CategoryID left join dbo.cs_PostMetadata M on (M.PostID = P.PostID and M.MetaKey = 'Telligent.CommunityServer.MetadataExtractor.Exif.ExifDirectory:36867') where P.SettingsID = 1000 and P.SectionID = 7 and S.IsActive = 1 and P.ApplicationPostType & 64 <> 0 and P.SectionID = C.SectionID and C.CategoryID = 1009 and C.CategoryID = PC.CategoryID and PC.CategoryID = 1009 and PC.PostID = P.PostID and P.IsApproved = 1 and P.PostDate <= getdate() order by M.MetaValue asc, P.PostDate asc"
The query creates a post threadset as it does in Blogs and other CS applications, which then is usually bound to a repeater control as it is here to the Pictures RepeaterPlusNone control.
ThreadSet ts = GalleryPosts.GetPictures(query);
Pictures.DataSource = ts.Threads;
Pictures.DataBind();
The pictures on the home page AggregatePortalPictureListing control are displayed using the same query, threadset-bound-to-repeater process. The AggregatePortalPictureListing control has a public CategoryID if you want to filter by a single category. The result in both examples is a sample thread ArrayList object, demonstrating that the post objects used to generate the list contain a null Categories[] value.
Okay, I guess I wouldn't be much of an ex-Community Server Evangelist if I didn't show you how to add the Categories[] data to a bound control before I close out this nuglet. For our PictureListing examples we would convert the ThreadSet returned from the query to a GalleryPost[] object and bind it to the control rather than the ThreadSet.
// DBVT Modified - Comment out original DataSource / DataBind and convert
// to galleryPost[] object
//pictureList.DataSource = GalleryPosts.GetPictures(query, true, true).Threads;
//pictureList.DataBind();
ThreadSet ts = GalleryPosts.GetPictures(query, true, true);
GalleryPost[] galleryPosts = new GalleryPost[ts.TotalRecords];
for (int i = 0; i < ts.TotalRecords; i++)
{
GalleryPost gp = (GalleryPost)ts.Threads[ i ];
galleryPosts[ i ] = GalleryDataProvider.Instance().GetPicture(gp.PostID, gp.UserID, true);
}
pictureList.DataSource = galleryPosts;
pictureList.DataBind();