simple-odata-client / Simple.OData.Client

MIT License
329 stars 193 forks source link

Multiple properties with the name 'propertyname' were detected in an entry or a complex value #630

Closed KoalaBear84 closed 5 years ago

KoalaBear84 commented 5 years ago

We updated to v5 lately and found a bug that we had on production. Somehow it is giving this error with v5 (v5.0.0.1+) which worked perfectly on at least v4.24.0. We tried to update to the latest 4.29.0 but it did not wanted to because it was not compatible with a Microsoft 7.6.0 package.

I do have found an issue like this, but because that issue should be fixed (we didn't really had a 'fixed' message from @phatcher so we don't know for sure) https://github.com/simple-odata-client/Simple.OData.Client/issues/475

It is about the 'username' property in our case.

This is the stripped model we are trying to insert.

public class BaseUser
{
  string _username { get; set; }

  public string username
  {
    get { return _username; }
    set { _username = value?.ToLower(); }
  }
}

public class User : BaseUser
{
  public BaseUser hr { get; set; }
  public BaseUser manager { get; set; }
}

And this is the call:

return oDataClient.For<User>().Set(user).InsertEntryAsync().Result;

This is all, we don't have the same property on the same level, or the same property.

phatcher commented 5 years ago

@KoalaBear84 My issue is fixed, at least I don't have an issue with the current implementation on my project.

What you should be able to do is a write a simple unit tests that calls ClientSettings.TypeCache.GetAllProperties and ClientSettings.TypeCache.GetMappedPropertiesWithNames on the relevant types - that should tell you enough as to whether it is mapping correctly. Once you've done that, you should be able to produce a simpler test case.

Unfortunately without this, these sorts of issues are very difficult to diagnose/fix.

Looking at the type hierarchy, it might be do to with subtype mapping, if so have a look at the code on my development branch features/575_SubTypes.

KoalaBear84 commented 5 years ago

Thanks @phatcher

I was already creating a smaller repro, because it looks like it also has to do something with the server, or the metadata it returns. When we implemented this (2 years ago or so) we already needed https://github.com/simple-odata-client/Simple.OData.Client/issues/75 because SuccessFactors returns bad/invalid metadata.

It looks like the underlying problem is something I do not understand.

Also, it looks like the underlying problem is not Simple.OData.Client, but the fact that it needs Microsoft.OData.Core packages 7.4.4+ which do more checking or so. And unfortunately I can only supply the repro without login credentials, so won't be that helpful because SuccessFactors is not that common I guess :|

For future reference I'm also including the stacktrace:

Click to expand ``` Exception: System.AggregateException: One or more errors occurred. ---> Microsoft.Data.OData.ODataException: Multiple properties with the name 'username' were detected in an entry or a complex value. In OData, duplicate property names are not allowed. at Microsoft.Data.OData.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(ODataProperty property) at Microsoft.Data.OData.Atom.ODataAtomPropertyAndValueSerializer.WriteProperty(ODataProperty property, IEdmStructuredType owningType, Boolean isTopLevel, Boolean isWritingCollection, Action beforePropertyAction, EpmValueCache epmValueCache, EpmSourcePathSegment epmParentSourcePathSegment, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, ProjectedPropertiesAnnotation projectedProperties) at Microsoft.Data.OData.Atom.ODataAtomPropertyAndValueSerializer.WriteProperties(IEdmStructuredType owningType, IEnumerable`1 cachedProperties, Boolean isWritingCollection, Action beforePropertiesAction, Action afterPropertiesAction, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, EpmValueCache epmValueCache, EpmSourcePathSegment epmSourcePathSegment, ProjectedPropertiesAnnotation projectedProperties) at Microsoft.Data.OData.Atom.ODataAtomWriter.WriteEntryContent(ODataEntry entry, IEdmEntityType entryType, EntryPropertiesValueCache propertiesValueCache, EpmSourcePathSegment rootSourcePathSegment, ProjectedPropertiesAnnotation projectedProperties) at Microsoft.Data.OData.Atom.ODataAtomWriter.EndEntry(ODataEntry entry) at Microsoft.Data.OData.ODataWriterCore.b__16() at Microsoft.Data.OData.ODataWriterCore.InterceptException(Action action) at Microsoft.Data.OData.ODataWriterCore.WriteEndImplementation() at Microsoft.Data.OData.ODataWriterCore.WriteEnd() at Simple.OData.Client.V3.Adapter.RequestWriter.d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Simple.OData.Client.RequestWriterBase.d__7.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Simple.OData.Client.RequestBuilder.d__7.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Simple.OData.Client.ODataClient.d__90.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Simple.OData.Client.BoundClient`1.d__15.MoveNext() --- End of inner exception stack trace --- at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification) at System.Threading.Tasks.Task`1.get_Result() at Simple.OData.Client.Issue630.Program.Main(String[] args) in C:\Users\bveeke\source\repos\Simple.OData.Client.Issue630\Simple.OData.Client.Issue630\Program.cs:line 38 ---> (Inner Exception #0) Microsoft.Data.OData.ODataException: Multiple properties with the name 'username' were detected in an entry or a complex value. In OData, duplicate property names are not allowed. at Microsoft.Data.OData.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(ODataProperty property) at Microsoft.Data.OData.Atom.ODataAtomPropertyAndValueSerializer.WriteProperty(ODataProperty property, IEdmStructuredType owningType, Boolean isTopLevel, Boolean isWritingCollection, Action beforePropertyAction, EpmValueCache epmValueCache, EpmSourcePathSegment epmParentSourcePathSegment, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, ProjectedPropertiesAnnotation projectedProperties) at Microsoft.Data.OData.Atom.ODataAtomPropertyAndValueSerializer.WriteProperties(IEdmStructuredType owningType, IEnumerable`1 cachedProperties, Boolean isWritingCollection, Action beforePropertiesAction, Action afterPropertiesAction, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, EpmValueCache epmValueCache, EpmSourcePathSegment epmSourcePathSegment, ProjectedPropertiesAnnotation projectedProperties) at Microsoft.Data.OData.Atom.ODataAtomWriter.WriteEntryContent(ODataEntry entry, IEdmEntityType entryType, EntryPropertiesValueCache propertiesValueCache, EpmSourcePathSegment rootSourcePathSegment, ProjectedPropertiesAnnotation projectedProperties) at Microsoft.Data.OData.Atom.ODataAtomWriter.EndEntry(ODataEntry entry) at Microsoft.Data.OData.ODataWriterCore.b__16() at Microsoft.Data.OData.ODataWriterCore.InterceptException(Action action) at Microsoft.Data.OData.ODataWriterCore.WriteEndImplementation() at Microsoft.Data.OData.ODataWriterCore.WriteEnd() at Simple.OData.Client.V3.Adapter.RequestWriter.d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Simple.OData.Client.RequestWriterBase.d__7.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Simple.OData.Client.RequestBuilder.d__7.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Simple.OData.Client.ODataClient.d__90.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Simple.OData.Client.BoundClient`1.d__15.MoveNext()<--- ```
phatcher commented 5 years ago

@KoalaBear84 The fact that it's OData V3 makes it more complicated, looks like you will have to raise a bug with SAP :scream:

KoalaBear84 commented 5 years ago

Ouch. For me it's too complicated to figure it out. Also having 1.17MB of metadata is not cool. :)

Thanks for helping. I'll close this issue here as it looks like the problem is not in here. SAP is not like the new Microsoft, and SuccesFactors is a whole other story. So I guess this is it for us. It feels like SuccesFactors is not actively maintained (in this part).

https://apps.support.sap.com/sap/support/knowledge/public/en/2613670

SuccessFactors OData API service is based on OData V2.0.