Resolve Incident in D365 Online via OData - c#

I have created a controller for one of our customers to use. It should run on POST and receive a JSON body with two parameters: id and statuscode.
The logic is simple - I wish to fetch the incident with guid equals id and change its statuscode based on the received value for statuscode.
Code of controller:
public async Task<MyCustomResponse> CloseIncident([FromBody] MyCustomRequest _request)
{
try
{
// Some logic here to check if both Id and StatusCode exist in _request ...
if(Guid.TryParse(_request.Id, out Guid guid))
{
// Construct OData request
JObject incidentResolution = new JObject();
incidentResolution.Add("subject", "testing");
incidentResolution.Add("incidentid#odata.bind", $"/incidents({guid})");
incidentResolution.Add("timespent", 2); //This is billable time in minutes
incidentResolution.Add("description", "description");
JObject parameters = new JObject();
parameters.Add("IncidentResolution", incidentResolution);
if (_request.StatusCode == 1)
{
parameters.Add("Status", (int)IncidentStatusCode.ProblemSolved);
}
else
{
parameters.Add("Status", (int)IncidentStatusCode.SomeOtherRejectedStatusCode);
}
RegenerateAccess(); // Connect to Microsoft Online
string urlAPI = "/api/data/v9.1/CloseIncident";
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(_serviceUrl);
client.Timeout = new TimeSpan(0, 2, 0); //2 minutes
client.DefaultRequestHeaders.Add("OData-MaxVersion", "4.0");
client.DefaultRequestHeaders.Add("OData-Version", "4.0");
//client.DefaultRequestHeaders.Add("Prefer", "return=representation");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpMethod method = HttpMethod.Post;
HttpRequestMessage request = new HttpRequestMessage(method, urlAPI);
request.Content = new StringContent(parameters.ToString(), Encoding.UTF8, "application/json");
// Set the access token
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _authResult.AccessToken);
HttpResponseMessage response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
return new MyCustomResponse()
{
Status = Status.Success,
Message = "..."
};
}
return new MyCustomResponse()
{
Status = Status.Error,
Message = "..."
};
}
else throw new Exception("Guid is invalid.");
}
catch(Exception ex)
{
return new MyCustomResponse() { Status = Status.Error, Message = ex.Message };
}
}
I'm getting a "Bad Request" from the client.SendAsync line. I think the OData body request is incorrect, but I can't figure out why.

Code looks perfect. I’ll try to add the below header and see the response.
client.DefaultRequestHeaders.Add("Content-Type", "application/json; charset=utf-8");
While trying to debug, if you see any useful error response in exception that will help troubleshooting.

Related

Why always get Bad Request in my C# console application Dynamics 365 Business Central Webservice

https://api.businesscentral.dynamics.com/v2.0/{tenantId}/{CompanyName}/ODataV4/Company('SimpleCompany')/TransferOrder
Service Name : "TransferOrder"
Object Name : Transfer Order
try
{
var url = $"https://api.businesscentral.dynamics.com/v2.0/{tenantId}/{companyName}/ODataV4/Company('{simplecompany}')/TransferOrder";
var client = new HttpClient();
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
TransferOrderHeader hdr = new TransferOrderHeader();
hdr.No = "T-002";
hdr.Transfer_from_Code = "WH1";
hdr.Transfer_to_Code = "Van1";
hdr.Direct_Transfer = true;
hdr.In_Transit_Code = "";
hdr.Posting_Date = "2022-05-23";
hdr.Shipment_Date = "2022-05-24";
string json = JsonConvert.SerializeObject(hdr);
StringContent httpContent = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, httpContent);
var content = await response.Content.ReadAsStringAsync();
var jObj = JObject.Parse(content);
if (response.StatusCode.ToString() == "Created")
{
}
}
catch (Exception ex)
{
throw new ArgumentException(ex.Message);
}
**Why Always Come Bad Request Error, Postman also badrequest if I add Transfer_from_Code, Transfer_to_Code Fields Value and Direct_Transfer : true, but if I add Transfer_from_Code : "" Transfer_to_Code : "", Direct_Transfer : false then postman and my program both working fine with success response. **
{"error":{"code":"Unknown","message":"Property \"Editable\" for Transfer-from Code is invalid. Expression: [( Status = 0 ) AND p5740p5740EnableTransferFields] CorrelationId: xxx76d22-ff59-4251-aa7d-xxfe21fc0cbx."}}

