Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Composite search filter can not search for Enums. #58

Open
Cubody opened this issue Jan 8, 2023 · 6 comments
Open

Composite search filter can not search for Enums. #58

Cubody opened this issue Jan 8, 2023 · 6 comments
Labels
question Further information is requested

Comments

@Cubody
Copy link

Cubody commented Jan 8, 2023

I have such filter:

public class StudentInfoShortResponseFilter : PaginationFilterBase
{
    [CompareTo(nameof(StudentInfoShortResponse.FullName),
        nameof(StudentInfoShortResponse.AcademicGroup),
        nameof(StudentInfoShortResponse.StudentIdCard),
        nameof(StudentInfoShortResponse.Institute))]
    [StringFilterOptions(StringFilterOption.Contains)]
    [ToLowerContainsComparison]
    public string? Search { get; set; }
}

And when I'm trying to write in 'search' anything - it always gives me all records, not filtering it.
StudentInfoShortResponse.Institute - enum type.
If I'll delete this from attribute - it will search for other properties.

With such enum property in filter attribute it stops write filter in query.

If I'll write

public Institute? Institute {get;set;}

in filter - all will be fine too.

@Cubody
Copy link
Author

Cubody commented Jan 8, 2023

System.ArgumentException: Method 'Boolean Contains(System.String)' declared on type 'System.String' cannot be called with instance of type 'ItPos.DataAccess.Common.Models.User.Institute'
at System.Linq.Expressions.Expression.ValidateCallInstanceType(Type instanceType, MethodInfo method)
at System.Linq.Expressions.Expression.ValidateStaticOrInstanceMethod(Expression instance, MethodInfo method)
at System.Linq.Expressions.Expression.ValidateMethodAndGetParameters(Expression instance, MethodInfo method)
at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, Expression arg0)
at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable`1 arguments)
at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, Expression[] arguments)
at AutoFilterer.Attributes.StringFilterOptionsAttribute.BuildExpressionWithoutComparison(StringFilterOption option, Expression expressionBody, PropertyInfo property, Object value)
at AutoFilterer.Attributes.StringFilterOptionsAttribute.BuildExpression(Expression expressionBody, PropertyInfo targetProperty, PropertyInfo filterProperty, Object value)
at AutoFilterer.Attributes.CompareToAttribute.BuildExpressionForProperty(Expression expressionBody, PropertyInfo targetProperty, PropertyInfo filterProperty, Object value)
at AutoFilterer.Types.FilterBase.BuildExpression(Type entityType, Expression body)

@enisn
Copy link
Owner

enisn commented Jan 8, 2023

Institute is a different type than string, so string and Institute can't be compared. You should compare Search parameter to one of the Institute parameter.

Something like"Institute.Name" should be working:

public class StudentInfoShortResponseFilter : PaginationFilterBase
{
    [CompareTo(nameof(StudentInfoShortResponse.FullName),
        nameof(StudentInfoShortResponse.AcademicGroup),
        nameof(StudentInfoShortResponse.StudentIdCard),
        "Institute.Name")]
    [StringFilterOptions(StringFilterOption.Contains)]
    [ToLowerContainsComparison]
    public string? Search { get; set; }
}

@enisn
Copy link
Owner

enisn commented Jan 8, 2023

Oh, sorry, I missed that Institute is an enum.

Enums are numeric fields and stored as numeric value types in databases by default. If you want to compare strings to enums, you should project enum values as string value in a different field and filter that field with autofilterer. That projection might be done with Select() LINQ method.

myDataSource.Select(x => new MyProjectedResult
{
    FullName = x.FullName,
    AcademicGroup = x. AcademicGroup,
    StudentIdCard = x. StudentIdCard,
    InstituteName = x.Institute?.ToString()
}).ApplyFilter(...)

And you can use InstituteName string field for filtering:
Institute is a different type than string, so string and Institute can't be compared. You should compare Search parameter to one of the Institute parameter.

Something like"Institute.Name" should be working:

public class StudentInfoShortResponseFilter : PaginationFilterBase
{
    [CompareTo(nameof(StudentInfoShortResponse.FullName),
        nameof(StudentInfoShortResponse.AcademicGroup),
        nameof(StudentInfoShortResponse.StudentIdCard),
        "InstituteName")] // 👈 here
    [StringFilterOptions(StringFilterOption.Contains)]
    [ToLowerContainsComparison]
    public string? Search { get; set; }
}

@enisn enisn added the question Further information is requested label Jan 8, 2023
@Cubody
Copy link
Author

Cubody commented Jan 8, 2023

It says then that it can not do query with toString(), like not supported, but I'm using mapster, so Idk.

@Cubody
Copy link
Author

Cubody commented Jan 9, 2023

Thanks for the your answer btw!
It's possible via straight property in Filter like

public Institute? Institute {get;set;}

But not via CompareToAttribute - it's strange thing.
But I see why it works like it works.

@Cubody
Copy link
Author

Cubody commented Jan 15, 2023

When you see that a separate field is working, there is a feeling that the complex variable will also work. I would consider this as a possible vector for improving your solution. If I have the time/opportunity, I will take a look and try to come up with a solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants