Why is JsonContent not populating before SendAsync? - json

I'm using a .NET Core console application to send JSON data to an Azure Logic App. If the JSON data is a short list of data e.g. 4 items then everything works. For more data I have to evaluate the Content of the HttpRequestMessage before sending otherwise the Azure Logic App reports empty content. Is there any alternative to forcing evaluation, it feels counter intuitive.
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var postRequest = new HttpRequestMessage(HttpMethod.Post, uri)
{
Content = JsonContent.Create(data)//data is a list object
};
//need this line to evaluate the content before posting otherwise content is empty according to Azure Logic App
await postRequest.Content.ReadAsStringAsync();
using var postResponse = await httpClient.SendAsync(postRequest);
postResponse.EnsureSuccessStatusCode();
This code structure seems to feature in a lot of tutorials without the call to postRequest.Content.ReadAsStringAsync() without anyone experiencing similar problems.
An example of the JSON that fails would be:
[{"runDate":"2021-02-18T16:30:11.23","name":"AuditLog","rows":3859209,"reservedKb":22061528,"dataKb":8781560,"reservedIndexSize":66328,"reservedUnused":13213640,"dbName":"DBOne"},{"runDate":"2021-02-18T16:30:11.23","name":"AnswerData","rows":70167,"reservedKb":12586736,"dataKb":12494912,"reservedIndexSize":1472,"reservedUnused":90352,"dbName":"DBOne"},{"runDate":"2021-02-18T16:30:11.23","name":"Data_import","rows":3623146,"reservedKb":722632,"dataKb":379704,"reservedIndexSize":1424,"reservedUnused":341504,"dbName":"DBOne"},{"runDate":"2021-02-18T16:30:11.23","name":"Answers","rows":2036892,"reservedKb":528872,"dataKb":270096,"reservedIndexSize":257360,"reservedUnused":1416,"dbName":"DBOne"},{"runDate":"2021-02-18T16:30:11.23","name":"Data","rows":3623146,"reservedKb":381256,"dataKb":379704,"reservedIndexSize":1424,"reservedUnused":128,"dbName":"DBOne"},{"runDate":"2021-02-18T16:30:11.23","name":"Data_backup","rows":3623146,"reservedKb":380048,"dataKb":379704,"reservedIndexSize":16,"reservedUnused":328,"dbName":"DBOne"},{"runDate":"2021-02-18T16:30:11.23","name":"datadec","rows":3623146,"reservedKb":252168,"dataKb":232952,"reservedIndexSize":8,"reservedUnused":19208,"dbName":"DBOne"},{"runDate":"2021-02-18T16:30:11.23","name":"SalesDetails","rows":84168,"reservedKb":170496,"dataKb":138104,"reservedIndexSize":20136,"reservedUnused":12256,"dbName":"DBOne"},{"runDate":"2021-02-18T16:30:11.23","name":"OurUsers","rows":66145,"reservedKb":72240,"dataKb":37880,"reservedIndexSize":32776,"reservedUnused":1584,"dbName":"DBOne"},{"runDate":"2021-02-18T16:30:11.23","name":"Orders","rows":362720,"reservedKb":70016,"dataKb":53608,"reservedIndexSize":11976,"reservedUnused":4432,"dbName":"DBOne"},{"runDate":"2021-02-18T16:30:11.597","name":"CustDetails","rows":8949,"reservedKb":16392,"dataKb":15704,"reservedIndexSize":80,"reservedUnused":608,"dbName":"DBTwo"},{"runDate":"2021-02-18T16:30:11.597","name":"OurUsers","rows":5580,"reservedKb":6096,"dataKb":4456,"reservedIndexSize":1600,"reservedUnused":40,"dbName":"DBTwo"},{"runDate":"2021-02-18T16:30:11.597","name":"Answers","rows":56835,"reservedKb":5184,"dataKb":5104,"reservedIndexSize":32,"reservedUnused":48,"dbName":"DBTwo"},{"runDate":"2021-02-18T16:30:11.597","name":"UserRoles","rows":5577,"reservedKb":4632,"dataKb":1496,"reservedIndexSize":3056,"reservedUnused":80,"dbName":"DBTwo"},{"runDate":"2021-02-18T16:30:11.597","name":"CustDetails","rows":5866,"reservedKb":1928,"dataKb":1864,"reservedIndexSize":16,"reservedUnused":48,"dbName":"DBTwo"},{"runDate":"2021-02-18T16:30:11.597","name":"OrderHistories","rows":6102,"reservedKb":1224,"dataKb":1168,"reservedIndexSize":16,"reservedUnused":40,"dbName":"DBTwo"},{"runDate":"2021-02-18T16:30:11.597","name":"Orders","rows":6196,"reservedKb":1224,"dataKb":1176,"reservedIndexSize":16,"reservedUnused":32,"dbName":"DBTwo"},{"runDate":"2021-02-18T16:30:11.597","name":"Transfers","rows":7522,"reservedKb":840,"dataKb":816,"reservedIndexSize":16,"reservedUnused":8,"dbName":"DBTwo"},{"runDate":"2021-02-18T16:30:11.597","name":"SalesDetails","rows":8762,"reservedKb":648,"dataKb":576,"reservedIndexSize":16,"reservedUnused":56,"dbName":"DBTwo"},{"runDate":"2021-02-18T16:30:11.597","name":"TransferAdvice","rows":13706,"reservedKb":392,"dataKb":328,"reservedIndexSize":16,"reservedUnused":48,"dbName":"DBTwo"}]

