How to filter a list of Pages by Category to display as a navigation - sitefinity

In Sitefinity v12.x I would like to create a widget that allows the user to select one or more Categories (Hierarchical Taxons) to use as filter criteria, and after which the widget would query for Pages that have these Categories assigned to them. This seems simple enough on the surface but I can't seem to pull it all together.
I've added "Category" as a Custom Field to the Page data and I've created my test pages. What I'm struggling with is forming the query that can access the custom field "Category" and then compare those against the categories provided by the user.
I've tinkered for awhile but it seems the issue I'm having is retrieving the Categories assigned to a Page from within the Linq query. I've tried var categories = pageNode.GetValue("Category") on it's own and that works as expected. But when I try to use the .GetValue("Category") method in a Linq query this does not seem to be valid, here is an example of what I mean:
var pageManager = PageManager.GetManager();
var pages = pageManager.GetPageDataList().Where(pageData =>
(pageData.Culture == "en" ||
pageData.NavigationNode.LocalizationStrategy != Telerik.Sitefinity.Localization.LocalizationStrategy.Split) &&
pageData.NavigationNode.NodeType == Telerik.Sitefinity.Pages.Model.NodeType.Standard &&
pageData.NavigationNode.RootNodeId == Telerik.Sitefinity.Abstractions.SiteInitializer.CurrentFrontendRootNodeId &&
pageData.Status == ContentLifecycleStatus.Live)
.Select(x => x.NavigationNode);
foreach (PageNode page in pages)
{
// This properly retrieves Categories assigned to a Page in the Debug window
var categories = page.GetValue("Category");
}
// This does not work, error message below .Any() reads: 'object' does not contain a definition for 'Any' and no accessible extension method 'Any' accepting a first argument of type 'object' could be found
var categoryPages = pages
.Where(pageData => pageData.GetValue("Category").Any())
.ToList();
Is there a way I can use/access the Custom Field "Category" on a Page from within a Linq query? Or do I have to go about this some other way?
Thank you in advance for any guidance!

As a note, don't forget to filter the pages for visible and not deleted.
pageData.Status == ContentLifecycleStatus.Live && pageData.IsDeleted == false && pageData.Visible == true)

You should cast pageData.GetValue("Category") to either Guid? or IEnumerable<Guid?> depending how exactly you have set the custom field up.

Thank you for the tips everyone! I was able to sort it out by specifying the type of the Custom Value in the Linq query, like so: pageData.GetValue<TrackedList<Guid>>("Category"), here's what I came up with:
var pageManager = PageManager.GetManager();
var pages = pageManager.GetPageDataList().Where(pageData =>
(pageData.Culture == "en" ||
pageData.NavigationNode.LocalizationStrategy != Telerik.Sitefinity.Localization.LocalizationStrategy.Split) &&
pageData.NavigationNode.NodeType == NodeType.Standard &&
pageData.NavigationNode.RootNodeId == Telerik.Sitefinity.Abstractions.SiteInitializer.CurrentFrontendRootNodeId &&
pageData.Status == ContentLifecycleStatus.Live && pageData.Visible == true)
.Select(x => x.NavigationNode);
var filteredPages = pages
.Where(pageData => categoriesQuery.All(c => pageData.GetValue<TrackedList<Guid>>("Category").Contains(c)))
.ToList();

Related

using a where clause in Entity Framework

