How to properly pass and receive a json object? - c#

From the client, I would like to pass a collection of json nodes: [{key, value},{key, value}] to a WebAPI endpoint. what should my api endpoint param type be? a List<>() or something else?
This would be using C#.
I need to iterate over each endpoint that is passed in the collection.

In general, it is good practice to create a model that your JSON will be deserialized into. To answer your question though if your JSON was in the format
[{key1: value1},{key2: value2}]
you would be able to use a
List<Dictionary<string,object>>()
If you were sure that your values were always string values you could do
List<Dictionary<string,string>>()
As JSON values can be strings (wrapped in quotes), integers (no quotes) or null.
So your Web API controller could be something like this:
[HttpPost]
public IHttpActionResult ReceiveJSON([FromBody]List<Dictionary<string,string>> in_json)
{
// And then one way to iterate over each 'json node' passed
foreach(var dict in in_json)
{
// Do something with dictionary object
}
return Ok(in_sjon);
}
What version of ASP.Net Web API will you be using?

Related

Json object in post not recognized as object in web api

I have an angular client and want to execute a get request to my web api backend to get a list of items from the underlying Dapper Db Wrapper. Dapper allows me to pass in parameters as an anonymous object which would in csharp look like this:
connection.GetList<T>(new {myParam1:"a", myParam2: true});
What I want to achieve is, to create this parameter object in my angular frontend and pass it in a post request to the server which would then pass it on to the GetList function. The problem here is that the web api does not deserialize it as an (anonymous) object, but rather and IEnumerable of JTokens?
My web api signature is this:
public async Task<IHttpActionResult> MyFunction([FromBody]dynamic whereCond)
I have also tried to pass the object as string wrapped in an outer object like so (angular client):
this.migController.MigrationGetMigrationReports({whereCond: JSON.stringify({NotMigrated: true, MissingTargetFiles: 0})})
and then on the server I manually deserialize it as JObject:
string obj = whereCond.whereCond;
dynamic pObj = JObject.Parse(obj);
But this results in the exact same result: pObj is an IEnumerable and therefore I get an error message from the GetList call:
An enumerable sequence of parameters (arrays, lists, etc) is not allowed in this context
can anybody help?
The answer to my question turned out rather simple:
dynamic pObj = JObject.Parse(obj).ToObject<ExpandoObject>();
I had to cast it as ExpandoObject not just dynamic.
#Tsahi: this is not a design problem. My intention was to provide the server with parameters (filter) which is a quite common task for a client to reduce the dataset to be transferred. We could debate a standard way how to provide these parameters, however. In my special case the most practical way is the anonymous object.

How can I return Json object in .net core controller? [duplicate]

The standard way AFAIK to return data in ASP.NET Core Web Api is by using IActionResult and providing e.g. an OkObject result. This works fine with objects, but what if I have obtained a JSON string somehow, and I just want to return that JSON back to the caller?
e.g.
public IActionResult GetSomeJSON()
{
return Ok("{ \"name\":\"John\", \"age\":31, \"city\":\"New York\" }");
}
What ASP.NET Core does here is, it takes the JSON String, and wraps it into JSON again (e.g. it escapes the JSON)
Returning plain text with [Produces("text/plain")] does work by providing the "RAW" content, but it also sets the content-type of the response to PLAIN instead of JSON. We use [Produces("application/json")] on our Controllers.
How can I return the JSON that I have as a normal JSON content-type without it being escaped?
Note: It doesn't matter how the JSON string was aquired, it could be from a 3rd party service, or there are some special serialization needs so that we want to do custom serialization instead of using the default JSON.NET serializer.
And of course a few minutes after posting the question I stumble upon a solution :)
Just return Content with the content type application/json...
return Content("{ \"name\":\"John\", \"age\":31, \"city\":\"New York\" }", "application/json");
In your action, replace Ok() with the Content() method, which lets you set the content (raw content), content type, and status code of your response: https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.contentresult?view=aspnetcore-2.0
This worked for me, where Json() did not:
return new JsonResult(json);

How to pass key values pairs to HttpGet in ASP.NET Core WebApi?

I am creating a WebApi and I need to take a key value pairs for my GET endpoint. I found some examples of using dictionary in POST method bus this seems not to work with GET
So far I tried this:
[HttpGet]
public IActionResult Get([FromQuery] Dictionary<string, string> myVar)
{
}
I am using swagger to test the API and if I pass {"key":"value"} I am getting my dictionary with a single pair and value is the entire object I pass in. ({[myVar, {"key":"value"}]})
What is the correct way to pass multiple key value pairs to the WebApi for GET method?
EDIT: The underlying issue was that I was using swagger (swashbuckle) to test my endpoint. And at the moment of this question it doesn't support dynamic query parameters Issue on github. It should support it once OpenApi v3 support is added to swashbucle Issue on github.
You should be able to call the endpoint using the following structure and have the values automatically bound via Web API's built-in binder.
https://example.com/api/values?1=john&2=jane
1 and 2=keys for respective entries in dictionaries.
john and jane=values

Build a WCF with generic type

