[CSHARP-2466] InvalidOperationException with IQueryable and ExtraElements Created: 28/Dec/18  Updated: 25/Jun/20  Resolved: 25/Jun/20

Status: Closed
Project: C# Driver
Component/s: BSON, Linq
Affects Version/s: 2.7.2
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Vincent Ugenti Assignee: Wan Bachtiar
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Trying to integrate Microsoft OData v4 stack with Mongo C# Driver. I would like to expose a Mongo collection and enable the OData $filter operation against the fields contained in the ExtraElements dictionary.

I have created a minimal example of the issue. Beginning with an empty WebAPI project in Visual Studio 2015, I created the following model:

public class TestEntity

{ [BsonId, BsonElement("_id")] public ObjectId _id \{ get; set; }

public string Id { get; set; }

[BsonExtraElements]
public Dictionary<string, object> ExtraElements { get; set; }
}

I exposed EDM EntitySet via OData by adding the following at the end of `WebApiConfig.Register()` method:

// OData
var edmBuilder = new ODataConventionModelBuilder();
edmBuilder.EntitySet<TestEntity>("test");

config.MapODataServiceRoute("odata", "odata", edmBuilder.GetEdmModel());

Finally, I created a simple TestController:

public class TestController : ODataController
{
[EnableQuery(AllowedFunctions = Microsoft.AspNet.OData.Query.AllowedFunctions.All)]
public IQueryable<TestEntity> Get()

{ var mongo = new MongoClient(); var db = mongo.GetDatabase("test"); var collection = db.GetCollection<TestEntity>("test"); var result = collection.AsQueryable() as IQueryable<TestEntity>; return result; }

}

I added an actual object to the Mongo collection:

> db.test.insert( {Id:'test', Name:'testName'}) WriteResult({ "nInserted" : 1 })
> db.test.find()

> { "_id" : ObjectId("5c266040fd7e5a3c63b33cd8"), "Id" : "test", "Name" : "testName" }

Now I can query find as long as I don't try to use $filter on the ExtraElements (note that OData is not rendering the ObjectId field properly, but I do not believe this is related to the problem):

http://localhost:63927/odata/test

{"@odata.context":"http://localhost:63927/odata/$metadata#test","value":[\{"Id":"test","Name":"testName","_id":{}}]}

However, if I try to filter against the `Name` (one of the `ExtraElements`) the following error occurs:

http://localhost:63927/odata/test?$filter=Name%20eq%20%27testName%27

*Message: Convert(IIF((({document}

{ExtraElements} != null) AndAlso {document}{ExtraElements}

.ContainsKey(\"Name\")), {document}

{ExtraElements}

.Item[\"Name\"], null)) is not supported.*

Exception: System.InvalidOperationException

Stack Trace:
at MongoDB.Driver.Linq.Translators.PredicateTranslator.GetFieldExpression(Expression expression)
at MongoDB.Driver.Linq.Translators.PredicateTranslator.TranslateComparison(Expression variableExpression, ExpressionType operatorType, ConstantExpression constantExpression)
at MongoDB.Driver.Linq.Translators.PredicateTranslator.Translate(Expression node)
at MongoDB.Driver.Linq.Translators.PredicateTranslator.Translate(Expression node, IBsonSerializerRegistry serializerRegistry)
at MongoDB.Driver.Linq.Translators.QueryableTranslator.TranslateWhere(WhereExpression node)
at MongoDB.Driver.Linq.Translators.QueryableTranslator.TranslatePipeline(PipelineExpression node)
at MongoDB.Driver.Linq.Translators.QueryableTranslator.Translate(Expression node, IBsonSerializerRegistry serializerRegistry, ExpressionTranslationOptions translationOptions)
at MongoDB.Driver.Linq.MongoQueryProviderImpl`1.Execute(Expression expression)
at MongoDB.Driver.Linq.MongoQueryableImpl`2.GetEnumerator()
at Microsoft.AspNet.OData.Formatter.Serialization.ODataResourceSetSerializer.WriteResourceSet(IEnumerable enumerable, IEdmTypeReference resourceSetType, ODataWriter writer, ODataSerializerContext writeContext)
at Microsoft.AspNet.OData.Formatter.ODataOutputFormatterHelper.WriteToStream(Type type, Object value, IEdmModel model, ODataVersion version, Uri baseAddress, MediaTypeHeaderValue contentType, IWebApiUrlHelper internaUrlHelper, IWebApiRequestMessage internalRequest, IWebApiHeaders internalRequestHeaders, Func`2 getODataMessageWrapper, Func`2 getEdmTypeSerializer, Func`2 getODataPayloadSerializer, Func`1 getODataSerializerContext)
at Microsoft.AspNet.OData.Formatter.ODataMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)
— End of stack trace from previous location where exception was thrown —
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__1b.MoveNext()

 



 Comments   
Comment by Rachelle Palmer [ 25/Jun/20 ]

Hi there, thank you for reaching out to MongoDB. As this sounds more like a support issue, I wanted to give you some resources to get this question answered more quickly:

  • our MongoDB support portal, located at support.mongodb.com
  • our MongoDB community forums, located here
  • If you are an Atlas customer, there is free support offered 24/7 in the lower right hand corner of the UI.

Thank you!
Rachelle

Comment by Vincent Ugenti [ 28/Dec/18 ]

 

Also to clarify further, if the "Name" property is then added to the TestEntity class, the $filter operation works as expected.

Generated at Wed Feb 07 21:42:38 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.