Update a OneNote page using Graph API - c#

I am trying to update a OneNote page using the PATCH request through the Microsoft Graph API. I keep getting Error 19999 which according to this https://msdn.microsoft.com/en-us/office/office365/howto/onenote-error-codes means "Unknown Error"
var pageId = settings.DefaultPage;
string requestUrl = $"https://graph.microsoft.com/v1.0/me/onenote/pages/{pageId}/content";
string body = #"{
{
'target':'body',
'action':'append',
'position':'after',
'content':'<div> added new </div>'}}";
var content = new StringContent(body, Encoding.UTF8, "application/json");
HttpRequestMessage req = new HttpRequestMessage()
{
Method = new HttpMethod("PATCH"),
Content = content,
RequestUri = new Uri(requestUrl)
};
HttpClient client = new HttpClient()
{
BaseAddress = new Uri(requestUrl),
};
client.DefaultRequestHeaders.TryAddWithoutValidation("authorization", "Bearer " + settings.MsaAccessCode);
HttpResponseMessage response = await client.SendAsync(req);
I can verify that the Authorization Code is valid (as I am able to do other actions like creating a new page) and has the necessary scopes to update a page. Can anyone help me with identifying the problem here?

Your JSON is invalid. Here is what I believe you want.
[{
"target": "body",
"action": "append",
"position": "after",
"content": "<div> added new </div>"
}]

Related

C# Amazon SP API CreateFeedDocument not working