I am trying to filter based on a table hierarchical relationship. But getting the error below.
I am trying to filter based on the variable C in c.Departments_Category_Registration.Category_Name == C
Can anyone advise, here is my code
var model = from r in _context.Departments_SubCategory_Registration.Include(c => c.Departments_Category_Registration.Category_Name == C)
where r.IsEnabled == true
select r;
return View(model);
and error messageInvalidOperationException: Incorrect include argument: c => (c.Departments_Category_Registration.Category_Name == __C_0)
update. I changed my code to this below and get no error, but yields no results
[Route("/{C}")]
public async Task<IActionResult> Product(String C)
{
return View(await _context.Departments_SubCategory_Registration.Include(c => c.Departments_Category_Registration)
.Where (d => d.IsEnabled == true)
.Where(r => r.Departments_Category_Registration.Category_Name == C).ToListAsync());
You pass condition to the Include method. It's supposed to accept the property only. Change it to .Include(c => c.Departments_Category_Registration) and move the match by name condition under Where clause.

Collecting a referenced app's values

I am trying to cleanup and optimize my come I am running on podio's API. What I am currently doing is using the filter query to return a collection from one app. I then loop over that collection. On each item I use Podio get_field_value to return the value(s) of a field in a referenced app. This creates a lot of API calls. I would like to retrieve everything in one API call Here is a simple version of my current code:
$collection = PodioItem::filter(WHSE_ID, array(
"filters" => array(
WHSE_EQUP_STATUS => array(2),
),
"sort_by" => WHSE_LOAD_IN,
"sort_desc" => false,
"limit" => 50
)
);
foreach ($collection as $item) {
// Table-A ID
$whId = $item->item_id;
// Referenced App Item(s)
$nucId = $item->fields[0]->values[0]->item_id;
// Get Referenced App Item Field
$app_b_value = PodioItem::get_field_value($nucId, NUC_LOAD_OUT);
echo $app_b_value;
}
Is there a more efficient way of doing this? I am thinking inline with the way you would use JOIN in a mysql query.
Thank you for any help you can provide!
if you are trying to get value from each item from filtered collection, you don't need to make podio calls each time.
Podio filter call will give you item with values. you just have to get value from each item.
like following
foreach ($podioFilterData['items'] as $itemData) {
$itemFields = $itemData['fields'];
foreach ($itemFields as $field) {
$value = $field['values'][0];
}
}

Select document based on matching Id in document property's collection

I would like to retrieve a document if one of its collections has an item with a certain Id in it. This is the query I have:
var query = from x in session.Query<MailPackageLog>()
where x.Package != null
where ((x.Package.To != null && x.Package.To.Select(y => y.Id).Contains(recipientId))
|| (x.Package.Cc != null && x.Package.Cc.Select(y => y.Id).Contains(recipientId))
|| (x.Package.Bcc != null && x.Package.Bcc.Select(y => y.Id).Contains(recipientId)))
select x;
query = query.Customize(x => x.WaitForNonStaleResultsAsOfNow(Settings.Default.DocumentStoreQueryTimeout));
return query.FirstOrDefault();
But I am getting this exception when it runs:
System.InvalidOperationException: Cannot understand how to translate
x.Package.To.Select(y => y.Id)
Is this a bug or am I just doing it wrong?
Instead of:
x.Package.To.Select(y => y.Id).Contains(recipientId)
Try this:
x.Package.To.Any(y => y.Id == recipientId)
Semantically they are the same, but Raven may have an easier time translating the second one.
You may also wish to review the "Filtering" section of the RavenDB documentation. This is similar to the "Where + Any" example show there.

query did not return a unique result: 2 . Issue with Nhibernate Query

I am current having an issue with getting records from database using nhibernate.
My 'publicstring' column is having two values, one with lower case and the other with upper case.
I am trying to fetch one of them depending on what is typed.
Below is my query
private string _publicId;
var _mediaFileShare = this.Session.QueryOver<MediaFileShare>()
.Where(q => q.Publicsting == _publicstring)
.SingleOrDefault();
Answers would be appreciated..
A naive solution is:
var _mediaFileShare = this.Session.QueryOver<MediaFileShare>()
.Where(q => q.PublicString == _publicString)
.List()
.SingleOrDefault(r => string.Compare(r.PublicString, _publicString, StringComparison.Ordinal) == 0);
If you're confident that the query will always return two rows then performance should be very acceptable. Alternatively you could use a dynamic order by, something like:
var query = this.Session.QueryOver<MediaFileShare>()
.Where(q => q.PublicString == _publicString);
query = _publicString == _publicString.ToLower()
? query.OrderBy(q => q.PublicString)
: query.OrderByDescending(q => q.PublicString);
var _mediaFileShare = query.Take(1).SingleOrDefault();
The results using an order by will be dependent on your database and its collation setting.

NHibernate Fetch when querying for single object

I'm trying to optimize an NHibernate query:
var profile = dc.Profiles.FirstOrDefault(p => p.IdProfile == idProfile);
I would like it to load a collection of Rights. I did this:
var profile = dc.Profiles.Fetch(x => x.Rights).FirstOrDefault(p => p.IdProfile == idProfile);
The results were totally different from what I expected - instead of getting single Profile with rights I got single profile with single right!
How can I fix it?
You can use like this
var profile = dc.Profiles.Where(p => p.IdProfile == idProfile).Select(x => x.Rights);