Why 2 Different JSON Results with String Parameter Search using RestSharp? - json

If I hard code the band name in my client request with RestSharp I get the results I expect. If I pass in the String I get a different result set. I checked the url it formed and they are the same. Any ideas? I don't use both, I will comment one out and use the other for testing this scenario.
ArtistInfoResponse IMusicRepository.GetArtistResponse(string artistName)
{
var client = new RestClient($"https://api.deezer.com/search?q=artist:{artistName}");
// returns this as url https://localhost:44343/Home/ArtistInformation?artistName=Dave%20Matthews%20Band
var client = new RestClient($"https://api.deezer.com/search?q=artist:\"Dave Matthews Band\"");
// returns this in url https://localhost:44343/Home/ArtistInformation?artistName=Dave%20Matthews%20Band
var request = new RestRequest(Method.GET);
var cancellationTokenSource = new CancellationTokenSource();
IRestResponse response = client.Execute(request);
if (response.IsSuccessful)
{
// Deserialize the string content into JToken object
var content = JsonConvert.DeserializeObject<JToken>(response.Content);
// Deserialize the JToken object into our ArtistInfoResponse Class
return content.ToObject<ArtistInfoResponse>();
}
return null;
}

Related

POST json to external API in .NET Core - Unsupported Media Type

I'm trying to code a middleman API that logs calls and other details from internal users to an external API.
When I try to POST to the external API from my Controller, I get 415 unsupported media type.
I set up my client in the controller constructor like this:
client.BaseAddress = new Uri("https://restapi.***.com/customers/");
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("X-AppSecretToken", Auth.APPSECRETTOKEN);
client.DefaultRequestHeaders.Add("X-AgreementGrantToken", Auth.AGREEMENTGRANTTOKEN);
My POST method looks like this:
var json = JsonConvert.SerializeObject(customer, Formatting.Indented);
using (var stringContent = new StringContent(json))
{
stringContent.Headers.ContentType.CharSet = "";
HttpResponseMessage response = await client.PostAsync(client.BaseAddress, stringContent);
if (!response.IsSuccessStatusCode)
{
return StatusCode((int)response.StatusCode);
}
}
return CreatedAtAction("GetCustomer", new { id = customer.ID }, customer);
I've been looking around and found a lot of comments telling me to use Stringcontent, but I also found a couple of responses saying ByteArrayContent - none of them work.
Can anyone help me?
EDIT: When I run the code with breakpoints it seems like some of the properties in the incoming customer object are set even though I didn't set them in my Postman call.
Example; the external API returns a customernumber when I give it the 5 properties that are obligatory. But when I call my internal API from Postman, sending only those 5 obligatory properties, it autopopulates the customernumber with a 0.
Could this be the source of the error? and how do I tell .net core to not autopopulate the customernumber?
EDIT2: I changed my stringContent to include encoding and used a different overload, so the using line now says
using (var stringContent = new StringContent(json, Encoding.UTF8, "application/json"))
And I removed
stringContent.Headers.ContentType.Charset = "";
to reflect the fact that I tried setting the encoding.
The return code changed from 415 to 400 Bad Request when I changed that.
EDIT3:
Tried NOT serializing with Json.Net, and instead used JObjects and Jproperties;
public async Task<ActionResult<Customer>> PostCustomer([FromBody]Customer customer)
{
JObject payload = new JObject(
new JProperty("currency", customer.Currency),
new JProperty("name", customer.Name),
new JProperty("customergroup",
new JObject(new JProperty("customergroupNumber",
customer.CustomerGroup.CustomerGroupNumber)
)),
new JProperty("paymentTerms",
new JObject(new JProperty("paymentTermsNumber",
customer.PaymentTerms.PaymentTermsNumber)
)),
new JProperty("vatZone",
new JObject(new JProperty("vatZoneNumber",
customer.VatZone.VatZoneNumber)
))
);
using (var stringContent = new StringContent(payload.ToString(), Encoding.UTF8, "application/json"))
{
HttpResponseMessage response = await client.PostAsync(client.BaseAddress, stringContent);
if (!response.IsSuccessStatusCode)
{
return StatusCode((int)response.StatusCode);
}
}
return CreatedAtAction("GetCustomer", new { id = customer.CustomerNumber }, customer);
}
Still 400 Bad Request
This is a case of capitalizing - simple really.
My POST request JSON had an object named customergroup - changed it to customerGroup, and it worked.

Post string to Rest API results in 400 Bad Request

