Sending a json object in a post method - c#

I am trying to create a virtual machine through a post method but I have not been able to create it since I cannot send the json file correctly.
This is my code:
// Create a json object
var deploy = new Deploy
{
name = "RandomName",
folder = "folder_3044",
resource_pool = "resgroup-4035"
};
//Change it into a json file
var deployResult = JsonConvert.SerializeObject(deploy);
//Change this file into a string so we can send it to the post method
var jsonContent = new StringContent(deployResult);
//Make post and send the needed information
var postResponse = await httpClient.PostAsync("URI", jsonContent);
return (content);
When executing my code in Postman it gives me a false positive because it sends something but it seems that it does not send the json as I wanted but the code below:
{
"headers": [
{
"key": "Content-Type",
"value": [
"text/plain; charset=utf-8"
]
},
{
"key": "Content-Length",
"value": [
"97"
]
}
]
}
Can anyone help me with this? I just need to send that json in my post like I do when sending from Postman.
Ps: I use .Net core and I can't change even if I want to.
This is the json that should be sent for it to work:
{
"name": "RandomName",
"placement": {
"folder": "folder_3044",
"resource_pool": "resgroup-4035"
}
}

Thank you to #Peter Csala's comment: When I specified the content-type as you advised, it worked. Just for future references, we need these two lines of code. (Don't forget to include the assembly System.Text on top.)
using System.Text;
new StringContent(deployResult, Encoding.UTF8, "application/json");

Related

View pre-deserialized response from GraphQL query

