msgraph-sdk-dotnet icon indicating copy to clipboard operation
msgraph-sdk-dotnet copied to clipboard

Updating Data on a OneNote Page Error, “Timeouts are not supported on this stream”

Open JMoss86 opened this issue 3 years ago • 1 comments

I have the goal of being able to programmatically update OneNote page data using C#. The Microsoft Graph API reference documentation suggests this can only be done by page element, not by page, and gives the following C# Graph SDK example:

GraphServiceClient graphClient = new GraphServiceClient( authProvider );

var stream = new System.IO.MemoryStream(Encoding.UTF8.GetBytes(@"[
   {
    'target':'#para-id',
    'action':'insert',
    'position':'before',
    'content':'<img src=""image-url-or-part-name"" alt=""image-alt-text"" />'
  }, 
  {
    'target':'#list-id',
    'action':'append',
    'content':'<li>new-page-content</li>'
  }
]
"));

var pages = new OnenotePage();
pages.Content = stream;

await graphClient.Me.Onenote.Pages["{onenotePage-id}"]
    .Request()
    .UpdateAsync(pages);

Below is the relevant snippet of my code:

GraphServiceClient client; // authenticated service client
CancellationToken cancellationToken; // a cancellation token
string userId; // identifier of user whose page contains the paragraph to be updated
string pageId; // identifier of page containing paragraph to be updated
string paragraphId; // identifier of paragraph to be updated
string filePath; // location of text file containing updated paragraph data

await client.Users[userId].Onenote.Pages[pageId]
    .Request()
    .UpdateAsync(new OnenotePage
    {
        Content = new MemoryStream(Encoding.UTF8.GetBytes(
            // [
            //    {
            //       'target':'{paragraphId}',
            //       'action':'replace',
            //       'content':'<p>{File.ReadAllText(filePath)}</p>'
            //    }
            // ] 
            $"[{{'target':'{paragraphId}','action':'replace','content':'<p>{File.ReadAllText(filePath)}</p>'}}]"))
    }, cancellationToken);

Microsoft's REST documentation includes PATCH /users/{id | userPrincipalName}/onenote/pages/{id}/content as a valid HTTP request, so my above code seems like it should work, even though it doesn't use the .Me option as in their example. For some reason, however, my code keeps throwing an InvalidOperationException, declaring that, "Timeouts are not supported on this stream," whenever it tries to execute the await command. Below are the details of the exception:

System.InvalidOperationException
    HResult=0x80131509
    Message=Timeouts are not supported on this stream.
    Source=System.Private.CoreLib
    StackTrace:
     at System.IO.Stream.get_ReadTimeout()

When I try to run the raw REST command on the official Graph Explorer, I get a No Content - 204 message, confirming that the PATCH worked. Please note again, however, that I am instead simply using the C# MS Graph SDK.

I have also posted about this over on Stack Overflow.

Where am I going wrong? How can I accomplish my goal?

EDIT: I still don't have a solution to the SDK throwing InvalidOperationExceptions at me, and thus do not consider this matter resolved, but since the API seems to be working just fine, I went ahead and found a workaround to accomplish my goal. Posted here, in case anyone else encounters my same issue and needs something that works.

GraphServiceClient client; // authenticated service client
CancellationToken cancellationToken; // a cancellation token
string userId; // identifier of user whose page contains the paragraph to be updated
string pageId; // identifier of page containing paragraph to be updated
string paragraphId; // identifier of paragraph to be updated
string filePath; // location of text file containing updated paragraph data

HttpRequestMessage request = new HttpRequestMessage(
    HttpMethod.Patch,
    client.Users[userId].Onenote.Pages[pageId].Content
        .Request()
        .RequestUrl)
{
    Content = new StringContent(
        // [
        //    {
        //       'target':'{paragraphId}',
        //       'action':'replace',
        //       'content':'<p>{File.ReadAllText(filePath)}</p>'
        //    }
        // ]
        $"[{{'target':'{paragraphId}','action':'replace','content':'<p>{File.ReadAllText(filePath)}</p>'}}]",
        Encoding.UTF8,
        "application/json")
};

await client.AuthenticationProvider.AuthenticateRequestAsync(request);
await client.HttpProvider.SendAsync(request);

AB#9776

JMoss86 avatar May 20 '21 21:05 JMoss86

This is a non standard api for the generator. We need to add an extension method to expose the Patch functionality for the content property on OneNote Page. We will also need to update the snippet generator to fix the example presented in the documentation.

andrueastman avatar Jul 07 '21 18:07 andrueastman

Closing issue as it is stale and code is now on a newer version. If this occurs on version 5 or greater please reopen.

ddyett avatar Jun 28 '23 01:06 ddyett