Custom filter for projection - query against a field created in the admin UI?

Topics: Customizing Orchard
Aug 24, 2015 at 11:55 AM
Edited Aug 24, 2015 at 12:21 PM
I'm going round in circles here and getting nowhere so if I anyone can help me it would really be appreciated.

I've created a TestimonialEntry through the admin panel Content Definition. It has a ContentItemPicker field in it called AssociatedProfiles which only allows one item to be picked of its type.

I've also created a Profiles through the admin panel Content Definition which is a section of pages on the site.

The idea is that when I'm on a Profile page I want
  • to show a list of TestimonialEntry's that has the AssociatedProfiles id set to the Profile pages id (so that testimonial is owned by that profile).
  • when I'm on the rest of the site it will see that the current page ContentType isn't the Profile so instead I will select TestimonialEntry's with no AssociatedProfiles set (so no owner, just show the generic site-wide testimonials)

Creating a custom IFilterProvider class

I've got the filter up and running, it's listed in its correct section in the admin panel but I cannot figure out how to access Fields within the ApplyFilter() method and I cannot find any documentation or tutorials that help:
        private void ApplyFilter(FilterContext context)
            context.Query = context.Query.ForType("TestimonialEntry");

            // Action<IAliasFactory> selector = alias => alias.ContentItem()..context.Parts.SelectMany(x => x.Fields).Single(x => x.Name == "AssociatedProfile");

            //context.Query = context.Query.Where()
I don't know how to drill down into the query to filter it by Fields made through the admin panel UI rather than being actual Parts in the source.
Aug 24, 2015 at 11:28 PM
I am very very pleased to say after two days of hunting and chipping away at this I have managed to solve the problem.

The code that finally did the filtering I wanted was as follows:
            context.Query = context.Query.ForType("TestimonialEntry").ForVersion(VersionOptions.Published);
            context.Query = context.Query.Where(
                a => a.ContentPartRecord<FieldIndexPartRecord>().Property("StringFieldIndexRecords", "TestimonialEntryProfile"),
                p => p.And(
                    x => x.Eq("PropertyName", "TestimonialEntry.Profile."), 
                    y => y.Eq("Value", "{114}")
It's hardcoded to a specific profile at the moment but I will integrate the url route into it tomorrow. The complicated bit is now done!

The article that finally let me get my foot in the door was this one:
I will be eternally grateful to this guy for posting this :)
Marked as answer by rtpHarry on 8/24/2015 at 4:28 PM