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

"Simple.OData.Client.UnresolvableObjectException: Type [FooStatus] not found" for Enum Foo #900

Open
iant-ee opened this issue Apr 3, 2023 · 0 comments

Comments

@iant-ee
Copy link

iant-ee commented Apr 3, 2023

I've come across some odd behaviour which is as much about our specific OData setup as it is a problem in the library, but I just wanted to note it here for our future reference and for the benefit of anyone searching for this error message.

Our client has a simple search using a c# Enum:

namespace Enums
{
    public enum FooStatus
    {
        Published = 1,
        Draft = 2,
        Deleted = 3
    }
}
var publishedFoos = await client
    .For<Foo>()
    .Filter(f => f.FooStatus.ToString() == Enums.FooStatus.Published);
    .FindEntriesAsync();

This results in the following error:

Simple.OData.Client.UnresolvableObjectException: Type [FooStatus] not found
   at Simple.OData.Client.V4.Adapter.Metadata.GetQualifiedTypeName(String typeName)
   at Simple.OData.Client.Adapter.MetadataCache.<GetQualifiedTypeName>b__37_0(String x)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Simple.OData.Client.Adapter.MetadataCache.GetQualifiedTypeName(String typeOrCollectionName)
   at Simple.OData.Client.V4.Adapter.CommandFormatter.ConvertValueToUriLiteral(Object value, Boolean escapeDataString)
   at Simple.OData.Client.ODataExpression.FormatValue(ExpressionContext context)
   at Simple.OData.Client.ODataExpression.FormatToStringFunction(ExpressionContext context)
   at Simple.OData.Client.ODataExpression.FormatFunction(ExpressionContext context)
   at Simple.OData.Client.ODataExpression.Format(ExpressionContext context)
   at Simple.OData.Client.ODataExpression.FormatExpression(ODataExpression expr, ExpressionContext context)
   at Simple.OData.Client.ODataExpression.Format(ExpressionContext context)
   at Simple.OData.Client.ResolvedCommand.ResolveFilter(FluentCommandDetails details)
   at Simple.OData.Client.ResolvedCommand..ctor(FluentCommand command, ISession session)
   at Simple.OData.Client.FluentCommand.Resolve(ISession session)
   at Simple.OData.Client.BoundClient`1.FindEntriesAsync(ODataFeedAnnotations annotations, CancellationToken cancellationToken)

Digging into this I've discovered that because we're using a C# Enum in our client code, the library assumes that we've also got an Enums in our OData service. In fact the OData service we're calling defines this column as a string, so in the example above we'd want the filter to be FooStatus eq "Published".

<EntityType Name="Foo">
<Key>
<PropertyRef Name="FooId"/>
</Key>
<Property Name="DisplayName" Type="Edm.String"/>
<Property Name="FooStatus" Type="Edm.String"/>
</EntityType>

The relevant library code is:

public class CommandFormatter : CommandFormatterBase
{
    public override string ConvertValueToUriLiteral(object value, bool escapeDataString)
    {
        var type = value?.GetType();

        if (value != null && _session.TypeCache.IsEnumType(type))
        {
            value = new ODataEnumValue(value.ToString(), _session.Metadata.GetQualifiedTypeName(type.Name));
        }
        ...
    }
}

IsEnumType checks if we have a c# enum.
Metadata.GetQualifiedTypeName looks up the name of the OData Enum.

Fix for us will be to use a string in our client code, instead of the c# enum.

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

No branches or pull requests

1 participant