OData / ODataConnectedService

A Visual Studio extension for generating client code for OData Services
Other
80 stars 42 forks source link

The response payload is a not a valid response payload!! #223

Open karim-devdotnet opened 3 years ago

karim-devdotnet commented 3 years ago

Describe the bug

When i try to call a SAP OData service i get the following error: The response payload is a not a valid response payload. Please make sure that the top level element is a valid Atom or JSON element or belongs to 'http://docs.oasis-open.org/odata/ns/data' namespace.

Version of the Project affected

ODataConnectedService v0.12.1 VisualStudio Version v16.9.2 Microsoft.Odata.Client v7.9.0 Microsoft.Odata.Core v7.9.0 Microsoft.Odata.Edm v7.9.0

Erro description and stacktrace

The response payload is a not a valid response payload. Please make sure that the top level element is a valid Atom or JSON element or belongs to 'http://docs.oasis-open.org/odata/ns/data' namespace.

Stacktrace

at Microsoft.OData.Client.Materialization.ODataMaterializer.CreateODataMessageReader(IODataResponseMessage responseMessage, ResponseInfo responseInfo, ODataPayloadKind& payloadKind) at Microsoft.OData.Client.Materialization.ODataMaterializer.CreateMaterializerForMessage(IODataResponseMessage responseMessage, ResponseInfo responseInfo, Type materializerType, QueryComponents queryComponents, ProjectionPlan plan, ODataPayloadKind payloadKind) at Microsoft.OData.Client.MaterializeAtom..ctor(ResponseInfo responseInfo, QueryComponents queryComponents, ProjectionPlan plan, IODataResponseMessage responseMessage, ODataPayloadKind payloadKind) at Microsoft.OData.Client.DataServiceRequest.Materialize(ResponseInfo responseInfo, QueryComponents queryComponents, ProjectionPlan plan, String contentType, IODataResponseMessage message, ODataPayloadKind expectedPayloadKind) at Microsoft.OData.Client.QueryResult.CreateMaterializer(ProjectionPlan plan, ODataPayloadKind payloadKind) at Microsoft.OData.Client.QueryResult.ProcessResult[TElement](ProjectionPlan plan) at Microsoft.OData.Client.DataServiceRequest.EndExecute[TElement](Object source, DataServiceContext context, String method, IAsyncResult asyncResult) at Microsoft.OData.Client.DataServiceQuery1.EndExecute(IAsyncResult asyncResult) at System.Threading.Tasks.TaskFactory1.FromAsyncCoreLogic(IAsyncResult iar, Func2 endFunction, Action1 endAction, Task1 promise, Boolean requiresSynchronization) --- End of stack trace from previous location --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at OdataService.BruSAP.Konsole.V2.Program.<Main>d__0.MoveNext() in C:\Users\abdallah\source\repos\GitHub\ConsumingOdataServiceInCsharp\src\OdataServiceClient\OdataService.BruSAP.Konsole.V2\Program.cs:line 21

Code

` static async Task Main(string[] args) { string odataServiceUrl = "https://sap-d...."; var context = new Container(new Uri(odataServiceUrl)); context.SendingRequest2 += (sender, e) => SendBaseAuthCredsOnTheRequest(sender,e);

        //get all TWA_Auftrags
        IEnumerable<TWA_AuftragType> twa_AuftragList = await context.TWA_Auftrag.ExecuteAsync();
        Console.WriteLine("Twa_AuftragList");
        foreach (var item in twa_AuftragList)
        {
            Console.WriteLine($"Twa_Auftrag[{item.Id}]: {item.WwaStrasseUndHausnummer}");
        }

        Console.ReadLine();
    }

`

Screenshot

image TWA_Metadata.zip

adrianaxente commented 3 years ago

Hello, I have the same error when invoking an Action that has empty response body.

habbes commented 3 years ago

@karimabd84 thanks for reporting this. It's not immediately clear what the issue is without being able to look at the actual response. Could you share the actual response payload that the service is returning?

Could you try to make the request directly on Postman and see whether you're getting the same response? Is it a valid OData response.

I see that you have a hook SendBaseAuthCredsOnTheRequest. Does that method make a separate request to the service, or does it only add auth headers to the request being sent? Could you also shed more light into what that method is doing?

I will take a look at the metadata file you shared to see if I can spot anything noteworthy.

habbes commented 3 years ago

@adrianaxente could you also share a sample of the request and the full response that you're getting, including the response headers.

chris472 commented 3 years ago

Hello @habbes I'm a co-worker of @karimabd84. The method only adds an auth header to the request being send:

private static void SendBaseAuthCredsOnTheRequest(object sender, SendingRequest2EventArgs e)
{
      e.RequestMessage.SetHeader("Authorization", "**********");
}

The response from a manual query is {"@odata.context":"$metadata#TWA_Auftrag","@odata.metadataEtag":"W/\"20210602095314\"","value":[{"id":"6000000000","wwaId":"Warmwasser ID","wwaStrasseUndHausnummer":"Walldorfer Straße 36a","wwaPlz":"69190","wwaOrt":"Walldorf","untersuchungspflicht":1,"bemerkungTourenplanung":"","gebaeudeNutzung":"","objektnummer":"","beprobenBis":"--","status":2,"nutzungsarten":"","auftragsart":3,"stufeNachuntersuchung":3},{"id":"6000000001","wwaId":"Warmwasser ID","wwaStrasseUndHausnummer":"Walldorfer Straße 36a","wwaPlz":"69190","wwaOrt":"Walldorf","untersuchungspflicht":1,"bemerkungTourenplanung":"","gebaeudeNutzung":"","objektnummer":"","beprobenBis":"--","status":2,"nutzungsarten":"","auftragsart":3,"stufeNachuntersuchung":3},{"id":"6000000002","wwaId":"Warmwasser ID","wwaStrasseUndHausnummer":"Walldorfer Straße 36a","wwaPlz":"69190","wwaOrt":"Walldorf","untersuchungspflicht":1,"bemerkungTourenplanung":"","gebaeudeNutzung":"","objektnummer":"","beprobenBis":"--","status":2,"nutzungsarten":"","auftragsart":3,"stufeNachuntersuchung":3},{"id":"6000000020","wwaId":"Warmwasser ID","wwaStrasseUndHausnummer":"Walldorfer Straße 36a","wwaPlz":"69190","wwaOrt":"Walldorf","untersuchungspflicht":1,"bemerkungTourenplanung":"","gebaeudeNutzung":"","objektnummer":"","beprobenBis":"--","status":2,"nutzungsarten":"","auftragsart":3,"stufeNachuntersuchung":3},{"id":"6000000021","wwaId":"Warmwasser ID","wwaStrasseUndHausnummer":"Walldorfer Straße 36a","wwaPlz":"69190","wwaOrt":"Walldorf","untersuchungspflicht":1,"bemerkungTourenplanung":"","gebaeudeNutzung":"","objektnummer":"","beprobenBis":"--","status":2,"nutzungsarten":"","auftragsart":3,"stufeNachuntersuchung":3}]}

Could the problem be that we are using OData Version 2?

habbes commented 3 years ago

@chris472 if you're using OData version 2, that could be part of your problem. I've looked at your metadata file and it states that the service uses v4:

<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" xmlns="http://docs.oasis-open.org/odata/ns/edm" Version="4.0">

This causes the OData Connected Service to generate client code target v4, and it's possible that it may not be fully compatible with the payload the service is sending.

Maybe you could try modifying the metadata to target v2 so that OData Connected Service can generate client code that supports v2 and see if that helps.

I have tried modifying the versions and namespace in the metadata file and tried to regenerate the client, but I keep getting some errors. The xml fails validation. It's probably using some constructs not supported in earlier versions. Do you have access to a version of the metadata that's meant for V2?

chris472 commented 3 years ago

@habbes I'm sorry, I got a wrong information. The service is using Version 4. Therefore the version should not cause the issue.

chris472 commented 3 years ago

@habbes I found the reason: In ODataJsonLightContextUriParser (line 84 on master) is an absolute URI containing the metadata path expected. In the sample service from odata.org it is http://services.odata.org/V4/(S(ffivnsbcnxlmch00wfggmuzc))/TripPinServiceRW/$metadata#People but for our service it's just $metadata#TWA_Auftrag (from field "@odata.context"). There is even a comment // TODO: Support relative context uri and resolving other relative uris. I think this TODO would fix our problem. Do you know whether somebody is working on this?

KenitoInc commented 3 years ago

@habbes I found the reason: In ODataJsonLightContextUriParser (line 84 on master) is an absolute URI containing the metadata path expected. In the sample service from odata.org it is http://services.odata.org/V4/(S(ffivnsbcnxlmch00wfggmuzc))/TripPinServiceRW/$metadata#People but for our service it's just $metadata#TWA_Auftrag (from field "@odata.context"). There is even a comment // TODO: Support relative context uri and resolving other relative uris. I think this TODO would fix our problem. Do you know whether somebody is working on this?

Hey @chris472 Kindly create an issue in this repo so that we can triage it https://github.com/OData/odata.net

chris472 commented 3 years ago

Thanks, I added #2132