Related

Yii2 HttpClient: Access Request instance from Response instance

Using yii2-httpclient, what is the correct way to access the corresponding yii\httpclient\Request instance from the resulting yii\httpclient\Response object?
I am trying to write a custom XML parser which needs to know what URL it is parsing. It does not seem to be possible to access the original Request (through which I could get the URL) from a parser instance (only the Response).
I have considered utilizing yii\httpclient\Client::EVENT_AFTER_SEND to copy the request into a variable, but that would not be thread-safe, so I need a better solution.
If your parser needs to know URL of request to parse response, it is probably not a parser and you're overusing parser API and ParserInterface. I suggest to create some component which will wrap and hide all request-response-parser logic. Then you will be able to implement custom parser and call it manually:
public function get($url) {
$client = new Client();
$response = $client->createRequest()
->setUrl($url)
->send();
return (new MyParser($url, $response))->getContent();
}

Parse.com cloud httpRequest response.text does not convert to JavaScript object

I have a http request I am trying to make on an afterSave method in my Cloud Code. I have been able to create my request, and when I console.log(response) it outputs a block that contains the information that I am after. I am aware that response.text is a string so I am trying to run JSON.parse(response.text) so I can access my API response.
I can print out what appears to be an object after running JSON.parse, but much of the data within my response is stripped out. I know it is not the fault of the API because I have another function that runs on the client with the same query and it works correctly.
What is the correct way to parse the response.text from a Parse.Cloud.httpRequest to maintain my data.
Try var result = JSON.parse(response['text']).

Microsoft.Net.Http vs Microsoft.AspNet.WebApi.Client

