OData / WebApi

OData Web API: A server library built upon ODataLib and WebApi
https://docs.microsoft.com/odata
Other
857 stars 473 forks source link

odata webapi core: sehexception when using $apply=aggregate #1413

Open mysticdotnet opened 6 years ago

mysticdotnet commented 6 years ago

When i use $apply=aggregate with your sample (https://github.com/OData/WebApi/tree/master/samples/AspNetCoreODataSample.Web) it throw sehexception

Assemblies affected

*Microsoft.AspNetCore.OData with asp.net core

Reproduce steps

I clone this project (https://github.com/OData/WebApi), i open this solution the odata core solution (WebApiOData.AspNetCore.sln) and i run the sample project (https://github.com/OData/WebApi/tree/master/samples/AspNetCoreODataSample.Web) and after i run this query: localhost:5912/odata/Movies?$apply=groupby((ReleaseDate))

Expected result

Show the result of the odata aggregate query

Actual result

sehexception

xuzhg commented 6 years ago

@mysticdotnet

Thanks for tring our sample. I change the sample and verify that the sehexception is not from our codes. I do think it's from efcore.

Because, when I change to use the in-memory data, the same aggregate expression can work. for example:

image

But, when I switch to EFCore, it throws the sehexception.

mysticdotnet commented 6 years ago

Thanks a lot for your help. Should i submit a ticket to the ef core team with a reference to this issue ?

xuzhg commented 6 years ago

@mysticdotnet That's helpful. Let's follow up the input form EFCore. Thanks.

karelz commented 6 years ago

@xuzhg @ajcvickers can you please provide info about how to debug the underlying problem? -- see more details in https://github.com/dotnet/corefx/issues/29526#issuecomment-388932741 I can't always reproduce AV and it is not clear where things go wrong. If you have steps how to get to a failure point under debugger, I can help route it to the right place.

ajcvickers commented 6 years ago

@karelz I was unable even to repro the issue.

xuzhg commented 6 years ago

@karelz @ajcvickers I think it's easy to repo using our sample project.

  1. Git clone:
git clone git@github.com:OData/WebApi.git
  1. VS2017 opens solution: https://github.com/OData/WebApi/blob/master/sln/WebApiOData.AspNetCore.sln

  2. Build and run: AspNetCoreODataSample.Web project

  3. Postman file request at: http://localhost:5913/efcore/Movies?$apply=groupby((ReleaseDate))

  4. Check the response, you will get the sehexception

Please let me know if it can't work at your side.

karelz commented 6 years ago

@xuzhg that is exactly what I tried. Attached windbg to IISExpress - no exception. Even no sehexception in VS, just 502 as I posted in https://github.com/dotnet/corefx/issues/29526#issuecomment-388932741

xuzhg commented 6 years ago

Werid! It can't repo at my side now. @mysticdotnet Can you repro it?

mysticdotnet commented 6 years ago

@xuzhg Sorry Sam, what do you mean by repo it ?

mysticdotnet commented 6 years ago

@xuzhg I think the same issue 1221 is reported

xuzhg commented 6 years ago

@mysticdotnet Sorry. I mean to reproduce it.

mysticdotnet commented 6 years ago

@xuzhg the exception occurs every time Repro:

  1. Clone / unzip https://github.com/OData/WebApi

  2. Open sln\WebApiOData.AspNetCore.sln

  3. Make samples\AspNetCoreODataSamples.Web project as StartUp project

  4. Run the project in Debug mode (F5) - Browser opens URL http://localhost:5912/efcore/Movies Browser will show: {"@odata.context":"http://localhost:5912/efcore/$metadata#Movies","value":[{"ID":1,"Title":"Conan","ReleaseDate":"2017-03-03T00:00:00-08:00","Genre":"Comedy","Price":1.99}]}

  5. Use URL in browser: http://localhost:5912/efcore/Movies?$apply=groupby((ReleaseDate)) Result:

the application is in break mode

xuzhg commented 6 years ago

@karelz did you follow up @mysticdotnet 's step?

karelz commented 6 years ago

@xuzhg I am able to repro problem (only in first F5 run in VS), but the exception is not coming from IISExpress process (nothing shows up in windbg) - see https://github.com/dotnet/corefx/issues/29526#issuecomment-388932741. It is quite possible that the dialog is just a decoy / bug in VS itself, or it comes from other processes -- IMO we need to focus on what happens in IISExpress process (where the service runs I assume). I need area experts to find that out - once you tell me which native/managed exception to track down, I can help route it.

mysticdotnet commented 6 years ago

@karelz Repro without iisexpress:

  1. Open cmd prompt
  2. cd to debug folder: ...\WebApi\samples\AspNetCoreODataSample.Web\bin\Debug\netcoreapp2.0
  3. run this cmd: dotnet AspNetCoreODataSample.Web.dll
  4. launch Windbg
  5. Go to: File > Attach to Process
  6. The list of processes appear
  7. Select dotnet.exe process opened in step 3
  8. this output appear with some exceptions: output.txt
  9. Start debug in Windbg
  10. open browser with this link: localhost:5000/efcore/Movies?$apply=groupby((ReleaseDate))
  11. This output is appended with Access violation exception in it:

(1b40.2688): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. System_Private_CoreLib!System.Collections.Generic.Dictionary2+KeyCollection+Enumerator[System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken,System.__Canon]..ctor(System.Collections.Generic.Dictionary2<System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken,System.__Canon>)$##600454E+0xf7562: 00007fff`695eb392 cd68 int 68h

karelz commented 6 years ago

Can you please get a callstack from the AV? (k command in windbg, sxe eh or sxe av will stop on first-chance exceptions)

mysticdotnet commented 6 years ago

@karelz With k command i have this output now: output.txt

mysticdotnet commented 6 years ago

@karelz @xuzhg I do the same test with asp.net core 2.1 release, unfortunately, i have the same error. Maybe it's a .net core clr issue !

mysticdotnet commented 6 years ago

@karelz @xuzhg I have more information now: 1-I edit AspNetCoreODataSample.Web.csproj, i add this PropertyGroup: `

win10-x86

` 2-After that i run the app in Debug Mode (F5) 3-open browser with this link: localhost:5000/efcore/Movies?$apply=groupby((ReleaseDate)) 4-Line 80 of DynamicTypeWrapper.cs throw this exception:

readmemory

5-I change the line 80 like this:

line80

6- Re run the app, i get another exception here:

serialize

karelz commented 6 years ago

The stack trace above (https://github.com/OData/WebApi/issues/1413#issuecomment-392662943) is missing some symbols :( @xuzhg can you please help to get the right callstack form the repro for further routing?

mysticdotnet commented 6 years ago

@karelz With .symfix[+] [LocalSymbolCache] cmd, i have this output output.txt and this stack stack.txt

mysticdotnet commented 6 years ago

@karelz @xuzhg did you see the Jan analysis about this issue ?

mysticdotnet commented 6 years ago

@xuzhg Did you expect a fix for this issue in the beta phase ?

xuzhg commented 6 years ago

@mysticdotnet Sorry for later response. What do you mean beta? That's in OData side or EFCore side?

mysticdotnet commented 6 years ago

@xuzhg I mean OData.

xuzhg commented 6 years ago

@mysticdotnet Sorry, I am a little bit confusing.

  1. Did you figure out the root cause?

  2. If yes, where comes the root cause? in OData side, or EFCore side?

  3. If that's OData problem, would you please share us what your found?

  4. If that's EFCore problem, it's better to fix , but OData itself doesn't depend on it.

mysticdotnet commented 6 years ago

@xuzhg I don't have more information about the root cause. Sorry for that and thank you very much

smitpatel commented 6 years ago

I investigated based on data provided and information given by .NET team and we may have possible cause of the issue here.

Ref: thread on EF Core repo which has more details (https://github.com/aspnet/EntityFrameworkCore/issues/12733)

Particularly posting last outcome from corefx team

From @jkotas

The crash is caused by invalid IL generated via Reflection.Emit.

Method Name:  DynamicClass.lambda_method(System.Runtime.CompilerServices.Closure, AspNetCoreODataSample.Web.Models.Movie)

IL_0000: newobj 6000002 Microsoft.AspNet.OData.Query.Expressions.GroupByWrapper..ctor()
IL_0005: dup 
IL_0006: newobj 6000003 Microsoft.AspNet.OData.Query.Expressions.AggregationPropertyContainer+LastInChain..ctor()
IL_000b: dup 
IL_000c: ldstr 70000004 "ReleaseDate"
IL_0011: callvirt 6000005 
IL_0016: dup 
IL_0017: ldarg.1 
// This returns System.DateTimeOffset
IL_0018: callvirt 6000006 AspNetCoreODataSample.Web.Models.Movie.get_ReleaseDate()
// This passes it to method that object reference - bad type mismatch!!!!
IL_001d: callvirt 6000007 Microsoft.AspNet.OData.Query.Expressions.PropertyContainer+NamedProperty`1[[System.__Canon, System.Private.CoreLib]].set_Value(System.__Canon) IL_0022: callvirt 6000008 Microsoft.AspNet.OData.Query.Expressions.GroupByWrapper.set_GroupByContainer(Microsoft.AspNet.OData.Query.Expressions.AggregationPropertyContainer)
IL_0027: ret 

The method with invalid IL is created at this callstack:

system_private_corelib!System.Reflection.Emit.DynamicMethod.GetMethodDescriptor()+0x10a
system_private_corelib!System.Reflection.Emit.DynamicMethod.CreateDelegate(System.Type, System.Object)+0x2a
DynamicClass.lambda_method(System.Runtime.CompilerServices.Closure, Microsoft.EntityFrameworkCore.Query.QueryContext)+0x1a2
microsoft_entityframeworkcore!Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[[System.Int32, System.Private.CoreLib]](System.Linq.Expressions.Expression)+0x7456ac12
microsoft_entityframeworkcore!Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[[System.Int32, System.Private.CoreLib]](System.Linq.Expressions.Expression)+0x74562e78
remotion_linq!Remotion.Linq.QueryableBase`1[[System.__Canon, System.Private.CoreLib]].System.Collections.IEnumerable.GetEnumerator()+0x21
newtonsoft_json!Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(Newtonsoft.Json.JsonWriter, System.Collections.IEnumerable, Newtonsoft.Json.Serialization.JsonArrayContract, Newtonsoft.Json.Serialization.JsonProperty, Newtonsoft.Json.Serialization.JsonContainerContract, Newtonsoft.Json.Serialization.JsonProperty)+0xe5
newtonsoft_json!Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(Newtonsoft.Json.JsonWriter, System.Object, Newtonsoft.Json.Serialization.JsonContract, Newtonsoft.Json.Serialization.JsonProperty, Newtonsoft.Json.Serialization.JsonContainerContract, Newtonsoft.Json.Serialization.JsonProperty)+0x18d
newtonsoft_json!Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(Newtonsoft.Json.JsonWriter, System.Object, System.Type)+0xf1
newtonsoft_json!Newtonsoft.Json.JsonSerializer.SerializeInternal(Newtonsoft.Json.JsonWriter, System.Object, System.Type)+0x468
newtonsoft_json!Newtonsoft.Json.JsonSerializer.Serialize(Newtonsoft.Json.JsonWriter, System.Object)+0x14
microsoft_aspnetcore_mvc_formatters_json!Microsoft.AspNetCore.Mvc.Formatters.JsonOutputFormatter.WriteObject(System.IO.TextWriter, System.Object)+0x53
microsoft_aspnetcore_mvc_formatters_json!Microsoft.AspNetCore.Mvc.Formatters.JsonOutputFormatter+<WriteResponseBodyAsync>d__11.MoveNext()+0xf6
system_private_corelib!System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start[[System.__Canon, System.Private.CoreLib]](System.__Canon ByRef)+0xffffffff`ab1048d9
microsoft_aspnetcore_mvc_formatters_json!Microsoft.AspNetCore.Mvc.Formatters.JsonOutputFormatter.WriteResponseBodyAsync(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterWriteContext, System.Text.Encoding)+0x65
microsoft_aspnetcore_mvc_core!Microsoft.AspNetCore.Mvc.Formatters.TextOutputFormatter.WriteAsync(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterWriteContext)+0x160

As @divega mentioned on that thread, EF Core does not use Reflection.Emit so bad IL is not result of something in EF Core.

I hand-crafted the query being created by OData for particular request. There is slight mismatch in what compiler generates vs what OData generated. Hand-written query (had to make some internal class public)

                var query = _context.Movies.AsNoTracking()
                    .GroupBy(it => new GroupByWrapper
                    {
                        GroupByContainer = new AggregationPropertyContainer.LastInChain
                        {
                            Name = "ReleaseDate",
                            Value = it.ReleaseDate
                        }
                    })
                .Select(it => new AggregationWrapper
                {
                    GroupByContainer = it.Key.GroupByContainer
                }).ToList();

IQueryable.Expression output for both the queries.

// Hand-written version
.Call System.Linq.Queryable.Select(
    .Call System.Linq.Queryable.GroupBy(
        .Call Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.AsNoTracking(.Constant<Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[AspNetCoreODataSample.Web.Models.Movie]>(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[AspNetCoreODataSample.Web.Models.Movie]))
        ,
        '(.Lambda #Lambda1<System.Func`2[AspNetCoreODataSample.Web.Models.Movie,Microsoft.AspNet.OData.Query.Expressions.GroupByWrapper]>))
    ,
    '(.Lambda #Lambda2<System.Func`2[System.Linq.IGrouping`2[Microsoft.AspNet.OData.Query.Expressions.GroupByWrapper,AspNetCoreODataSample.Web.Models.Movie],Microsoft.AspNet.OData.Query.Expressions.AggregationWrapper]>))

.Lambda #Lambda1<System.Func`2[AspNetCoreODataSample.Web.Models.Movie,Microsoft.AspNet.OData.Query.Expressions.GroupByWrapper]>(AspNetCoreODataSample.Web.Models.Movie $it)
{
    .New Microsoft.AspNet.OData.Query.Expressions.GroupByWrapper(){
        GroupByContainer = .New Microsoft.AspNet.OData.Query.Expressions.AggregationPropertyContainer+LastInChain(){
            Name = "ReleaseDate",
            Value = (System.Object)$it.ReleaseDate
        }
    }
}

.Lambda #Lambda2<System.Func`2[System.Linq.IGrouping`2[Microsoft.AspNet.OData.Query.Expressions.GroupByWrapper,AspNetCoreODataSample.Web.Models.Movie],Microsoft.AspNet.OData.Query.Expressions.AggregationWrapper]>(System.Linq.IGrouping`2[Microsoft.AspNet.OData.Query.Expressions.GroupByWrapper,AspNetCoreODataSample.Web.Models.Movie] $it)
{
    .New Microsoft.AspNet.OData.Query.Expressions.AggregationWrapper(){
        GroupByContainer = ($it.Key).GroupByContainer
    }
}

// OData Version
.Call System.Linq.Queryable.Select(
    .Call System.Linq.Queryable.GroupBy(
        .Call Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.AsNoTracking(.Constant<Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[AspNetCoreODataSample.Web.Models.Movie]>(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[AspNetCoreODataSample.Web.Models.Movie]))
        ,
        '(.Lambda #Lambda1<System.Func`2[AspNetCoreODataSample.Web.Models.Movie,Microsoft.AspNet.OData.Query.Expressions.GroupByWrapper]>))
    ,
    '(.Lambda #Lambda2<System.Func`2[System.Linq.IGrouping`2[Microsoft.AspNet.OData.Query.Expressions.GroupByWrapper,AspNetCoreODataSample.Web.Models.Movie],Microsoft.AspNet.OData.Query.Expressions.AggregationWrapper]>))

.Lambda #Lambda1<System.Func`2[AspNetCoreODataSample.Web.Models.Movie,Microsoft.AspNet.OData.Query.Expressions.GroupByWrapper]>(AspNetCoreODataSample.Web.Models.Movie $$it)
{
    .New Microsoft.AspNet.OData.Query.Expressions.GroupByWrapper(){
        GroupByContainer = .New Microsoft.AspNet.OData.Query.Expressions.AggregationPropertyContainer+LastInChain(){
            Name = "ReleaseDate",
            Value = $$it.ReleaseDate
        }
    }
}

.Lambda #Lambda2<System.Func`2[System.Linq.IGrouping`2[Microsoft.AspNet.OData.Query.Expressions.GroupByWrapper,AspNetCoreODataSample.Web.Models.Movie],Microsoft.AspNet.OData.Query.Expressions.AggregationWrapper]>(System.Linq.IGrouping`2[Microsoft.AspNet.OData.Query.Expressions.GroupByWrapper,AspNetCoreODataSample.Web.Models.Movie] $$it)
{
    .New Microsoft.AspNet.OData.Query.Expressions.AggregationWrapper(){
        GroupByContainer = ($$it.Key).GroupByContainer
    }
}

Output of query model printer in EF Core (Query Model is generated by parsing the Expression tree using Remotion.Linq)

//Hand-written version
dbug: Microsoft.EntityFrameworkCore.Query[10101]
      Compiling query model:
      'from IGrouping<GroupByWrapper, Movie> e in
          (from Movie <generated>_1 in DbSet<Movie>
          select [<generated>_1])
          .AsNoTracking()
          .GroupBy(new GroupByWrapper() {GroupByContainer = new LastInChain() {Name = "ReleaseDate", Value = Convert([<generated>_1].ReleaseDate, Object)}}, [<generated>_1])
      select new AggregationWrapper{ GroupByContainer = [e].Key.GroupByContainer }
      '
dbug: Microsoft.EntityFrameworkCore.Query[10104]
      Optimized query model:
      'from IGrouping<GroupByWrapper, Movie> e in
          (from Movie <generated>_1 in DbSet<Movie>
          select [<generated>_1]).GroupBy(new GroupByWrapper() {GroupByContainer = new LastInChain() {Name = "ReleaseDate", Value = Convert([<generated>_1].ReleaseDate, Object)}}, [<generated>_1])
      select new AggregationWrapper{ GroupByContainer = [e].Key.GroupByContainer }
      '
dbug: Microsoft.EntityFrameworkCore.Query[10107]
      (QueryContext queryContext) => IEnumerable<AggregationWrapper> _InterceptExceptions(
          source: IEnumerable<AggregationWrapper> _Select(
              source: IEnumerable<IGrouping<GroupByWrapper, Movie>> _GroupBy(
                  source: IEnumerable<Movie> EntityQuery(
                      queryContext: queryContext,
                      entityType: EntityType: Movie,
                      key: Key: Movie.ID PK,
                      materializer: (IEntityType entityType | ValueBuffer valueBuffer) =>
                      {
                          instance = new Movie()
                          instance.<ID>k__BackingField = int TryReadValue(valueBuffer, 0, Movie.ID)
                          instance.<Genre>k__BackingField = Genre TryReadValue(valueBuffer, 1, Movie.Genre)
                          instance.<Price>k__BackingField = decimal TryReadValue(valueBuffer, 2, Movie.Price)
                          instance.<ReleaseDate>k__BackingField = DateTimeOffset TryReadValue(valueBuffer, 3, Movie.ReleaseDate)
                          instance.<Title>k__BackingField = string TryReadValue(valueBuffer, 4, Movie.Title)
                          return instance
                      }
                      ,
                      queryStateManager: False),
                  keySelector: (Movie <generated>_1) => new GroupByWrapper{ GroupByContainer = new LastInChain{
                          Name = "ReleaseDate",
                          Value = (object)<generated>_1.ReleaseDate
                      }
                       }
                  ,
                  elementSelector: (Movie <generated>_1) => <generated>_1),
              selector: (IGrouping<GroupByWrapper, Movie> e) => new AggregationWrapper{ GroupByContainer = e.Key.GroupByContainer }
          ),
          contextType: AspNetCoreODataSample.Web.Models.MovieContext,
          logger: DiagnosticsLogger<Query>,
          queryContext: queryContext)

//OData version
dbug: Microsoft.EntityFrameworkCore.Query[10101]
      Compiling query model:
      'from IGrouping<GroupByWrapper, Movie> $it in
          (from Movie <generated>_1 in DbSet<Movie>
          select [<generated>_1])
          .AsNoTracking()
          .GroupBy(new GroupByWrapper() {GroupByContainer = new LastInChain() {Name = "ReleaseDate", Value = [<generated>_1].ReleaseDate}}, [<generated>_1])
      select new AggregationWrapper{ GroupByContainer = [$it].Key.GroupByContainer }
      '
dbug: Microsoft.EntityFrameworkCore.Query[10104]
      Optimized query model:
      'from IGrouping<GroupByWrapper, Movie> $it in
          (from Movie <generated>_1 in DbSet<Movie>
          select [<generated>_1]).GroupBy(new GroupByWrapper() {GroupByContainer = new LastInChain() {Name = "ReleaseDate", Value = [<generated>_1].ReleaseDate}}, [<generated>_1])
      select new AggregationWrapper{ GroupByContainer = [$it].Key.GroupByContainer }
      '
dbug: Microsoft.EntityFrameworkCore.Query[10107]
      (QueryContext queryContext) => IEnumerable<AggregationWrapper> _InterceptExceptions(
          source: IEnumerable<AggregationWrapper> _Select(
              source: IEnumerable<IGrouping<GroupByWrapper, Movie>> _GroupBy(
                  source: IEnumerable<Movie> EntityQuery(
                      queryContext: queryContext,
                      entityType: EntityType: Movie,
                      key: Key: Movie.ID PK,
                      materializer: (IEntityType entityType | ValueBuffer valueBuffer) =>
                      {
                          instance = new Movie()
                          instance.<ID>k__BackingField = int TryReadValue(valueBuffer, 0, Movie.ID)
                          instance.<Genre>k__BackingField = Genre TryReadValue(valueBuffer, 1, Movie.Genre)
                          instance.<Price>k__BackingField = decimal TryReadValue(valueBuffer, 2, Movie.Price)
                          instance.<ReleaseDate>k__BackingField = DateTimeOffset TryReadValue(valueBuffer, 3, Movie.ReleaseDate)
                          instance.<Title>k__BackingField = string TryReadValue(valueBuffer, 4, Movie.Title)
                          return instance
                      }
                      ,
                      queryStateManager: False),
                  keySelector: (Movie <generated>_1) => new GroupByWrapper{ GroupByContainer = new LastInChain{
                          Name = "ReleaseDate",
                          Value = <generated>_1.ReleaseDate
                      }
                       }
                  ,
                  elementSelector: (Movie <generated>_1) => <generated>_1),
              selector: (IGrouping<GroupByWrapper, Movie> $it) => new AggregationWrapper{ GroupByContainer = $it.Key.GroupByContainer }
          ),
          contextType: AspNetCoreODataSample.Web.Models.MovieContext,
          logger: DiagnosticsLogger<Query>,
          queryContext: queryContext)

Based on ExpressionTree & QueryModel output, the difference is in GroupByWrapper creation, where assigning ReleaseDate to Value property has Convert node since release date is DateTime and Value is of type object. Further, according to @jkotas 's post there is bad type mismatch happening inside IL after getting value of ReleaseDate and assigning it to Value Property. Based on missing Convert node in OData query, it is likely that that is generating invalid IL.

Compiler introduce this Convert node automatically when you hand write the query. I am not sure whether it is needed or why OData is not introducing it. And what are its implication in IL. Perhaps coreFx team can provide more information on that. If current Expression Tree generated by OData is invalid (given compiler generates slightly different then) OData team can fix it. Or if the ExpressionTree is valid then it should not be generating error in IL when evaluating in memory. (perhaps corefx issue).

Since EF Core is working correctly for compiler generated Expression Tree, I will be closing this issue on EF Core side.

ikemtz commented 6 years ago

Any update on the fix for this issue from the OData side?

techniq commented 6 years ago

See also: https://github.com/OData/WebApi/issues/1154#issuecomment-416420820

There is also https://github.com/OData/WebApi/issues/1221, which is a duplicate of this issue (been open longer, but still a duplicate)

vinils commented 5 years ago

I´m struggling with data problem too since I can´t make a groupby. Would be nice to have a work-around or an ETA I tracked this bug to a year ago and since groupby(aggregate) its a kind of basic query resource wouldn't this bug be a p1 blocking? Regards,

jannikbuschke commented 5 years ago

Im also facing this issue

SenyaMur commented 5 years ago

I found solution. Just change one method in AggregationBinder class

        private Expression WrapConvert(Expression expression)
        {
            return Expression.Convert(expression, typeof(object));
            // return this._linqToObjectMode
            //     ? Expression.Convert(expression, typeof(object))
            //     : expression;
        }

Now always use convert for property

esbenbach commented 5 years ago

Any updates on this?

kenanilgun commented 5 years ago

I found solution. Just change one method in AggregationBinder class

        private Expression WrapConvert(Expression expression)
        {
            return Expression.Convert(expression, typeof(object));
            // return this._linqToObjectMode
            //     ? Expression.Convert(expression, typeof(object))
            //     : expression;
        }

Now always use convert for property

Hi SenyaMur, Can you give example to here please.

SenyaMur commented 5 years ago

I found solution. Just change one method in AggregationBinder class

        private Expression WrapConvert(Expression expression)
        {
            return Expression.Convert(expression, typeof(object));
            // return this._linqToObjectMode
            //     ? Expression.Convert(expression, typeof(object))
            //     : expression;
        }

Now always use convert for property

Hi SenyaMur, Can you give example to here please.

What example you need? Request url or fix the bug? If you want to fix the bug, then just clone the repository, change code as i writed and build it.

kosinsky commented 5 years ago

Issue should be fixed by: https://github.com/OData/WebApi/pull/1728 Could you try nightly build to check that fix works for you?

SenyaMur commented 5 years ago

It's worked on build 7.1.1-Nightly201907241245. When it will be in nuget?

SenyaMur commented 5 years ago

It's worked on 7.2.0. Thank you!

SenyaMur commented 4 years ago

Not work on 7.3.0 :(

Bilal-El-Mursi commented 4 years ago

Did you try to use services.AddControllers().AddNewtonsoftJson();? It seems to solve some of the issues.