8

I'm using 8.2 Update-3 and have deployed it to Azure with Sitecore's ARM template.

I have indexed a page called Event Page. The Event Page has a DateTime field called Start Date on it. It is indexed as an Edm.DateTimeOffset field. I have mapped the index to a custom SearchResultItem called EventItem. The EventItem looks like this:

public class EventItem : IndexedItem
{
    [IndexField(Constants.IndexFields.Header)]
    public string Header { get; set; }

    [IndexField(Constants.IndexFields.Content)]
    public override string Content { get; set; }

    [IndexField(Constants.IndexFields.StartDate)]
    public DateTimeOffset StartDate { get; set; }
}

I want to search for all events that has a Start Date in the future:

using (var context = this.SearchIndexResolver.GetIndex("my_index").CreateSearchContext())
{
    var queryable = this.CreateAndInitializeQuery(context);

    queryable = queryable.OrderBy(x => x.StartDate);

    var dateTime = new DateTimeOffset(DateTime.UtcNow);
    queryable = queryable.Where(x => x.StartDate >= dateTime);

    var results = queryable.GetResults();

    return results;
}

This gives me the search result that I want. If I stick a breakpoint on the results variable I can see that there are 3 hits which is correct. However, when I use the mapped EventItem's from the search result I get the following exception:

[NotSupportedException: IndexFieldUtcDateTimeOffsetValueConverter cannot convert from System.DateTime.]
   System.ComponentModel.TypeConverter.GetConvertFromException(Object value) +184
   System.ComponentModel.TypeConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value) +8035992
   Sitecore.ContentSearch.Azure.Converters.CloudIndexFieldStorageValueFormatter.ReadFromIndexStorageBase(Object indexValue, String fieldName, Type destinationType) +596
   Sitecore.ContentSearch.Azure.Converters.CloudIndexFieldStorageValueFormatter.ReadFromIndexStorage(Object indexValue, String fieldName, Type destinationType) +234
   Sitecore.ContentSearch.DocumentTypeMapInfo.SetProperty(Object target, String propertyName, String documentFieldName, Object value) +801
   Sitecore.ContentSearch.DefaultDocumentMapper`1.MapFieldValuesToType(IDictionary`2 fieldValues, TElement result, DocumentTypeMapInfo documentTypeMapInfo) +1789
   Sitecore.ContentSearch.DefaultDocumentMapper`1.MapToType(TDocument document, SelectMethod selectMethod, IEnumerable`1 virtualFieldProcessors, IEnumerable`1 executionContexts, SearchSecurityOptions securityOptions) +760
   Sitecore.ContentSearch.Azure.Query.CloudSearchResults`1.Map(IDictionary`2 fields) +813
   Sitecore.ContentSearch.Azure.Query.<GetSearchHits>d__13.MoveNext() +366

I have tried changing my EventItem type to a DateTime instead of DateTimeOffset and query with a DateTime.Now but that gives me a "Specified cast is not valid" exception when it comes the the GetResults() method:

[InvalidCastException: Specified cast is not valid.]
   Sitecore.ContentSearch.Azure.Query.Operations.PrepareValue(Object value, String edmType) +201
   Sitecore.ContentSearch.Azure.Query.CloudQueryMapper.HandleGreaterThanOrEqual(String srcFieldName, Object value, Single boost) +244
   Sitecore.ContentSearch.Azure.Query.CloudQueryMapper.HandleGreaterThanOrEqual(GreaterThanOrEqualNode node, CloudQueryMapperState state) +147
   Sitecore.ContentSearch.Azure.Query.CloudQueryMapper.HandleWhere(WhereNode node, CloudQueryMapperState mappingState) +37
   Sitecore.ContentSearch.Azure.Query.CloudQueryMapper.MapQuery(IndexQuery query) +64
   Sitecore.ContentSearch.Linq.Parsing.GenericQueryable`2.GetQuery(Expression expression) +271
   Sitecore.ContentSearch.Linq.Parsing.GenericQueryable`2.Execute(Expression expression) +37
   Sitecore.ContentSearch.Linq.QueryableExtensions.GetResults(IQueryable`1 source) +334

So how do I fix this? What am I doing wrong?

1 Answer 1

4

I have been digging a little further. As the stacktrace says the issue lies in the IndexFieldUtcDateTimeOffsetValueConverter. So I reflected on Sitecore.ContentSearch.Azure.Converters.IndexFieldUtcDateTimeOffsetValueConverter, Sitecore.ContentSearch.Azure and created my own implementation of the TypeConverter. The issue lies in the ConvertFrom method in the System.ComponentModel.TypeConverter class. So an override of the ConvertFrom method fixed the issue:

using Sitecore.ContentSearch.Converters;
using System;
using System.ComponentModel;
using System.Globalization;

public class IndexFieldUtcDateTimeOffsetValueConverter : AbstractTypeConverter
{
    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        DateTime dateTimeValue = DateTime.MinValue;
        bool success = value != null && DateTime.TryParse(value.ToString(), out dateTimeValue);

        if (success)
        {
            return new DateTimeOffset(dateTimeValue);
        }

        throw GetConvertFromException(value);
    }
}

Now I am able to query on DateTimes, compare them in queries and sort on DateTimes. This fixes my problem. I'll open a ticket with Sitecore and if there is a different way of fixing this, I will update this post.

If you face the same problem and are using the above TypeConverter, remember to switch the TypeConverter with the standard Sitecore one:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
<sitecore>
    <contentSearch>
        <indexConfigurations>
            <defaultCloudIndexConfiguration>
                <indexFieldStorageValueFormatter>
                    <converters>
                        <converter handlesType="System.DateTimeOffset" typeConverter="Sitecore.Foundation.Indexing.IndexFieldUtcDateTimeOffsetValueConverter, Sitecore.Foundation.Indexing" patch:instead="*[@handlesType='System.DateTimeOffset']" />
                    </converters>
                </indexFieldStorageValueFormatter>
            </defaultCloudIndexConfiguration>
        </indexConfigurations>
    </contentSearch>
</sitecore>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.