C# HttpClient.SendAsync causes error, cannot send a content-body with this verb-type

I am getting error cannot send a content-body with this verb-type. I am calling a GET Endpoint from a C# VSTO desktop application. What am I doing wrong.
public static string GetCentralPath(LicenseMachineValidateRequestDTO licenseMachine)
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Properties.Settings.Default.Properties["JWT"].DefaultValue.ToString());
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri($"{Constants.URL.APIBase}licensemachine/GetCentralPath"),
Content = new StringContent(JsonConvert.SerializeObject(licenseMachine), Encoding.UTF8, "application/json"),
};
using (HttpResponseMessage response = client.SendAsync(request).GetAwaiter().GetResult()) // Causing ERROR
{
var result = GetStringResultFromHttpResponseMessage(response, true);
if (string.IsNullOrEmpty(result))
return null;
return JsonConvert.DeserializeObject<string>(result);
}
}
}
The end point looks like the following:
[HttpGet("GetCentralPath")]
public async Task<IActionResult> GetCentralPath(LicenseMachineValidateRequestDTO dto)
{
// Some code
}
fix the action, you cannot send body data with get, see this post
HTTP GET with request body
[HttpPost("GetCentralPath")]
public async Task<IActionResult> GetCentralPath(LicenseMachineValidateRequestDTO dto)
and fix request , replace Method = HttpMethod.Get with Post, this is what generates an error
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri($"{Constants.URL.APIBase}licensemachine/GetCentralPath"),
Content = new StringContent(JsonConvert.SerializeObject(licenseMachine), Encoding.UTF8, "application/json"),
};

MS Graph API returns 400 Bad request

I am using HttpClient to call Microsoft Graph and create a new Team. I am using the Beta version.
string TeamsName = objTeam.TeamsName.ToString();
string TeamsDescription = objTeam.TeamsDescription.ToString();
var objJson = new CreateTeamsJson
{
templateodatabind = "https://graph.microsoft.com/beta/teamsTemplates(\'educationClass\')",
displayName = TeamsName,
description = TeamsDescription
};
var json = JsonConvert.SerializeObject(objJson, jsonSettings);
var modifiedjson = json.Replace("templateodatabind", "template#odata.bind");
StringContent postContent = new StringContent(modifiedjson, UnicodeEncoding.UTF8, "application/json");
if (!string.IsNullOrEmpty(TeamsName))
{
TokenHelper tokenHelper = new TokenHelper();
TokenResponse tokenResponse = tokenHelper.GetTokenAsync().Result;
using(HttpClient httpClient = new HttpClient())
{
var request = new HttpRequestMessage(HttpMethod.Post, "https://graph.microsoft.com/beta/teams");
request.Headers.Authorization = new AuthenticationHeaderValue("bearer", tokenResponse.access_token);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Content = postContent;
var response = httpClient.SendAsync(request).Result;
var createdTeamDetails = response.Headers.Location;
if (response.IsSuccessStatusCode)
{
responseMessage = string.Format("Successfully created team - details: '{0}'", createdTeamDetails);
}
else
{
responseMessage = "ERROR: Failed to create Team.";
}
}
}
else
{
log.Info("Please provide Teams Name");
responseMessage = "Please provide Teams Name";
IsError = true;
}
When I run the code I am getting a 400 - Bad Rrequest at the following line:
var response = httpClient.SendAsync(request).Result;
I tried the same endpoint and same JSON body request in Graph Explorer and I could create teams successfully. Can anybody help me?

Bad Request error setting header in Ebay API

