1

When I try to create a custom rule and pass field name, I get Instance property 'textField' is not defined for type 'Sitecore.ContentSearch.SearchTypes.SearchResultItem' exception.

This is how my query expression is set.

    public Expression GetQueryExpression(ConditionContext p_Context)
    {
        Expression readNameProperty = Expression.Property(p_Context.ParameterExpression, "textField");
        Expression standardValuesConstant = Expression.Constant("somevalue");

        return Expression.Equal(readNameProperty, standardValuesConstant);
    }

1 Answer 1

5

By using Expression.Property(...) you are trying to access a Property with the name textField on the SearchResultItem, which corresponds to this:

SearchResultItem.textField

To get a field value you instead need to use the indexer on SearchResultItem which corresponds to this:

SearchResultItem['textField']

I don't know much about Coveo, but I found Creating a Custom Rule Condition for Coveo for Sitecore in their developer guide which explains it pretty well.

It's a bit complicated to do this, so in the guide they have made a method for just that: GetFieldIndexerExpression(...).

/// <summary>
/// Gets the <see cref="Expression"/> that will invoke the indexer for the field <paramref name="p_FieldName"/>.
/// </summary>
/// <remarks>The indexer must be called as a method, not as a property.</remarks>
/// <param name="p_Instance">The parameter instance of the Linq expression. This is the part of the Linq expression before the <c>=></c> symbol.
///   <example>item => item["fieldName"]</example>
/// </param>
/// <param name="p_FieldName">The field name to reference in the indexer.</param>
/// <returns>The <see cref="Expression"/> that will invoke the field indexer when executed.</returns>
Expression GetFieldIndexerExpression(ParameterExpression p_Instance, string p_FieldName)
{
    string indexerPropertyName = "Item";
    // By default the indexer corresponds to the "Item" property, but one can change it.
    // In order to find the name, if modified, we must search for DefaultMemberAttribute attribute.
    // Fortunately, only one indexer name can be defined.
    object[] attributes = p_Instance.Type.GetCustomAttributes(typeof(DefaultMemberAttribute), true);
    if (attributes.Any()) {
        indexerPropertyName = (attributes[0] as DefaultMemberAttribute).MemberName;
    }

    PropertyInfo indexerProperty = p_Instance.Type.GetProperty(indexerPropertyName,
                                                               new Type[] { typeof(string) });
    MethodInfo indexerGetMethod = indexerProperty.GetMethod;

    Expression callIndexerExpression = Expression.Call(p_Instance,
                                                       indexerGetMethod,
                                                       Expression.Constant(p_FieldName));
    return callIndexerExpression;
}

You then use it instead of Expression.Property(...) like this:

public Expression GetQueryExpression(ConditionContext p_Context)
{
    Expression readNameProperty = GetFieldIndexerExpression(p_Context.ParameterExpression, "textField");
    Expression standardValuesConstant = Expression.Constant("somevalue");

    return Expression.Equal(readNameProperty, standardValuesConstant);
}

With this it should now work correctly.

Your Answer

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

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