simple-odata-client / Simple.OData.Client

MIT License
329 stars 196 forks source link

Calling Unbound Action with Complex type... #507

Open NetTecture opened 6 years ago

NetTecture commented 6 years ago

I define a funciton with the following metadata:

and

AddressGeoCoded is derived from Adddress and has the following metadata:

The following calling code:

        var c = new ODataClient(TestSetup.ClientSettings);
        var s = await c
            .Unbound<AddressGeoCoded>()
            .Action("GeoCode")

            .Set(new
            {
                Address =  new AddressGeoCoded()
                {
                    Street = "Westendstrasse",
                    No = "199",
                    City = "Munich",
                    Location = new Location() { Latitude = 0, Longitude = 0 },
                }
            })
            .ExecuteAsSingleAsync();

Explodes:

Test Name: GeoCoded Test FullName: Tests.Api.Odata.Web.Controllers.ToolsTests.GeoCoded Test Source: C:\Work\OBB\Source.Backend\Tests.Api.Odata.Web\Controllers\ToolsTests.cs : line 21 Test Outcome: Failed Test Duration: 0:00:05.4606566

Result StackTrace:
at Microsoft.OData.ODataParameterWriterCore.VerifyCanWriteValueParameter(Boolean synchronousCall, String parameterName, Object parameterValue) at Microsoft.OData.ODataParameterWriterCore.WriteValueAsync(String parameterName, Object parameterValue) at Simple.OData.Client.V4.Adapter.RequestWriter.WriteOperationParameterAsync(ODataParameterWriter parameterWriter, IEdmOperationParameter operationParameter, String paramName, Object paramValue) at Simple.OData.Client.V4.Adapter.RequestWriter.WriteActionContentAsync(String method, String commandText, String actionName, String boundTypeName, IDictionary2 parameters) at Simple.OData.Client.RequestWriterBase.CreateActionRequestAsync(String commandText, String actionName, String boundTypeName, IDictionary2 parameters, Boolean resultRequired) at Simple.OData.Client.ODataClient.ExecuteActionAsync(FluentCommand command, CancellationToken cancellationToken) at Simple.OData.Client.ODataClient.ExecuteAsEnumerableAsync(FluentCommand command, CancellationToken cancellationToken) at Simple.OData.Client.ODataClient.ExecuteAsSingleAsync(FluentCommand command, CancellationToken cancellationToken) at Simple.OData.Client.FluentClientBase2.FilterAndTypeColumnsAsync(Task1 entry, IList`1 selectedColumns, String dynamicPropertiesContainerName) at Tests.Api.Odata.Web.Controllers.ToolsTests.GeoCoded() in C:\Work\OBB\Source.Backend\Tests.Api.Odata.Web\Controllers\ToolsTests.cs:line 24 Result Message: Test method Tests.Api.Odata.Web.Controllers.ToolsTests.GeoCoded threw exception: Microsoft.OData.ODataException: The parameter 'Address' is of Edm type kind 'Complex'. You cannot call WriteValue on a parameter that is not of Edm type kinds 'Primitive', 'Enum' or 'Complex'.

Well, it IS of type complex ;) Looks like a bug.

phatcher commented 6 years ago

@NetTecture Have a look at the OData lib issues list, ISTR something there about this

NetTecture commented 6 years ago

Damn, Anything that is done on the OData side has a tendency not to be resolved for years.

phatcher commented 6 years ago

Their velocity has increased a bit recently, and we are up to date with the latest library so I'd at least suggest raising the question there as to whether the OData library supports it - that either eliminates or establishes the blocker :-)

NetTecture commented 5 years ago

Tried. Multiple times. Does not look like, still there, even in more complex scenarios and I seem to be totally unable to work around that.

1304 und #1305 on their site https://github.com/OData/odata.net opened (2 because I managed 2 approaches with separate error messages and stack traces trying to bypass this).

phatcher commented 5 years ago

@NetTecture Only trick I can thing of for now if you control the API is to json serialize the complex property and pass it as a string.

You can then deserialize on the other end appropriately - not great and needs lots of docs but potentially stops it being a blocker.

NetTecture commented 5 years ago

@phatcher What I do so far is not use Odata. This is SO FAR a very limited use case, so we have "ActionName" (which is not use) and "ActionNameJson" which is similar but a traditional REST and we serialize the whole object. Works so far - one action, no external users. One would hope the OData team is not snoring nicely while baseline bugs like that go on existing, but it seems they do - and so Simple.Odata.Client can not really do anything. But that really goes back to criticism on the Odata team, which releases updates and bug fixes it seems every February 29th if it is snowing in Barcelona and Raining in Tucson or something like that. Last release 2 months ago... The Jwon workaround works good enough for now, but I can see that reaching end of the line in a couple of months.

phatcher commented 5 years ago

@NetTecture Just having to do something similar since my entities have a property bag but open types are really supported (breaks with expand, etc, etc)

So I'm trying to introduce a SetProperty action on some of my controllers, but I can't pass "object" as the value so I'm passing it as string along with a type parameter so I can convert it back!

If you think the OData team are bad try getting any updates out of the Azure B2C team

mike9182 commented 5 years ago

This may have been fixed as part of #634. As part of those changes, I fixed a similar issue with complex types containing navigation properties not being handled correctly.