Update event with outlook rest api fails with Method Not Allowed - c#

I have an application that uses the outlook REST API for creating events on the user's calendar. The creation of the event works perfectly, but once I tried to to exactly as this post indicates, I get 405 Method Not Allowed.
the error details are as follow:
{"error":{"code":"ErrorInvalidRequest","message":"The OData request is not supported."}}
here's a part of my code:
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, new Uri("https://outlook.office365.com/api/v1.0/me/events/"+meeting.OutlookEventId));
var auth = "Bearer " + token;
request.Headers.Add("Accept", "application/json");
request.Headers.Add("Authorization", auth);
var converters = new List<JsonConverter>();
converters.Add(new MyStringEnumConverter());
var createResponse = #"{
'Location': {
'DisplayName': 'Your office'
}
}";
request.Content = new StringContent(createResponse);
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await client.SendAsync(request);
I have the user token sotred on the "token" variable, as well as the outlook event Id on the "meeting.OutlookEventId" variable.
Any ideas?
Thank you very much!

I feel like a total fool...
I was sending a POST when this request required a PATCH
I just replaced
HttpMethod.Post
for
new HttpMethod("PATCH")

Related

WPF / C# Using variables in API POST

Following on from the following question
WPF / C# Submit button to POST API
I now want to amend the POST BODY to include Username and Password Variable.
The below is what I am using at the moment
var OktaUserName = ADAccountName;
var OktaPassword = Password;
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://trial.okta.com/api/v1/authn");
request.Content = new StringContent("{\"username\":"+OktaUserName+",\"password\":"+OktaPassword+",\"options\": {\"multiOptionalFactorEnroll\": true,\"warnBeforePasswordExpired\": true}}", Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
var responseContent = await response.Content.ReadAsStringAsync();
MessageBox.Show("Alert", json, "OK");
MessageBox.Show(responseContent, "Message");
I expect that the username and password is pulled from the stored variables and then added to OKTA as a new user, however with the above I get an error
ErrorCode E000003 Error Summary The Request Body was not well-formed
Any help will be greatly appreciated
Thank you #Fildor, your answers helped.
My modified request.Content is as follows
request.Content = new StringContent("{\"username\":\""+ADAccountNameStr+"\",\"password\":\""+PasswordStr+"\",\"options\": {\"multiOptionalFactorEnroll\": true,\"warnBeforePasswordExpired\": true}}", Encoding.UTF8, "application/json");

Restsharp Request gives "Argument 1: cannot convert from 'RestSharp.Method' to 'string?'" error

I am trying to call POST API request using restSharp 108.0.1v.
The code is as below;
var client = new RestClient("https://driver-vehicle-licensing.api.gov.uk/vehicle-enquiry/v1/vehicles");
var request = new RestRequest(Method.Post);
request.AddHeader("x-api-key", "MYAPIKEY");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n\t\"registrationNumber\":\"AA19AAA\"\n}", ParameterType.RequestBody);
RestResponse response = client.Execute(request);
The snippet Method.Post of var request = new RestRequest(Method.Post);gives the error that I mentioned.
Please help me to solve this issue ?
Looking at the documentation here the first parameter of the RestRequest constructor is the subpath to the resource you want to access. Instead you should do something like the following
var client = new RestClient("https://driver-vehicle-licensing.api.gov.uk");
var request = new RestRequest("vehicle-enquiry/v1/vehicles", Method.Post);
// ... or I believe this should work as well:
var client = new RestClient("https://driver-vehicle-licensing.api.gov.uk/vehicle-enquiry/v1");
var request = new RestRequest("vehicles", Method.Post);

System.TypeLoadException when submitting HTTP request through Httpclient

I am attempting to use the PayPal RESTful API through Xamarin Forms and am running into trouble when I try and obtain the OAuth token. Here is the code I am running, and error occurs when on Android. The authentication header I have changed here so that my client id and secret are not openly available. This is the curl command I am basing this HTTP request on also: https://developer.paypal.com/docs/integration/direct/make-your-first-call/. Thank you.
var getToken = new HttpClient(new NativeMessageHandler());
getToken.BaseAddress = new Uri("https://api.sandbox.paypal.com/v1/oauth2/token");
getToken.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
getToken.DefaultRequestHeaders.AcceptLanguage.Add(new StringWithQualityHeaderValue("en_US"));
getToken.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("**client_id**", "**secret**");
getToken.DefaultRequestHeaders.TryAddWithoutValidation("content-type", "application/x-www-form-urlencoded");
OAuthDetails clientCredentials = new OAuthDetails("client_credentials");
HttpResponseMessage tokenResponse = await getToken.PostAsJsonAsync("/v1/oauth2/token", clientCredentials);
AccessResponse accessInfo = await tokenResponse.Content.ReadAsAsync<AccessResponse>();
The way to send a post request with application/x-www-form-urlencoded is like this: instead of TryAddWithoutValidation you need to do this and then include this as the content in the request instead of client credentials like I did previously.
var tokenContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "client_credentials"
});