Sending a post request with a json object transformed into HttpContent, but the result is a 400 Bad request.
Sender
HttpClient _client = new HttpClient();
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var jsonObject = new JObject(new JProperty("id", Id), new JProperty("image", face));
var strJson = JsonConvert.SerializeObject(jsonObject);
var response = _client.PostAsync(_settings.Uri,
new StringContent(strJson, Encoding.UTF8, "application/json"));
Receiver
[HttpPost]
public IActionResult Post([FromBody]string value)
Could you please give me an advise on how to overcome 400 error?
You current code sends an object serialized to json while ASP.NET Core action expects a string serialized to json. The easiest solution would be repeated data serialization
var objectJson = JsonConvert.SerializeObject(jsonObject);
var stringJson = JsonConvert.SerializeObject(objectJson);
var response = _client.PostAsync(_settings.Uri, new StringContent(stringJson, Encoding.UTF8, "application/json"));
It appears that you have an extra Parentheses in your call
var response = _client.PostAsync(_settings.Uri, (new StringContent(strJson, Encoding.UTF8, "application/json"));
(new
Try removing that first.
Cheers

Custom response in place of "error": "invalid_grant"

I'm using oAuth 2.0 in ASP.NET web API.
In refresh token provider class I have code like this.
public Task ReceiveAsync(AuthenticationTokenReceiveContext context)
{
string tokenId = context.Token;
var protectedTicket = WebApiBusiness.GetProtectedTicket(tokenId);
if (!string.IsNullOrEmpty(protectedTicket))
{
context.DeserializeTicket(protectedTicket);
var result = WebApiBusiness.RemoveRefreshToken(tokenId);
}
else
{
context.Response.ContentLength = 200;
context.Response.ContentType = "application/json";
var ML_DefaultRes = new ML_DefaultRes()
{
ResponseCode = ResponseCodes.TokenInvalidRC,
APIVersion = apiversion,
ErrorDescription = ResponseCodes.GetRCDescription(ResponseCodes.TokenInvalidRC)
};
string str = JsonConvert.SerializeObject(ML_DefaultRes);
context.Response.Write(str);
return;
}
}
When refresh token is not valid I want custom response in JSON format.
But instead of setting content length to 200 it is taking content length upto 25 only, which makes invalid JSON response.
Is their any way to make this happen?

Salesforce JSON POST works for standard objects by not custom object

I am using the Salesforce REST API. I have created a new custom object within SFDC and want to POST data to it. I can happily POST JSON documents to the standard SFDC objects such as Account or Contact. However, when I try posting to my custom object I receive a timeout from SFDC.
Here is the method I am using to perform all POSTS (whether standard or custom)
public static BsonDocument PostJSONToSFDC(string uri, BsonDocument postDoc, string method, HPSUtilities.Transformation.Transformation transformation)
{
string accessToken = transformation.sfdcAccess.accessToken;
string instanceUri = transformation.sfdcAccess.instanceUri;
string uri2 = instanceUri + uri;
System.Net.WebRequest req = System.Net.WebRequest.Create(uri2);
req.ContentType = "application/json";
req.Method = method;// "POST" or "PATCH"; // a PATCH alternative uses POST with url parm="?_HttpMethod=PATCH"
req.Headers.Add("Authorization: Bearer " + accessToken);
string postDocAsString = postDoc.ToJson();
byte[] bytes = System.Text.Encoding.ASCII.GetBytes(postDocAsString);
req.ContentLength = bytes.Length;
System.IO.Stream os = req.GetRequestStream();
os.Write(bytes, 0, bytes.Length); //Push it out there
os.Close();
System.Net.WebResponse resp = req.GetResponse();
if (resp == null) return null;
System.IO.StreamReader sr =
new System.IO.StreamReader(resp.GetResponseStream());
string rs = sr.ReadToEnd().Trim();
MongoDB.Bson.BsonDocument doc2;
if (rs.Equals("") && method.Equals("PATCH", StringComparison.CurrentCultureIgnoreCase))
{
// For successful PATCHs (updates), SFDC mysteriously returns a completely empty response.
// In this case let's create something more meaningful!
doc2 = new BsonDocument();
doc2.Add("success", "true");
}
else
{
doc2 = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<MongoDB.Bson.BsonDocument>(rs);
}
return doc2;
}
Given that this code works when POSTing or PATCHing to SFDC I believe that I must be hitting some sort of SFDC restriction for custom objects. Is it necessary to mark SFDC custom objects as API-enabled? Is anyone aware of any other issues that might be causing my timeout?

Query Camel case json documents in Azure CosmosDB

I have created collections with camelcase partition keys like \locationId instead of \LocationId. Also when inserting / updating documents in cosmosdb, i have added them as camelcase using below code :
T entity = null;
var settings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
var messageBody = JsonConvert.SerializeObject(entity, Formatting.Indented, settings);
using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(messageBody)))
{
var res = Resource.LoadFrom<Document>(memoryStream);
await _client.UpsertDocumentAsync((await _collection).SelfLink, res, option);
}
However, when retriving any document using linq condition, the result is always null. I have decorated all CosmosDB T types with [JsonProperty(PropertyName = "id")]
Am i missing something here?