so basically, i'm new to umbraco, i have a document type of Demo, it has a a property of demoDate.
as the client wishes these to be shown in a calendar, i only want to get the demo's between a certain date range, using an API controller. i've had a few stabs at it, but basically i cant get the filter to work on the date range, here is my class:
public class DemosController : UmbracoApiController
{
public IEnumerable<Demo> GetDemos(DateTime startdate, DateTime enddate)
{
var demosPage = Umbraco.ContentAtRoot().First().Children("demosHome").Where("Visible").First();
IPublishedContent typePage = Umbraco.TypedContent(demosPage.Id);
var typedChildren = typePage.Children.Where(c => (DateTime)c.GetProperty("demoDate").Value <= enddate).ToList();
DynamicPublishedContentList demos = Umbraco.Content(demosPage.Id).Children("demo").Where("Visible").Where("demoDate <= @0", enddate).OrderBy("demoDate");
//.Where($"demoDate <= {enddate.ToShortDateString()}")
//.Where($"demoDate <= {enddate}")
// a.
return typedChildren
//.Cast<DynamicPublishedContent>()
.Select(d => new Demo { Date = Convert.ToDateTime(d.GetProperty("demoDate").Value), Title = (string)d.GetProperty("demoTitle").Value, Url = d.Url })
.ToList();
}
public string Test()
{
return "test";
}
}
i'm wondering if someone could tell me a way to get it to work, if i try and compare them through the dynamic way i get an error saying >= cannot be applied to types of string.
public class DemosController : UmbracoApiController
{
public IEnumerable<Demo> GetDemos(DateTime startdate, DateTime enddate)
{
// first lets get the demospage node
// umbraco has a typed (or dynamic version) helper that enables you to get the first node at a particular XPATH
//so 'Home' is the document type of your root node
var demosPage = Umbraco.TypedContentSingleAtXPath("//Home/demosHome");
// then lets get the children of the demosPage with doctype alias demoPage ?
// then we use strongly typed where filtering to do apply the date conditions
// .GetPropertyValue<DateTime("alias") will do the date conversion for you
var demos = demosPage.Children(new string[] { "demoPage" }).Where(f => f.GetPropertyValue<DateTime>("demoDate") > startdate && f.GetPropertyValue<DateTime>("demoDate") <= enddate).OrderByDescending(f=>f.GetPropertyValue<DateTime>("demoDate"));
// as before select the result into a plain Demo class for the Web API to serialise
return demos.Select(d => new Demo { Date = d.GetPropertyValue<DateTime>("demoDate"), Title = d.GetPropertyValue<string>("demoTitle"), Url = d.Url })
.ToList();
}
public string Test()
{
return "test";
}
}
public class Demo
{
public DateTime Date { get; set; }
public string Title { get; set; }
public string Url { get; set; }
}
Marc's solution With the GetPropertyValue<DateTime> is the best. However, if you have LOTS of documents, do know that you are getting each document and the filter it afterwards. If you experience a performance impact, consider other querying ways like an examine query...
Yes it's all about context, the best idea is to start off simple, get something working and then measure the performance with the MiniProfiler
eg
var profiler = UmbracoContext.Application.ProfilingLogger;
using (profiler.DebugDuration<YourClass>("Name of what you are measuring"))
{
// code you want to measure the performance of
System.Threading.Thread.Sleep(1000);
}
then depending on the context of your application you may need to refactor if performance is an issue.
For example in the code above, instead of retrieving the demo page with
var demosPage = `Umbraco.TypedContentSingleAtXPath("//Home/demosHome");`
You could more efficiently retrieve all the demos between the two dates, still using the Umbraco Cache with a single XPath statement, and then no filtering will take place in memory!
eg:
var demos = Umbraco.TypedContentAtXPath("//Home/demosHome/demoPage[@isDoc and number(translate(demoDate,'-T:','')) < '" + String.Format("{0:yyyyMMddHHmmss}",enddate) + "' and number(translate(demoDate,'-T:','')) > '" + String.Format("{0:yyyyMMddHHmmss}", startdate) + "']");
XPath against XML is really quick.
But you can't be really sure, without measuring, because the best approach will be determined by whether there is 10, 100, or 100000 demos
I've found the Umbraco Cache can perform pretty well compared to Examine for this kind of query for surprisingly large recordsets, but if you were doing a fuzzy search of text, examine is the obvious way to go!
(Also if you have 100000 demos - Umbraco content may not be the best way of storing them)
Querying Child Content
so basically, i'm new to umbraco, i have a document type of Demo, it has a a property of demoDate.
as the client wishes these to be shown in a calendar, i only want to get the demo's between a certain date range, using an API controller. i've had a few stabs at it, but basically i cant get the filter to work on the date range, here is my class:
to test it im simply doing this at the minute:
i'm wondering if someone could tell me a way to get it to work, if i try and compare them through the dynamic way i get an error saying >= cannot be applied to types of string.
any help would be greatly appreciated
thanks in advance
Hi Dan
Try this:
Marc's solution With the
GetPropertyValue<DateTime>
is the best. However, if you have LOTS of documents, do know that you are getting each document and the filter it afterwards. If you experience a performance impact, consider other querying ways like an examine query...Hi Damiaan,
with reference to your comment, is it getting all the documents because of the .Children(new string[] { "demoPage" }) part of the query?
is there anyway to minimize this result set within this query structure or is examine the only way to do this?
thanks
Hi Dan
Yes it's all about context, the best idea is to start off simple, get something working and then measure the performance with the MiniProfiler
eg
then depending on the context of your application you may need to refactor if performance is an issue.
For example in the code above, instead of retrieving the demo page with
and then filtering in memory by dates:
You could more efficiently retrieve all the demos between the two dates, still using the Umbraco Cache with a single XPath statement, and then no filtering will take place in memory!
eg:
XPath against XML is really quick.
But you can't be really sure, without measuring, because the best approach will be determined by whether there is 10, 100, or 100000 demos
I've found the Umbraco Cache can perform pretty well compared to Examine for this kind of query for surprisingly large recordsets, but if you were doing a fuzzy search of text, examine is the obvious way to go!
(Also if you have 100000 demos - Umbraco content may not be the best way of storing them)
regards
Marc
thanks for the replies and help with this one guys, plenty to think about in terms of performance etc.
i also got the xpath query working now with great help to Marc, my xpath skills are so hot (yet), so onto making the next bit work
thanks again for the help
is working on a reply...