Update record in CRM 2015 using HttpRequestMessage

I need to update a record in CRM 2015 using web api in C#. However when processing, I got this error "Method not allowed" Status Code 405.
Here is some sample code.
HttpClient client = new HttpClient(new HttpClientHandler() { Credentials = new NetworkCredential("username", "password", "domain") });
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add(HttpRequestHeader.ContentType.ToString(), "application/json");
HttpRequestMessage retrieveReq = new HttpRequestMessage(HttpMethod.Post, serviceUrl + "SalesOrderSet(guid'" + orderId + "')");
retrieveReq.Headers.Accept.Clear();
retrieveReq.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
retrieveReq.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue("en-us"));
retrieveReq.Headers.Add(HttpRequestHeader.ContentType.ToString(), "application/json");
retrieveReq.Headers.Add("Prefer", "odata.include-annotations=\"*\"");
retrieveReq.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
retrieveReq.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate"));
retrieveReq.Headers.Host = server_name;
retrieveReq.Headers.Add(HttpRequestHeader.ContentLength.ToString(), "117");
retrieveReq.Headers.Connection.Add("Keep-Alive");
retrieveReq.Headers.Pragma.Add(new NameValueHeaderValue("no-cache"));
var postData = new List<KeyValuePair<string, string>>();
postData.Add(new KeyValuePair<string, string>("name", "value"));
HttpContent content = new FormUrlEncodedContent(postData);
retrieveReq.Content = content;
await client.SendAsync(retrieveReq).ContinueWith(
(postTask) =>
{
postTask.Result.EnsureSuccessStatusCode();
});
Any help?
Thanks in advance
Error 405 usually means you are trying to send a method different than the expected by the server (normally the HttpVerb is wrong). You are using POST so could you try with GET? HttpMessage.Get.
Edit: looks like update operations require a PATCH verb. Others will require a PUT, and deletions must use DELETE.
https://msdn.microsoft.com/en-us/library/mt607664.aspx

HttpClient authentication header not getting sent

I'm trying to use an HttpClient for a third-party service that requires basic HTTP authentication. I am using the AuthenticationHeaderValue. Here is what I've come up with so far:
HttpRequestMessage<RequestType> request =
new HttpRequestMessage<RequestType>(
new RequestType("third-party-vendor-action"),
MediaTypeHeaderValue.Parse("application/xml"));
request.Headers.Authorization = new AuthenticationHeaderValue(
"Basic", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", "username", "password"))));
var task = client.PostAsync(Uri, request.Content);
ResponseType response = task.ContinueWith(
t =>
{
return t.Result.Content.ReadAsAsync<ResponseType>();
}).Unwrap().Result;
It looks like the POST action works fine, but I don't get back the data I expect. Through some trial and error, and ultimately using Fiddler to sniff the raw traffic, I discovered the authorization header isn't being sent.
I've seen this, but I think I've got the authentication scheme specified as a part of the AuthenticationHeaderValue constructor.
Is there something I've missed?
Your code looks like it should work - I remember running into a similar problem setting the Authorization headers and solved by doing a Headers.Add() instead of setting it:
request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "username", "password"))));
UPDATE:
It looks like when you do a request.Content, not all headers are being reflected in the content object. You can see this by inspecting request.Headers vs request.Content.Headers. One thing you might want to try is to use SendAsync instead of PostAsync. For example:
HttpRequestMessage<RequestType> request =
new HttpRequestMessage<RequestType>(
new RequestType("third-party-vendor-action"),
MediaTypeHeaderValue.Parse("application/xml"));
request.Headers.Authorization =
new AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", "username", "password"))));
request.Method = HttpMethod.Post;
request.RequestUri = Uri;
var task = client.SendAsync(request);
ResponseType response = task.ContinueWith(
t =>
{ return t.Result.Content.ReadAsAsync<ResponseType>(); })
.Unwrap().Result;
This would also work and you wouldn't have to deal with the base64 string conversions:
var handler = new HttpClientHandler();
handler.Credentials = new System.Net.NetworkCredential("username", "password");
var client = new HttpClient(handler);
...
Try setting the header on the client:
DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(String.Format("{0}:{1}", userName, password))));
This works for me.
Also, consider that Redirect-Handler will clear the Authorization header if your request gets redirected.
So if you call an HTTP endpoint and it redirected to the HTTPS one, you will lose your authorization header.
request.Headers.Authorization = null;
Framework: .NET v6.0
Actually your problem is with PostAsync- you should use SendAsync. In your code - client.PostAsync(Uri, request.Content); sends only the content the request message headers are not included.
The proper way is:
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = content
};
message.Headers.Authorization = new AuthenticationHeaderValue("Basic", credentials);
httpClient.SendAsync(message);

Categories