I want to build a service that will pass the data read from the database to the client in JSON format. I don't know the schema table and the types.
I thought about implementing the WCF over Dictionary but the JSON is very complicated and contains objects like "key = ...; value = ..." and i want just "key=value" and i need to return list of Dictionary objects. Sometimes from database i will receive a comma separated array, so i will insert in my Dictionary a key with a new Dictionary as value.
In PHP my boss said that it can be done through associative arrays. Please help me with some ideas or link because i don't know where to start to look.
If there is something that you didn't understood please comment and i will try another explanation.
Edits:
I need it to be a rest service, so JSON is mandatory.
How can i load data from the table ? What type can i use ?
Edit #2 : This is what i want to get : CorectJSON
Edit #3 : This is my current json :
stdClass Object
(
[areaGetStreetTypesResult] => stdClass Object
(
[responseMessage] => [{"name":"IMPASSE","street_type":"IMP"}{"name":"LOTISSEMENT","street_type":"LOT"}{"name":"ROUTE","street_type":"RTE"}{"name":"RUE","street_type":"RUE"}]
[response_status] => stdClass Object
(
[message] => Success : JSON created into the responseMessage variable !
[status] => 0
)
)
)
Is not containing some commas between so it cannot be decoded by php. What should i do ?
This is my method Code
I think that doing everything as a dictionary in webservice API is bad practice and I hate when I need to work with API's like this. If it is a WCF, it produces WSDL and WDSL describes the data is going in and out, so if everything is dictionary, WSDL can not provide anything meaningfull, so your datacontracts tell you nothing about the data.
If you need simply forward database data through webservice, WCF has DataServices http://msdn.microsoft.com/en-us/data/bb931106 although I think you should create API that fits your business needs and is not simple proxy between database and your client.
What is the reason why you need to pass JSON? If you want to create a WCF REST service, it is sufficient to tell WCF to create JSON messages as described here: http://www.codeproject.com/Articles/327420/WCF-REST-Service-with-JSON
If you access the service from a C# application, you don't need to care about how data is passed back and forth. Just take "normal" method parameters and use return values like you'd do locally and you're set.
Example:
string[] GetResultStrings(List<Rectangle> sourceRectangles);
If you really need to pass JSON strings, just pass strings and use the JSON serializer and deserializer to encode the reply and decode the parameters.
For example:
string GetJSONString(string jsonRequest);
The following information may help on using the JSON serializer and deserializer: http://www.codeproject.com/Articles/272335/JSON-Serialization-and-Deserialization-in-ASP-NET
EDIT
I'm using the following method to serialize serializable objects to JSON:
public static string SerializeJSON(this object obj)
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
using (MemoryStream ms = new MemoryStream())
{
serializer.WriteObject(ms, obj);
return Encoding.UTF8.GetString(ms.ToArray());
}
}
This works just fine for any DataContract class like:
[DataContract]
public class MyJSONReturnableClass
{
[DataMember]
public string ThisBecomesANamedString;
[DataMember]
public MyJSONReturnableClass[] AndWorksAlsoForNestedArrays;
}
Populate your dictionary, then serialize it using JSon.
Pass it to your client using WCF or RabbitMq...
JsonConvert.SerializeObject(yourDict);
Download the NewtonSoft.dll
Put using:
using Newtonsoft.Json;

When HTTP-POST has body, url parameter is null

This is self-hosted RESTful MVC4 Web API, the only route is api/{controller}/{state}. When I send an HTTP-POST that has a body, the state argument comes in null. If I remove the body the state variable is present.
The way I thought it worked for HTTP-POST was that the url parameters get mapped then the body gets serialized into the extra parameter, which in this case is data parameter. The content is just string data which I had to write a custom MediaTypeFormatter (which I thought was odd it couldn't handle a regular string).
Here is my controller signature
public class MyController : ApiController
{
public void Post(string state, string data)
{
}
}
Has anyone seen this behavior before or can explain to me why having a body present is affecting my url parameter?
One Solution:
I tried changing data parameter into a complex type (Just a class with a public property) and sending the content as text/xml instead of text/plain and it worked as expected. The state parameter wasn't null and I had my strongly typed object with the data. I suppose MVC wants to have something to deserialize like XML or JSON for the http-request body...
More Research:
I've had the chance to run some more tests. If the body of a post is XML/JSON it will first try to map the properties of the body-object to the method parameters like so. If still has unmapped properties then it will match the remaining properties to the properties of any strongly-typed objects in the method parameters
PostMethod(string p1, string p2, myClass obj) // if myClass has a p3 property it will be mapped from the xml body.
{
}
// xml in body of http-post
<Xml>
</p1>
</p2>
</p3>
</Xml>
If all the parameters were not mapped, then it will attempt to map the url parameters. To relate it directly to my initial problem. The best and easiest solution I see at this time is to send text/xml like this.
PostMethod(string state, string data)
{
}
<data>put data here</data>
Urlencoded key/value pairs also work very well.
var r = client.PostAsync(url, new StringContent("data=Something", Encoding.UTF8, "application/x-www-form-urlencoded"));
My best guess is that the key/value nature of JSON and XML, FormEncoded help it to map to parameters so that is why it doesn't like plain strings.
This sure gave me a headache and I find the MVC4 documentation to be rather scarce (its still in beta), but I hope this can help someone else who may have the same problem.

Categories

Resources