I have a simple GraphQL query that I'm making out to a server, and trying to use GraphQL.Client.Serializer.Newtonsoft to deserialize it. I'm getting a response, but the response does not make the NewtonsoftJsonSerializer happy. It complains:
This converter can only parse when the root element is a JSON Object.
Okay, fair enough. The response must not be what was expected. But how can I view the response to see what may be wrong? The GraphQLHttpClient.SendQueryAsync<>() method requires a type to try to deserialize to...which is the part that is failing. I don't see a way to just get the text response so I can see what is wrong with it.
I've included sample code at the bottom, but the only real line of interest (I believe) is the last one:
var graphQLResponse = await graphQLClient.SendQueryAsync<object>(theRequest);
Is there some way to just get the text of the response?
var graphQLClient = new GraphQLHttpClient("https://<TheDomain>.com/graphql/api/v1", new NewtonsoftJsonSerializer());
graphQLClient.HttpClient.DefaultRequestHeaders.Add("Authorization", "Bearer <MyKey>");
graphQLClient.HttpClient.DefaultRequestHeaders.Add("Accept", "application/json");
var theRequest = new GraphQLRequest
{
Query = "{ __schema { queryType { fields { name } } } }"
};
var graphQLResponse = await graphQLClient.SendQueryAsync<object>(theRequest);
Using Fiddler Everywhere, I was able to pull in the request and response, both of which seem superficially valid (I updated the query in the question to match the current query I'm passing in...a general schema query)
Request:
{
"query": "{ __schema { queryType { fields { name } } } }"
}
Response:
(I've redacted the names of the endpoints and removed much of the repetition from the middle of the response. But the rest is unchanged, and looks superficially okay to me...in particular, it looks like valid JSON, so I'm unclear why the converter is complaining.)
{
"errors": [],
"data": {
"__schema": {
"queryType": {
"fields": [
{
"name": "getData1"
},
{
"name": "getData2"
},
...
<a bunch more here>
...
{
"name": "getData100"
}
]
}
}
},
"extensions": null,
"dataPresent": true
}
After a few hit and trials and discussion with the O.P, it was found that while initializing GraphQLHttpClient with GraphQL.Client.Serializer.Newtonsoft, the serializer is not correctly doing the deserialization of the response despite the response being a valid JSON string.
After switching to GraphQL.Client.Serializer.SystemTextJson, the response is being correctly parsed as expected which suggests that there could be a bug in the GraphQL.Client.Serializer.Newtonsoft serializer

Why is Asp.net Core returning JSON instead of a CSV file? [duplicate]

I am currently working with ASP.NET Core RC2 and I am running into some strange results.
So I have an MVC controller with the following function:
public HttpResponseMessage Tunnel() {
var message = new HttpResponseMessage(HttpStatusCode.OK);
message.Content = new StringContent("blablabla", Encoding.UTF8);
message.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("text/plain");
message.Headers.CacheControl = new System.Net.Http.Headers.CacheControlHeaderValue {
NoCache = true
};
return message;
}
If I call this with postman with an Accept header set to text plain I get this response:
{
"Version": {
"Major": 1,
"Minor": 1,
"Build": -1,
"Revision": -1,
"MajorRevision": -1,
"MinorRevision": -1
},
"Content": {
"Headers": [
{
"Key": "Content-Type",
"Value": [
"text/plain"
]
}
]
},
"StatusCode": 200,
"ReasonPhrase": "OK",
"Headers": [
{
"Key": "Cache-Control",
"Value": [
"no-cache"
]
}
],
"RequestMessage": null,
"IsSuccessStatusCode": true
}
I really do not understand how this is the generated reponse to the above controller. It is basically a JSON serialization of the entire message itself and does in no way contain the "blablabla" I intended to send.
The only way I have gotten the desired result is by making my controller function return string instead of HttpResponse, but that way I am unable to set headers like CacheControl
So my question is: why do I get this strange response? It seems like very weird behaviour to me
According to this article, ASP.NET Core MVC does not support HttpResponseMessage-returning methods by default.
If you want to keep using it, you can, by using WebApiCompatShim:
Add reference to Microsoft.AspNetCore.Mvc.WebApiCompatShim to your project.
Configure it in ConfigureServices(): services.AddMvc().AddWebApiConventions();
Set up route for it in Configure():
app.UseMvc(routes =>
{
routes.MapWebApiRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
If you want to set Cache-Control header with string content, try this:
[Produces("text/plain")]
public string Tunnel()
{
Response.Headers.Add("Cache-Control", "no-cache");
return "blablabla";
}
In ASP.NET Core, modify the response as it travels through the pipeline. So for headers, set them directly as in this answer. (I've tested this for setting cookies.) You can also set the HTTP status code this way.
To set content, and therefore use a specific formatter, follow the documentation Format response data in ASP.NET Core Web API. This enables you to use helpers such as JsonResult() and ContentResult().
A complete example translating your code might be:
[HttpGet("tunnel")]
public ContentResult Tunnel() {
var response = HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.OK;
response.Headers[HeaderNames.CacheControl] = CacheControlHeaderValue.NoCacheString;
return ContentResult("blablabla", "text/plain", Encoding.UTF8);
}

Trying to PUT string with Postman in local C# web api, always null or fails

I currently have this WEB API running locally:
// POST api/CsvParse
[HttpPut]
public void Put([FromBody]string value)
{
if (string.IsNullOrEmpty(value))
throw new Exception("Input is null or empty.");
}
I currently have it running locally, and am sending a string to the put using POSTMAN. I have selected the body tab, and have the string pasted into the raw body tab:
It states that my text is unsupported, or when I add a break point the value is null or I get the error describing the format is incorrect.
What am I doing wrong?
That's because there is no media type formatter that can serialize a raw string into your model (your route parameter with [FromBody] attribute).
A quick and dirty workaround is to directly read the body of your request as a string:
[HttpPut]
public async Task<HttpResponseMessage> Put(HttpRequestMessage request)
{
var myCsv = await request.Content.ReadAsStringAsync();
// do stuff with your string
return new HttpResponseMessage(HttpStatusCode.OK);
}
As an alternative you could implement a custom media type formatter yourself, as per this answer.
Change the media type to x-www-form-urlencoded rather than multipart/form-data.
Also, WebAPI is particular about FromBody parameters.
http://encosia.com/using-jquery-to-post-frombody-parameters-to-web-api/
For you, I think this is the relevant part:
[FromBody] parameters must be encoded as =value
The final hurdle remaining is that Web API requires you to pass
[FromBody] parameters in a particular format. That’s the reason why
our value parameter was null in the previous example even after we
decorated the method’s parameter with [FromBody].
Instead of the fairly standard key=value encoding that most client-
and server-side frameworks expect, Web API’s model binder expects to
find the [FromBody] values in the POST body without a key name at all.
In other words, instead of key=value, it’s looking for =value.
This part is, by far, the most confusing part of sending primitive
types into a Web API POST method. Not too bad once you understand it,
but terribly unintuitive and not discoverable.
Try adding a content type of text/plain
There is a similar Q&A here
I found that solution #1 worked for me as I was trying to PUT JSON containing the Key/Value pair. So originally my JSON looked like this
{
"subscriber": {
"Id": "2",
"subscriptions":[
{
"Name": "Subscription 1",
"Id": "18",
"IsSubscribed": false
},
{
"Name": "Subscription 2",
"Id": "19",
"IsSubscribed": false
},
{
"Name": "Subscription 3",
"Id": "20",
"IsSubscribed": false
}
]
}
}
But I modified it to become
{
"Id": "2",
"subscriptions":[
{
"Name": "Subscription 1",
"Id": "18",
"IsSubscribed": false
},
{
"Name": "Subscription 2",
"Id": "19",
"IsSubscribed": false
},
{
"Name": "Subscription 3",
"Id": "20",
"IsSubscribed": false
}
]
}
And that worked. My PUT request from Postman was recognised in my C# web api using [FromBody]
Just to add my bit, there is one more solution to pass primitives into a POST or a PUT method. Just specify the model as JObject. ASP.Net core web api then binds incoming JSON object(containing primitives like string) into JObject model object.
Your code would look like this:
// POST api/CsvParse
[HttpPut]
public void Put([FromBody]JObject value)
{
//access your string data
string data = value[SPECIFY_KEY_HERE];
if (string.IsNullOrEmpty(data))
throw new Exception("Input is null or empty.");
}

Format JSON response using ASP.NET JsonResult Class

I'm trying to integrate BlueImp jQuery file upload component into my ASP.NET 4 website. I have the file upload working and writing to disk, but the component requires that I return a JSON object from the server as confirmation of success, in a particular format:
{"files": [
{
"name": "picture1.jpg",
"size": 902604,
"url": "http:\/\/example.org\/files\/picture1.jpg",
"thumbnailUrl": "http:\/\/example.org\/files\/thumbnail\/picture1.jpg",
"deleteUrl": "http:\/\/example.org\/files\/picture1.jpg",
"deleteType": "DELETE"
},
{
"name": "picture2.jpg",
"size": 841946,
"url": "http:\/\/example.org\/files\/picture2.jpg",
"thumbnailUrl": "http:\/\/example.org\/files\/thumbnail\/picture2.jpg",
"deleteUrl": "http:\/\/example.org\/files\/picture2.jpg",
"deleteType": "DELETE"
}
]}
I'd like to use the JsonResultClass to return this object in my C#, but I'm not sure how to format the response correctly. I can probably do something like this:
var uploadedFiles = new List<object>();
uploadedFiles.Add(new { name = "picture1.jpg", size = 902604, url = "http://example.org/files/picture1.jpg", thumbnailUrl = "http://example.org/files/thumbnail/picture1.jpg", deleteUrl ="http://example.org/files/picture1.jpg", deleteType = "DELETE" });
uploadedFiles.Add(new { name = "picture2.jpg", size = 902604, url = "http://example.org/files/picture1.jpg", thumbnailUrl = "http://example.org/files/thumbnail/picture1.jpg", deleteUrl ="http://example.org/files/picture1.jpg", deleteType = "DELETE" });
return Json(uploadedFiles);
...but then I'm not sure how to wrap this in the outer 'files' object.
Can anyone point me (a .NET novice trying to learn!) in the right direction here. I've looked at the MSDN documentation but it doesn't go into detail about formatting or constructing more complex JSON objects.
Many thanks.
Replace:
return Json(uploadedFiles);
with:
return Json(new {files = uploadedFiles});
to create a new anonymous type with property "files", which has your original list as a value.

Easiest way to read from a response from URL

I am new to C#, and did not find an easy piece of code to read a response from a URL. Example:
http://www.somesitehere.com/mysearch
The response is something like this ( I do not know what kind of response is this):
{ "response": {
"status": {
"code": "0",
"message": "Success",
"version": "4.2"
},
"start": 0,
"total": 121,
"images": [
{
"url": "www.someimagelinkhere.com/pic.jpg",
"license": {
"url": "",
"attribution": "",
"type": "unknown"
}
}
]
}}
After that I will to save that url "www.someimagelinkhere.com/pic.jpg" to a file. But this I know how to do. I just want to separate the url from the rest.
I saw this topic: Easiest way to read from a URL into a string in .NET
bye
Your response is of JSON Format. Use a library (NewtonSoft but there are others too) to extract the node you want.
You can use something like JSON.NET by Newton soft, which can be found and installed using NuGet Package Manager in Visual Studio.
Also you could just do this.
var jSerializer = new JavaScriptSerializer();
var result = jSerializer.DeserializeObject("YOUR JSON RESPONSE STRING");
The JSON string will not be a C# object with properties that match your names such as start, total, images, etc. If you need to you can create a strong type object and cast your converted object to that one for ease of use.
Strong typed version:
var jSerializer = new JavaScriptSerializer();
var result = (YourStrongType)jSerializer.DeserializeObject("YOUR JSON RESPONSE STRING");
var imgUrl = result.images[0].url;

Categories