I have Sitecore 9.3 SXA with Azure search
in our application. We are trying to create a custom SXA search token to filter upcoming events starting from the current date.
In the code am trying to pass the date range
as [2020-11-30T00:00:00.000Z TO *]
in SearchStringModel. It is working fine in my local with Solr search when testing the code on dev with Azure search. Below is the error from the Console for the SXA search service, log details, and code implementation for reference.
**Error:** Field 'eventdate_dt' with value '[2020-11-30T00:00:00.000Z TO *]' of type 'System.String' cannot be converted to type 'System.DateTimeOffset' declared for the field in the schema.
**Log**
Exception: System.NotSupportedException
Message: Field 'eventdate_dt' with value '[2020-11-30T00:00:00.000Z TO *]' of type 'System.String' cannot be converted to type 'System.DateTimeOffset' declared for the field in the schema.
Source: Sitecore.XA.Foundation.Search.Providers.Azure
at Sitecore.XA.Foundation.Search.Providers.Azure.CloudIndexFieldStorageValueFormatter.FormatValueForIndexStorage(Object value, String fieldName)
at Sitecore.ContentSearch.Azure.Query.CloudQueryMapper.HandleWildcardMatch(WildcardMatchNode node)
at Sitecore.ContentSearch.Azure.Query.CloudQueryMapper.HandleAnd(AndNode node, CloudQueryMapperState mappingState)
at Sitecore.ContentSearch.Azure.Query.CloudQueryMapper.HandleWhere(WhereNode node, CloudQueryMapperState mappingState)
at Sitecore.ContentSearch.Azure.Query.CloudQueryMapper.HandleWhere(WhereNode node, CloudQueryMapperState mappingState)
at Sitecore.ContentSearch.Azure.Query.CloudQueryMapper.HandleWhere(WhereNode node, CloudQueryMapperState mappingState)
at Sitecore.ContentSearch.Azure.Query.CloudQueryMapper.MapQuery(IndexQuery query)
at Sitecore.XA.Foundation.Search.Spatial.GenericQueryable`2.GetQuery(Expression expression)
at Sitecore.ContentSearch.Linq.Parsing.GenericQueryable`2.Execute[TResult](Expression expression)
at Sitecore.XA.Feature.Search.Controllers.SearchController.GetResults(QueryModel model)
Nested Exception
Exception: System.FormatException
Message: String was not recognized as a valid DateTime.
Source: mscorlib
at System.DateTimeParse.Parse(String s, DateTimeFormatInfo dtfi, DateTimeStyles styles, TimeSpan& offset)
at System.DateTimeOffset.Parse(String input, IFormatProvider formatProvider, DateTimeStyles styles)
at Sitecore.XA.Foundation.Search.Providers.Azure.CloudIndexFieldStorageValueFormatter.TryConvertToPrimitiveType(Object value, Type expectedType, Object& result)
at Sitecore.XA.Foundation.Search.Providers.Azure.CloudIndexFieldStorageValueFormatter.ConvertToType(Object value, Type expectedType, ITypeDescriptorContext context)
at Sitecore.XA.Foundation.Search.Providers.Azure.CloudIndexFieldStorageValueFormatter.FormatValueForIndexStorage(Object value, String fieldName)
Code
public class ExcludeItemsWithPreviousDates : ResolveSearchQueryTokensProcessor
{
protected string TokenPart { get; } = "ExcludeItemWithPreviousDateInDateField";
[SxaTokenKey]
protected override string TokenKey => FormattableString.Invariant(FormattableStringFactory.Create("{0}|FieldName", (object)this.TokenPart));
public override void Process(ResolveSearchQueryTokensEventArgs args)
{
if (args.ContextItem == null || args.ContextItem.ID.IsNull)
return;
try
{
for (var index = 0; index < args.Models.Count; ++index)
{
var model = args.Models[index];
Log.Info($"SXA_Token model:{model.Value}", "SXA_Token");
if (model.Type.Equals("sxa", StringComparison.OrdinalIgnoreCase) && ContainsToken(model))
{
string fieldName = model.Value.Replace(TokenPart, string.Empty).TrimStart('|');
var dateField = args.ContextItem.Fields[fieldName];
Log.Info($"SXA_Token field:{dateField}", "SXA_Token");
if (dateField != null)
{
Log.Info($"SXA_Token model value:{args.Models[index].Value}", "SXA_Token");
args.Models.Insert(index, this.BuildModel(fieldName));
args.Models.Remove(model);
}
Log.Info($"SXA_Token model removing: {model.Value}", "SXA_Token");
}
}
}
catch(Exception e)
{
Log.Error($"SXA_Token Exceptio:{e.Message}", "SXA_Token");
}
}
private SearchStringModel BuildModel(string fieldName)
{
Log.Info($"SXA_Token customSearchModel: {new SearchStringModel("custom", FormattableString.Invariant(FormattableStringFactory.Create("{0}|{1}", (object)fieldName.ToLowerInvariant(), $"[{DateTime.Today.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'")} TO *]")))}", "SXA_Token");
return new SearchStringModel("custom", FormattableString.Invariant(FormattableStringFactory.Create("{0}|{1}", (object)fieldName.ToLowerInvariant(), (object)$"[{DateTime.Today.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'")} TO *]" )))
{
Operation = "must"
};
}
protected override bool ContainsToken(SearchStringModel m)
{
return Regex.Match(m.Value, FormattableString.Invariant(FormattableStringFactory.Create("{0}\\|[a-zA-Z ]*", (object)this.TokenPart))).Success;
}
}