IharYakimush / comminity-data-odata-linq

Use OData filter text query in linq expresson for any IQuerable without ASP.NET dependency. Support netstandard2.0
Other
42 stars 16 forks source link

Possible bug in $expand(EntityName($filter)) #32

Open mgesc opened 5 years ago

mgesc commented 5 years ago

Hi Ihar,

I've been testing the filter inside the expand and for my use case i can't get it work. It seem that the $filter string is being bypased on nested entities.

In addition, when trying to use the .ToJson() seems that the "NullHandlingValue.Ignore" option is also being ignored

I've setup a .netfiddle for you to replicate those issues and point me in the right direction if i'm doing something wrong.

https://dotnetfiddle.net/KCbGib

Regards

IharYakimush commented 5 years ago

Hi @mgesc ,

Filter in expand and expand itself applicable for collections. In your sample you trying to expand and filter single property "URLT" declared as public virtual URLT URLT { get; set; }. It is not a collection, hence can't be filtered in expand. You can add filter to root level if needed e.g. string filter = "(PDAID eq 1 or PDAID eq 3) and isDeleted eq false and DA/URLT/isDeleted eq true";

Regarding ToJson NullHandlingValue.Ignore I need time to check the root cause. Probably this is because of using SelectExpandWrapperConverter

Thanks, Ihar

mgesc commented 5 years ago

Indeed!! I didn't realize that expand filter only work over collections. Thank you very much, Ihar!!

mgesc commented 5 years ago

@IharYakimush I have managed to solve the null handling issue with this helper class. I'll leave it here if it's helpful to you.

It's a very dumb solution but as a hot fix it helps.

string list = list1.ToJson().ToString();
JToken token = JsonHelper.RemoveEmptyChildren(JToken.Parse(list));
object result = JsonConvert.DeserializeObject<object>(token.ToString(), settings);

where settings

JsonSerializerSettings settings = new JsonSerializerSettings()
{
   ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
   NullValueHandling = NullValueHandling.Ignore
};

and JsonHelper

public static class JsonHelper
{
    public static JToken RemoveEmptyChildren(JToken token)
    {
        if (token.Type == JTokenType.Object)
        {
            JObject copy = new JObject();
            foreach (JProperty prop in token.Children<JProperty>())
            {
                JToken child = prop.Value;
                if (child.HasValues)
                {
                    child = RemoveEmptyChildren(child);
                }
                if (!IsEmpty(child))
                {
                    copy.Add(prop.Name, child);
                }
            }
            return copy;
        }
        else if (token.Type == JTokenType.Array)
        {
            JArray copy = new JArray();
            foreach (JToken item in token.Children())
            {
                JToken child = item;
                if (child.HasValues)
                {
                    child = RemoveEmptyChildren(child);
                }
                if (!IsEmpty(child))
                {
                    copy.Add(child);
                }
            }
            return copy;
        }
        return token;
    }

    public static bool IsEmpty(JToken token)
    {
        return (token.Type == JTokenType.Null) ||
         (token.Type == JTokenType.Array && !token.HasValues) ||
         (token.Type == JTokenType.Object && !token.HasValues);
    }
}