I have a problem understanding how IEnumerable works in C#.
Background
I'm developing an Azure Function, the purpose of which is to combine data from different API's. I have used an API generator for each of the sources.
Currently I'm trying to make a Post request with one of the generated functions, but
I'm having trouble providing data in the correct format for the parameter.
First of all, in the API's Swagger documentation, it says that the function I'm using requires a Request body that looks like this:
[
{
"name": "string",
"address": "string"
"properties": {
"prop1": "string",
"prop2": "string",
},
}
]
... and when looking at the function in Visual Studio, function needs parameter type of " IEnumerable<> body ".
What have I tried?
First I thought that I could just create an object and pass it as a parameter. Something like this:
var newProperties = new ApiProperties()
{
Prop1 = "example",
Prop2 = "example"
};
var newApiData = new ApiData()
{
Name = "example",
Address = "example",
Properties = newProperties,
};
... and passing newApiData as an parameter to the function.
await api.PostDataAsync(newApiData)
But this does not work because parameter needs to be IEnumerable.
Problem
How can I pass the request body information as an IEnumerable type parameter?
var enumerable = new ApiData[] { newApiData };
That is, you need to pass an IEnumerable (array, list), not a single entry
Instead of directly sending the data, just put the data in an array before sending:
await api.PostDataAsync(new ApiData[] { newApiData });
Instead of an array, create a list:
await api.PostDataAsync(new List<ApiData>() { newApiData });
The IList interface inherits from an IEnumerable, that's why a list will work.
I believe it will be very interesting for you to study the following answer: https://stackoverflow.com/a/4455507/3231884
Related
i am working with two unknown json (i don't know structure) and i need to merge these two, i also have to remove missing properties, I know I probably haven't explained myself very well, so I'll give you an example.
Json 1:
{
'FullName': 'Dan Deleted',
'Deleted': true,
'DeletedDate': '2013-01-20T00:00:00',
'location': {
'nation': 'it',
'city': 'Madrid'
}
}
Json 2:
{
'FullName': 'Dan',
'Age': '23',
'DeletedDate': '2014-01-20T00:00:00',
'location': {
'nation': 'es'
}
what I would:
{
'FullName': 'Dan',
'Deleted': true,
'DeletedDate': '2014-01-20T00:00:00',
'location': {
'nation': 'es',
'city': 'Madrid'
}
}
I'm using Newtonsoft.Json and i've saw that there is a method merge json1.merge(json2) but in this way i will get something like that:
{
"FullName": "Dan",
"Deleted": true,
"DeletedDate": "2014-01-20T00:00:00",
"location": {
"nation": "es",
"city": "Madrid"
},
"Age": "23"
}
I hope you understand.
In practice I would like that if the property is present in both json, in the result the value is that of json2, but if a property is present only in json2, in the result this should not be there. While if it is only in json1 then it will be in the result.
How could I do?
Thank you very much!😃😃
According to Newtonsoft's example its a matter of which JObject it is invoked on and which other JObject is passed in as an argument. The one passed in by argument is the one that overwrites. Given these parameters, you will want to get the API responses as a string and then deserialize with JObject.Parse(string)
Also note that prior to the merge you can probably run some validation logic on these parsed objects to suit your needs
You should probably also explore the JsonMergeSettings object that is shown in the example, as it may include some finer grained options that you may want for your merge
I am working on JArray in .NET CORE and I am getting random structure of this one specific key, hence getting different error. I need to know if JArray has specific child Array and if Child JArray have specific key pair (NOT VALUE) i.e. value{ "Id":""} one of error is following;
Accessed JArray values with invalid key value: "id". Int32 array index expected.
at Newtonsoft.Json.Linq.JArray.get_Item(Object key) at
the standard structure I am expecting is as following;
{[value, [
{
"id": "7ef82869-e235-69a2-f81e-3a9664e89bc4",
"value": ""
}
]]}
sometime I get as, meaning throw null error where I am trying to map Id.
{[value, [
{
"value": ""
}
]]}
and some Time I don't get this property at all
I am trying following check to cover all scenario but Its not really working.
code
if (answerItems.value != null && answerItems.value.HasValues && answerItems.value["id"]!=null)
{
I received some constructive criticism on the brevity of my answer so I figured I would elaborate to help you through your issue.
First, let's take a look at your JSON. In short, it isn't valid. In fact, it isn't even close to valid JSON. I can only assume you meant something like this:
{
"values" : [{ "id" : "7ef82869-e235-69a2-f81e-3a9664e89bc4", "value": "" }]
}
I would suggest that anytime you are trying to parse data like this and you run into issues you start trouble shooting by validating the data itself. I like to use JSONLint for this.
Next, it is difficult from your example code to tell exactly what you are trying to do. I can only guess that you are attempting to use the dynamic object method of parsing and working with the data. A downside to this method is it is difficult to validate your data before you work with it.
Instead, I would use the Newtonsoft.Json.Linq.JObject.Parse method. This gives you some tools for working with and validating the information. Below I have included a very simple example of how this would be done.
using System;
using Newtonsoft.Json.Linq;
public class Program
{
public static void Main()
{
string json = "{ \"values\": [{ \"id\": \"7ef82869-e235-69a2-f81e-3a9664e89bc4\", \"value\": \"\" }] }";
JObject obj = JObject.Parse(json);
// Check to see if we got our value array
if (obj.ContainsKey("values")) {
JArray values = (JArray)obj["values"];
// Do we have any values in our array?
if (values.Count > 0) {
JObject firstItem = (JObject)values[0];
// We check to see if we have an ID parameter
if (firstItem.ContainsKey("id")) {
Console.WriteLine(firstItem["id"]);
}
}
}
}
}
As I mentioned in my original post, I would strongly recommend reviewing the Newtonsoft.Json documentation.
I'm just an amateur in C# programming. Now i have a JSON data that looks like following
{
type: "xxx",
width: "xxx",
dataSource: {
"chart": {
"caption": "xxx"
},
"data": [
{},
{}
]
}
}
I'm having the whole data as escaped string. now after Unescape when I'm using JavaScriptSerializer as follows
var data = ser.Deserialize<Dictionary<String, Object>>(chartData);
I'm able to get the "type", "width" as
data["width"]
data["type"]
Now I have to get the value of "caption". Any suggestion how to get that, I believe the dictionary structure need to be changed but I'm stacked for my lack of knowledge in C#
If you know the object's scheme you man want to create a class that represents in and then deserialize the json into it:
YourKnownClass obj = JsonConvert.DeserializeObject<YourKnownClass>(json);
Console.WriteLine(obj.dataSource.chart.caption.Value);
Another option is by using a dynamic type (There is no good reason using a dynamic object if you know the schema and can create a matching C# class. This has a performance impact as well):
dynamic obj = JsonConvert.DeserializeObject<dynamic>(json);
Console.WriteLine(obj.dataSource.chart.caption.Value);
BTW, In this example i'm using json.net which is a popular library.
I've got a method which takes a IList<Person> and returns an IEnumberable as so:
internal static IEnumerable<Dictionary<string, string>> GetPersonsPerSite(IList<Person> Data)
{
//Implementation ...
}
and I'm trying to create a mock object of IList<Person> so I can test this method.
Using Moq I have written the following:
var mockObjects = new Mock<IList<Person>>();
mockObjects.Setup(x => x[0]).Returns(new Person()
{
SITE_ID = "test",
MPAN = "test",
ADDLINE1 = "test",
ADDLINE2 = "test",
ADDRESS_LINE_1 = "test",
ADDRESS_LINE_2 = "test"
});
However when I come to use the object the IEnumerable returned is aways throwing exception Object reference not set to an instance of an object.
I'm brand new to Moq, and I'm pretty sure I'm missing a fundamental concept here, however I've successfully being able to throw exceptions and modifiy outputs with other mock objects.
I'd appreciate if someone could point me in the right direction.
Don't mock the IList. You don't need to, unless there's something specific your looking to check.
Instead just keep your test simple and do something like this:
var testData = new List<Person>(){new Person()
{
SITE_ID = "test",
MPAN = "test",
ADDLINE1 = "test",
ADDLINE2 = "test",
ADDRESS_LINE_1 = "test",
ADDRESS_LINE_2 = "test"
}};
var result = GetPersonsePerSite(testData);
The code you have got there looks fine and does work for me. Can you expand with an example of where you actually consume the mockObjects.Object and find it null?
Also, do you really need to mock your IList<Person>?
If you are just using it to supply test data to the method under test, just use a concrete list - there is nothing gained by using a mock for this.
Of course, you may be mocking it so you can verify certain actions are taken on it (methods called, properties accessed, etc) - in which case that is different.
I'm having problems passing an array parameter to my .ashx handler. Querystring parameters work fine, but I don't know how to access the array from within the ashx file.
My array is a list of strings called list. This is how I call the getJSON method:
jQuery.getJSON('Handlers/AccessoryUpdateHandler.ashx?action=updateselection&a=' + a_sku, function (list) {
//...
});
In AccessoryUpdateHandler.ashx I can get the querystring parameter using context.Request.QueryString["a"];
But how do I get the array data? I've looked at the Request.QueryString object but there's nothing there that looks like my array.
If there's a better way of doing this I'd also be interested to know.
Perhaps you shouldn't rely on QueryString to pass the kind of data. I would advice you to use "POST" method instead. In either case, using the approach you are using, you wont be able to pass the data as an array. Convert the array into a string. A utility like stringify() can come in handy here if you dont want to convert the array into a string manually. When you extract the string from the Request.QueryString or Request.Form (in case you use post) in the handler, you can easily use JavaScriptSerializer to deserialize using a simple C# class that has a schema similar to your json array.
Edited: Illustration
An array like:
var ary = [{ "id": "1", "name": "Mark" }, { "id": "2", "name": "John"}];
can be converted to a string like:
var aryS = "[{\"id\":\"1\",\"name\":\"Mark\"},{\"id\":\"1\",\"name\":\"Mark\"}]";
then, your QueryString can be constructed as:
jQuery.getJSON('Handlers/AccessoryUpdateHandler.ashx?action=updateselection&a=' + aryS, function (list) {
//...
});
when you go to your handler code, you can have a simple class to help you deserialize the data:
class Rec
{
public int Id { get; set; }
public string Name { get; set; }
}
with that in place, the last step to deserialize is:
string s = context.Request.QueryString["a"]; // HttpContext context
var jserializer = new JavaScriptSerializer();
var ary = jserializer.Deserialize<Rec[]>(s);
Note you have to use Rec[] in the Deserialize function since you are deserializing into an array. ary will be an array of Rec with all your data from your javascript array. You need to reference System.Web.Extensions to use JavaScriptSerializer
EDIT:
I thought you were talking about an array of objects. If its just an array of *long*s, the following lines should be sufficient:
string s = context.Request.QueryString["a"]; // HttpContext context
var jserializer = new JavaScriptSerializer();
var ary = jserializer.Deserialize<long[]>(s);
and you dont need to create a class. you would only need that if you had a array of json objects
I don't think your need for passing arrays should dictate whether you use get or post as others suggest.
Using get, the most idiomatic ways is using the same parameter multiple times. e.g.
Handlers/AccessoryUpdateHandler.ashx?a=1&a=2&a=55
In fact in most frameworks(.NET being the exception) when you get a parameter from url you get a array return(often with one item)
My suggestion is you parse context.Request.RawUrl