I need to access REST service from .NET application and it seems it can be done with any of those two packages. It's not clear to me which package is supposed to be used in which scenarios. Can anyone bring more light into this?
The short answer is yes, use Microsoft.AspNet.WebApi.Client.
https://www.nuget.org/packages/Microsoft.AspNet.WebApi.Client/
This package adds support for formatting and content negotiation to
System.Net.Http. It includes support for JSON, XML, and form URL
encoded data.
Microsoft.AspNet.WebApi.Client actually depends on Microsoft.Net.Http, and extends the HttpClient with some more features that you would likely need to talk to a RESTful service such as ASP.NET Web API (e.g. JSON and XML support).
Both packages operate in the System.Net.Http namespace and revolve around the key HttpClient class.
The Microsoft.AspNet.WebApi.Client package contains the System.Net.Http.Formatting.dll assembly, which adds some handy extension methods to HttpClient and HttpContent (and others).
So for example:
using (var client = new HttpClient())
{
var response = await client.GetAsync("http://localhost/foo/api/products/1");
response.EnsureSuccessStatusCode();
var product = await response.Content.ReadAsAsync<ProductInfo>();
}
The ReadAsAsync method is an extension method that Microsoft.AspNet.WebApi.Client adds onto the HttpContent object. This automatically figures out if the response is JSON, XML or form URL encoded (the aforementioned content negotiation), and then uses the corresponding formatter to de-serialize it into your strongly typed model (in this case, ProductInfo).
If you tried to just use Microsoft.Net.Http, the ReadAsAsync method wouldn't be available to you, and you'd only be able to read the content as raw data such as bytes or string, and have to do the serializing / de-serializing yourself.
You also get extension methods to PUT / POST back to the service in JSON or XML without having to do that yourself:
// Save the ProductInfo model back to the API service
await client.PutAsJsonAsync("http://localhost/foo/api/products/1", product);
Key Microsoft.AspNet.WebApi.Client extensions:
https://msdn.microsoft.com/en-US/library/system.net.http.httpclientextensions.aspx
https://msdn.microsoft.com/en-US/library/system.net.http.httpcontentextensions.aspx

How to Intercept parameters sent as JSON data in HTTPRequest to Controller?

We are in the process of building a custom built JEE security layer which is going to ensure that all possible OWASP concerns are addressed. This security layer is built as Filters that needs to run before the Controllers (Spring in our case), so that they can execute before the request actually reaches the Controller. These security filters looks at the user input and performs various Sanitation. One such sanitation is the JSON sanitation, where the JSON data from client is looked for any malicious content.
Currently , the Spring Controllers use the #RequestBody annotation to populare the incoming JSON data into POJO classes.
I have exactly the same question but, is there a generic way to retrieve the parameters (sent as JSON data) from the request ?
my objective is to have a JSON sanitizer code in a Filter, so that it
intercepts and parses all JSON data that comes to the controller.
I was able to read & retrieve the json data using the following technique. The StringBuffer jb finally has the entire JSON data.
StringBuffer jb = new StringBuffer();
String line = null;
BufferedReader reader = request.getReader();
while ((line = reader.readLine()) != null)
jb.append(line);
}
Ref: HttpServletRequest get JSON POST data

Get JSON data from RavenDB

I have an Asp.Net MVC3 application that use embedded RavenDB to store data.
The view needs json data that is now created by the controller in this way:
public ContentResult Data()
{
var res = JsonConvert.SerializeObject(DocumentSession.Query<DataObject>());
return new ContentResult { Content = res, ContentType = "application/json" };
}
Everything works fine but to me it seems inefficient because data that are stored in DB in JSON format is serialized in POCO and then deserialized again.
Is there a more direct way to get json data directly from the embedded db?
It's not inefficient at all. Keep in mind that internally, raven actually uses BSON - so you would have to translate it anyway. Also there are metadata fields. If you were to return it directly through your controller, you would have no opportunity to shape the response of the data and strip off the unwanted fields.
If you must continue with this line of thinking, you have two options:
You could use the DocumentStore.DatabaseCommands.Get() and related operations to return RavenJObjects that you could then translate JSON from.
You could talk directly to the Raven database over HTTP without using the raven client.
Neither of these are straightforward, and you are throwing away a lot of goodness of the Raven Client API. IMHO, any performance gain you were to achieve would be unnoticeable. I would stick with your current approach.
Also - If you are just trying to avoid having to serialize here, consider returning a JsonResult instead of a ContentResult. If you want to use Json.Net instead (per your other recent post), Here is a cleaner way to do it: http://james.newtonking.com/archive/2008/10/16/asp-net-mvc-and-json-net.aspx