Closed tvhars closed 5 years ago
At a guess you are using the V4 Adapter rather than the V3 Adapter which supports OData v1-3.
Check which assembly you are referencing and lets see the startup code
Thanks for the quick reply - unfortunately not as simple as the wrong assemblies :-( attached file shows pict of current assemblies definitely the V3 adaptor.
Test rig code below -
Can you paste your service metadata document?
Hopefully this is the information you want - attached : C4C-metadata-xml.txt.
Also, I added the OnTrace to the code for the instantiation of the oDataClienttSettingDetails class with the following returned information if this is helpful -
DYNAMIC READ Service Ticket
GET request: https://my323585.crm.ondemand.com/sap/c4c/odata/v1/c4codataapi/$metadata
Request completed: OK
OData protocol is not supported
(caught exception text)```
Are there any options which generate a deeper level of trace information?
I wrote the following 'raw' query and it seems to return the correctly formatted oData payload (again not sure if this helps except showing that the server does return data when queried) -
var username = "xxxx"; var password = "xxxx"; var authHeader = "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes(username + ":" + password)); var cookieContainer = new CookieContainer(); // Connection End // Product File Creation // Get request for reading the list of collections HttpWebRequest request = (HttpWebRequest)(WebRequest.Create("https://myxxxxxx.crm.ondemand.com/sap/c4c/odata/v1/c4codataapi/ServiceRequestCollection"));
// Share cookies between the requests
request.CookieContainer = cookieContainer;
// Set auth header
request.Headers.Add("Authorization", authHeader);
// Set header to fetch a CSRF token to be used in modifying requests
request.Headers.Add("x-csrf-token", "fetch");
// Set accept header to get the data in JSON. Default response format is XML
//request.Accept = "application/json";
// Get the response.
HttpWebResponse response = (HttpWebResponse)(request.GetResponse());
// Get the stream containing content returned by the server.
using (Stream dataStream = response.GetResponseStream())
{
// Open the stream using a StreamReader for easy access.
using (StreamReader reader = new StreamReader(dataStream))
{
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Now Write the contents to a BLOB file
// write a blob to the container, add to Header add Footer
Console.WriteLine(responseFromServer);
// Get x-csrf-token
string x_csrf_token = response.Headers["x-csrf-token"];
// Clean up the streams and the response.
response.Close();
// Clean up the streams.
reader.Close();
}
dataStream.Close();
}
[C4C-metadata-xml.txt](https://github.com/simple-odata-client/Simple.OData.Client/files/3129509/C4C-metadata-xml.txt)
[Vendor Doco](https://help.sap.com/doc/d0f9ba822c08405da7d88174b304df84/LATEST/en-US/index.html#/topic/ServiceRequest)
Not sure that last file attachment worked - resent
Your schema is correct and is read properly. I wrote a simple test:
[Fact]
public async Task Test()
{
using (var reader = new StreamReader(@"F:\Temp\C4C-metadata.xml"))
{
var metadataDoc = await reader.ReadToEndAsync();
var settings = new ODataClientSettings { BaseUri = _serviceUri, MetadataDocument = metadataDoc };
var client = new ODataClient(settings);
var doc = await client.GetMetadataAsync();
}
}
So the error must be somewhere else, possibly in the content of your DLLs. A possible way to uncover it is to build the library from sources and debug through its code to find out what exactly happens.
Thank you for the help and suggestions. I have traced the mechanics of the request and response (against the working system instance and problematic one) - it appears that the authentication for the one not working is presenting a login page back for credentials and therefore not what is being expected - almost like the sent credential information is not being seen by the server and therefore the default solution login page is being generated as the return request.
Even with full tracing on for both requests and response I don't see what is being passed as the message header contents. I tried to trace this during the execution but the headers (Simple.OData.Client.Core/ODataRequest.cs line 62 - 80) does not have any header information populated at this point during the execution.
Is there a way to dump the request header information prior to sending (or a place in the code where this should be set prior to sending to the server for processing?) I can see the rest of the send payload and it seems to be fine - I think the header will also be fine but just want to investigate further to help resolve the issue.
many thanks.
@tvhars You are responsible for setting any authentication headers, there are a couple of approaches...
I'm generally using the first approach in .NET Framework and the second in .NET Core.
Would you be able to share or point me in the direction of some sample code for the methods mentioned above? as guide - thanks.
In trying the second approach (as the code utilises the .net core libraries). Do you inject the HttpClient object into the oDataClientSettings at object creation, and if so, pre-populate the object with the header values.
Or is the HttpClient object injected into a different oData object?
Adding the object through the oDataClientSettings appears to result in a null referenced object not the populated HttpClient created.
I am obviously missing a step/nuance of the second option??
I think I have worked something out for this item - thank you for the assistance.
Note for developers getting this error This exception usually thrown when the Simple.OData.Client tries to get the metadata of your webservice, but instead of getting the metadata, it redirects the HttpClient to a SSO login form instead. Make sure that you've set the authentication correctly.
I receive the following stack dump (below) regardless of the methods used to query the oData source (untyped, dynamic, or typed). The oData source (v2) for the query returns correct data when queried direct with a REST call programmatically or via a browser. The query also executes correctly on the testing instance of the system.
Is there any additional debug or information the simple.odata classes can return to narrow down further the source of the problem? Is this a general exception or does it have a specific meaning? As the testing against the source shows you can query correctly as an oData source and therefore the odata protocol should be supported.
Many thanks.
--- DUMP ---
Unhandled Exception: System.NotSupportedException: OData protocol is not supported at Simple.OData.Client.AdapterFactory.CreateModelAdapter(String metadataString, ITypeCache typeCache) at Simple.OData.Client.AdapterFactory.CreateAdapter(String metadataString, ITypeCache typeCache) at Simple.OData.Client.EdmMetadataCache..ctor(String key, String metadataDocument, ITypeCache typeCache) at Simple.OData.Client.Session.<>cDisplayClass26_0.<b0>d.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.EdmMetadataCache.d 5.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.Session.d26.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.Session.d 17.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.Session.d20.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.FluentCommand.d 20.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__5.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 CallSite.Target(Closure , CallSite , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at CA_SOD.CA_SOD_Prg.d 2.MoveNext() in C:\Source\repos\CRM\SampleCode\CA_EDMLibSample\CA_SOD_Prg\CA_SOD_Prg.cs:line 65
--- 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 System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at CA_SOD.CA_SOD_Prg.d__1.MoveNext() in C:\Source\repos\CRM\SampleCode\CA_EDMLibSample\CA_SOD_Prg\CA_SOD_Prg.cs:line 33
--- 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 System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at CA_SOD.CA_SOD_Prg.(String[] args)