I would like to ask help how can I fix the issue in the header of my httpclient request.
This is ebay restful api in creating a fulfillment shipment. I am able to create in Postman but when I tried it in VS, it won't work with error bad request. Screenshot below using postman.
Codes below in ASP.NET
private HttpClient CreateHttpClient()
{
var client = new HttpClient();
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
string baseAddress = WebApiBaseAddress;
client.Timeout = new TimeSpan(0, 5, 59);
client.BaseAddress = new Uri(baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("Authorization", string.Format("Bearer {0}", _cred.eBayToken));
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
return client;
}
public HttpResponseMessage PostHttpResponse(string requestUri, object data)
{
var stringPayload = JsonConvert.SerializeObject(data);
var httpContent = new StringContent(stringPayload, Encoding.UTF8, "application/json");
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
httpContent.Headers.Add("Content-Language", "en-US");
using (var client = CreateHttpClient())
{
try
{
HttpResponseMessage response = client.PostAsJsonAsync(requestUri, httpContent).Result;
if (response.IsSuccessStatusCode)
{
return response;
}
else
{
GetErrorsResponse(response);
throw new HttpRequestException(string.Format("There was an exception trying to post a request. response: {0}", response.ReasonPhrase));
}
}
catch (HttpRequestException ex)
{
throw ex;
//return null;
}
}
}
I was able to fix the issue by not converting the request to json but send as object. Though the error provided is very generic and could not identify the main issue. Upon asking to someone has experienced in ebay integration, the main issue is to provide all the needed in the headers.
public HttpResponseMessage PostHttpResponse(string requestUri, object data)
{
using (var client = CreateHttpClient())
{
try
{
HttpResponseMessage response = client.PostAsJsonAsync(requestUri, data).Result;
if (response.IsSuccessStatusCode)
{
return response;
}
else
{
GetErrorsResponse(response);
throw new HttpRequestException(string.Format("There was an exception trying to post a request. response: {0}", response.ReasonPhrase));
}
}
catch (HttpRequestException ex)
{
throw ex;
//return null;
}
}
}
And in the httpclient needs to add the header.
private HttpClient CreateHttpClient()
{
var client = new HttpClient();
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
string baseAddress = WebApiBaseAddress;
if (string.IsNullOrEmpty(baseAddress))
{
throw new HttpRequestException("There is no base address specified in the configuration file.");
}
client.Timeout = new TimeSpan(0, 5, 59);
client.BaseAddress = new Uri(baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("Authorization", string.Format("Bearer {0}", _cred.eBayToken));
client.DefaultRequestHeaders.Add("Accept-Language", "en-US");
client.DefaultRequestHeaders.Add("Accept-Charset", "utf-8");
client.DefaultRequestHeaders.Add("Accept", "application/json");
client.DefaultRequestHeaders.Add("LegacyUse", "true");
return client;
}

How to send POST request to outlook 365 API to ReplyAll

I am trying to ReplyAll to email with Outlook 365 API. Following this tutorial. As per tutorial to ReplyAll we just need to input Commnet but when I try to do that it's giving Bad Request error -
"error": {
"code": "ErrorInvalidRecipients",
"message": "At least one recipient isn't valid., A message can't be sent because it contains no recipients."
}
I am trying to do this with below method.
public string EmailReplyAll(AuthenticationResult result, string uriString, string msgBody)
{
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uriString);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
EmailReplyAll replyAll = new EmailReplyAll();
replyAll.MsgBody = msgBody;
var jsonData = JsonConvert.SerializeObject(msgBody);
var content = new StringContent(jsonData, Encoding.UTF8, "application/json");
HttpResponseMessage response = httpClient.PostAsync(request.ToString(),content).Result;
if (!response.IsSuccessStatusCode)
throw new WebException(response.StatusCode.ToString() + ": " + response.ReasonPhrase);
uriString = response.Content.ReadAsStringAsync().Result;
return uriString;
}
Could someone please point me where I am doing wrong. I'm trying this with WPF.
Here is what I figured out and working for me.
EmailReplyAll class
public class EmailReplyAll
{
public string Comment { get; set; }
}
The URI string -
var uriString = String.Format(CultureInfo.InvariantCulture, "{0}api/{1}/me/messages/{2}/replyall", graphApiEndpoint, graphApiVersion, emailId);
//emailId is id of email e.g - AAMkADBjMGZiZGFACAAC8Emr9AAA=
EmailReplyAll method -
public string EmailReplyAll(AuthenticationResult result, string uriString, string msgBody)
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
EmailReplyAll replyAll = new EmailReplyAll();
replyAll.Comment = msgBody;
var jsonData = JsonConvert.SerializeObject(replyAll);
var content = new StringContent(jsonData, Encoding.UTF8, "application/json");
try
{
HttpResponseMessage response = httpClient.PostAsync(uriString, content).Result;
var apiResult = response.Content.ReadAsStringAsync().Result;
}
catch (Exception exception)
{
return "Error";
}
return apiResult;
}

Categories