There are 3 steps to upload a feed via Amazon SP API, the first one is to get feed encryption info via createFeedDocument API. But I am getting Bad Request as response with following content:
{
"errors": [
{
"code": "InvalidInput",
"message": "Invalid Input",
"details": ""
}
]
}
C# code
private async Task<IRestResponse> CreateFeedDocument()
{
IRestRequest restRequest = new RestRequest("feeds/2020-09-04/documents", Method.POST);
restRequest.AddParameter("contentType", "application/xml; charset=UTF-8", ParameterType.RequestBody);
restRequest.AddQueryParameter("MarketplaceIds", "A21TJRUUN4KGV");
restClient = new RestClient(live_url_base);
restRequest = await signRequest(restRequest, restClient);
return restClient.Execute(restRequest);
}
private async Task<IRestRequest> signRequest(IRestRequest restRequest, RestClient restClient)
{
var roleAcccess = await GetAssumeRoleTokenDetail();
restRequest.AddHeader("x-amz-access-token", accessToken);
AWSAuthenticationCredentials AWSCredentials = new AWSAuthenticationCredentials();
AWSCredentials.AccessKeyId = roleAcccess.Credentials.AccessKeyId;
AWSCredentials.SecretKey = roleAcccess.Credentials.SecretAccessKey;
AWSCredentials.Region = region;
restRequest.AddHeader("X-Amz-Security-Token", roleAcccess.Credentials.SessionToken);
return new AWSSigV4Signer(AWSCredentials).Sign(restRequest, restClient.BaseUrl.Host);
}
I doubt that I am not using restRequest.AddParameter properly, but I am not sure.
I have been following below links:
https://github.com/amzn/selling-partner-api-docs/blob/main/references/feeds-api/feeds_2020-09-04.md#createfeeddocument
https://github.com/amzn/selling-partner-api-docs/blob/main/guides/en-US/use-case-guides/feeds-api-use-case-guide/feeds-api-use-case-guide-2020-09-04.md#step-1-create-a-feed-document
How to Encrypt and upload data using selling-partner-api in Amzon using .net
Update
I also tried replacing below line
restRequest.AddParameter("contentType", "application/xml; charset=UTF-8", ParameterType.RequestBody);
with
restRequest.AddJsonBody(new { contentType = "text/xml; charset=UTF-8" });
but then I was getting InvalidSignature error as below:
{
"errors": [
{
"message": "The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.
The Canonical String for this request should have been
'POST
/feeds/2020-09-04/documents
host:sellingpartnerapi-eu.amazon.com
x-amz-access-token:Atza|IwEBIA5KgrCsBbSXHmrXFS_FIgBTInh_xPAydLfi5q2P9xaFQf7p8Zl4NjqhHHxqRzUku__Q7GN1p2WQGRzuAoAa8oMkPLx57NJ05SqxEVXXG-fet3_XgKj8uBCU30HaGPsKltf4g2MD8Pqqt2OUrOXtkv4dAAjjCIxC-bFwVqOhvHktAur--NBv-bJaPZ608Av1GEu96GsNEV9eb0saVBwLaZD7NW3oOjzlCc8GPV9hdqHV5TUXY77QZgBLD1y94Vs1fSo54ShpyoMMOZebzbSr1K5gtf3wJZ.........................{ I hid it }...........................................
x-amz-date:20210524T175148Z
x-amz-security-token:FwoGZXIvYXdzEGsaDNUytY0xuP5/u61APiK2ARMZgv4IT+y2HLzdg5FjZOv6aL2bJ3baJPxBtCY2/7ASntTXfAF5s39P3/qspLLQfmqHPZiMGjweCE3Yf3aW5Q1mt+FLT2s2VUwuOawOQwDll51T2HB3wqyaDOSEpsWeR2Iym4TJXE2hbo7q5CQQBXissOo1Oruk5gcAp7uQHpnyuhCRCkfv/ErEpzdDA0JqfhMxdzmViVgsL1Kzalnbcy9lp+ACI4TL70iOl6j6xkyhFexe/aLXKLLPr4UGMi3Ver2CL6Q4kz.........................{ I hid it }...........................................
host;x-amz-access-token;x-amz-date;x-amz-security-token
4d719849acd655844ab5129f5e54a0ed16954c9580c7a9a737504faf42b309e2'
The String-to-Sign should have been
'AWS4-HMAC-SHA256
20210524T175148Z
20210524/eu-west-1/execute-api/aws4_request
a20e7ffe252dbf98d6a4b9213511ac1918f8bbad75ccbfd7ec46f5c9c1457b08'
",
"code": "InvalidSignature"
}
]
}
Note: I have removed some trailing chars of tokens and placed ......{ I hid it }..........
try this one
restRequest.AddJsonBody("{\"contentType\":\"text/tab-separated-values; charset=UTF-8\"}");
RestClient restClient = new RestClient("https://sandbox.sellingpartnerapi-eu.amazon.com/");
IRestRequest restRequest = new RestRequest("/feeds/2021-06-30/documents", Method.POST);
restRequest.AddJsonBody("{\"contentType\":\"text/tab-separated-values; charset=UTF-8\"}");
I do that in my open source library and its work without problem
https://github.com/abuzuhri/Amazon-SP-API-CSharp
Here sample to create and submit feed
ConstructFeedService createDocument = new ConstructFeedService("A3J37AJU4O9RHK", "1.02");
var list = new List<PriceMessage>();
list.Add(new PriceMessage()
{
SKU = "8201031206122...",
StandardPrice = new StandardPrice()
{
currency = BaseCurrencyCode.AED.ToString(),
Value = (201.0522M).ToString("0.00")
}
});
createDocument.AddPriceMessage(list);
var xml = createDocument.GetXML();
var feedID = amazonConnection.Feed.SubmitFeed(xml, FeedType.POST_PRODUCT_PRICING_DATA);
Thread.Sleep(1000*30);
var feedOutput=amazonConnection.Feed.GetFeed(feedID);
var outPut=amazonConnection.Feed.GetFeedDocument(feedOutput.ResultFeedDocumentId);
var reportOutpit = outPut.Url;
private async Task UploadFile(byte[] bytes, string url)
{
var contentType = "text/plain; charset=utf-8"; // this should be the same as what was used in Step #1 (in the CreateFeedDocument API request)
RestClient restClient = new RestClient(url);
IRestRequest restRequest = new RestRequest(Method.PUT);
restRequest.AddParameter(contentType, bytes, ParameterType.RequestBody);
var response = await restClient.ExecuteAsync(restRequest);
if (!response.IsSuccessful)
{
// your error logic
}
// success. Move to Step #3
}
IllegalLocationConstraintExceptionThe unspecified location constraint is incompatible for the region specific endpoint this request was sent to.5B8EGG143CSG45XCi7DqESeN8Q/1QfotMvQIiijcEj/76sr2T+gNh9Ubhq5aQZ7SbZMXCIS/8Mgw6iDod2mCwX/LX6Q=

Issue setting request content for HttpRequestMessage in Dotnet?

I'm new to dotnet/C#, and I'm having a really hard time setting my request body when trying to make an HttpClient request. I've attempted the following:
string url = "https://sample-url.io";
var request = new HttpRequestMessage()
{
RequestUri = new Uri(url),
Method = HttpMethod.Post
};
request.Content = new StringContent("Test", Encoding.UTF8, "application/json");
However, when I print out the request, this is what I see:
{
"Content":{
"Headers":[
{
"Key":"Content-Type",
"Value":[
"application/json; charset=utf-8"
]
}
]
},
"Method":{
"Method":"POST"
},
"RequestUri":"https://sample-url.io",
"Headers":[
],
"Properties":{
}
}
I can't , for the life of me, figure out why Content does not contain the body I set ("Test"), and why it does contain the other parameters under that strange secondary "Header". I also tried defining Content on creation of the request variable, to no avail:
var request = new HttpRequestMessage()
{
RequestUri = new Uri(url),
Method = HttpMethod.Post,
Content = new StringContent("Test", Encoding.UTF8, "application/json")
};
Does anyone see what I'm doing wrong here? Any help is much appreciated!
It is not clear how are you outputting the content. You won't see it if you just serialize it. But if you try it like this, I believe you will get the value:
Console.WriteLine(await request.Content.ReadAsStringAsync());
On the side, yes, you specified the mediatype to application/json (3rd parameter on the constructor) but the content is just a plain text - there's at least some level of inconsistency.
Another way to see it is by fiddler:

Get Response Header data from Post Call

I'm calling a Microsoft API to create a printer however I need a way to get the response header where the information about the post is.
I'm following this guide https://learn.microsoft.com/en-us/graph/api/printer-create?view=graph-rest-beta&tabs=csharp but not sure how to extract the response from the call as I can not assign a variable to the call.
await graphClient.Print.Printers
.Create(displayName,manufacturer,model,certificateSigningRequest,physicalDeviceId,hasPhysicalDevice,connectorId)
.Request()
.PostAsync();
Operation-Location
You can send HTTP request with the .Net Microsoft Graph client library and read response headers.
Something like this:
var requestUrl = graphClient.Print.Printers.Request().RequestUrl;
var content = "json_content";
var hrm = new HttpRequestMessage(HttpMethod.Post, requestUrl);
hrm.Content = new StringContent(content, System.Text.Encoding.UTF8, "aplication/json");
// Authenticate (add access token)
await client.AuthenticationProvider.AuthenticateRequestAsync(hrm);
// Send the request and get the response.
var response = await client.HttpProvider.SendAsync(hrm);
if (!response.IsSuccessStatusCode)
{
throw new ServiceException(
new Error
{
Code = response.StatusCode.ToString(),
Message = await response.Content.ReadAsStringAsync()
});
}
else
{
// read header values
var headerValues = response.Headers.GetValues("Operation-Location");
}
Example of the request body:
{
"displayName": "Test Printer",
"manufacturer": "Test Printer Manufacturer",
"model": "Test Printer Model",
"physicalDeviceId": null,
"hasPhysicalDevice": false,
"certificateSigningRequest": {
"content": "{content}",
"transportKey": "{sampleTransportKey}"
},
"connectorId": null
}
Documentation

Unsupported media type in httpclient call c#

I'm a trying to post the following request but I am getting a "Unsupported Media Type" response. I am setting the Content-Type to application/json. Any help would be appreciated. And as per comment below, if i change content as 'new StringContent(JsonConvert.SerializeObject(root), Encoding.UTF8, "application/json")' then i get bad request response
string URL = "https://test.com/api/v2/orders/"; //please note it is dummy api endpoint
var client = new HttpClient();
var httpRequestMessage = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri(URL),
Headers = {
{ HttpRequestHeader.Authorization.ToString(), "Bearer ABcdwenlfbl8HY0aGO9Z2NacFj1234" }, //please note it is dummy bearer token
{ HttpRequestHeader.Accept.ToString(), "application/json;indent=2" },
{ HttpRequestHeader.ContentType.ToString(), "application/json" }
},
//Content =new StringContent(JsonConvert.SerializeObject(root), Encoding.UTF8, "application/json")
Content = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(root))
};
var response = client.SendAsync(httpRequestMessage).Result;
With HttpClient, some headers are counted as request headers, and others are counted as content headers. I'm not sure why they made this distinction really, but the bottom line is that you have to add headers in the correct place.
In the case of Content-Type, this can be added as part of the StringContent constructor, or to the constructed StringContent object.
My approach is to use the constructor:
Content = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(root), System.Text.Encoding.UTF8, "application/json");
Or alternatively set it afterwards:
Content = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(root))
Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
Note: If your issue still presents after making this change, then it's likely a server-side problem and you'll need to contact the maintainer of the API to ask what you're doing wrong.
I prefer using some third party wrappers like FluentClient
Note that you should not instance a new object for every request, O only did it for the sake of an example.
var client = new FluentClient("https://test.com/api/v2/orders/")
.PostAsync(URI)
.WithBody(root)
.WithBearerAuthentication("ABcdwenlfbl8HY0aGO9Z2NacFj1234");
var response = await client.AsResponse();

How to pull a LFS file from gitlab repo using api

I am trying to use the gitlab api to get a file from my repo without success. Can you give me some pointers? When I run my below C# code, I get this response
{
“message”: “Access forbidden. Check your access level.”,
“documentation_url”: “https://gitlab.com/help”
}
I am positive that I am passing my correct credentials.
C# code follows:
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/vnd.git-lfs+json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", <my_username>, <my_password>))));
string json = #"{
'operation': 'download',
'transfers': [ 'basic' ],
'ref': { 'name': 'refs/heads/master' },
'objects': [
{
'oid': '9669a62bbe8d8150c11d814509078b5db8f73c97ecfc94beb1dc6b22130adf7b',
'size': 4465559,
'authenticated': true
}
]
}";
var response = client.PostAsync("https://gitlab.com/<my_repo>/info/lfs/objects/batch", new StringContent(JsonConvert.SerializeObject(json), Encoding.UTF8, "application/json"));

Categories

Resources