Reading JSON response as a List of objects - c#

I'm trying to get an object List from cors API but all of the List entries are null.
I succeeded in obtaining the List (list type and length are ok).
List<PluginModelDB> result;
using (HttpResponseMessage response = await ApiBroker.ApiClient.GetAsync(""))
{
if (response.IsSuccessStatusCode)
{
result = await response.Content.ReadAsAsync<List<PluginModelDB>>();
}
else
{
throw new Exception(response.ReasonPhrase);
}
}
HomeViewModel.PluginList = new List<PluginModelDB>();
foreach (var p in result)
{
HomeViewModel.PluginList.Add(new PluginModelDB { ID = p.ID, Name = p.Name, Description = p.Description});
}

Try to read it as string first, so don't deserialize it immediately. Output that string to Console or a simple text file and see if you can track you items there. If not, the problem is at the API, its returning empty objects.

It seems that your model is not corresponds to received JSON. You can check you model via http://json2csharp.com/

Related

Get element by key with Firebase in c#

I am coming to a problem where I have a guid style schema in my firebase database, which I want to display a text that is DisplayText, but for some reason my code is not working. I am using a FirebaseDatabase.Net Wrapper. How can I map it in order to read from the database properly using a guid way schema? thanks for the help.
Code:
private async Task ShowQuestion()
{
var firebase = new
FirebaseClient("https://PROJECT_URL.firebaseio.com/");
var dinos = await firebase
.Child("Questions")
.OrderByKey()
.StartAt("DisplayText")
.LimitToFirst(1)
.OnceAsync<GameController>();
foreach (var dino in dinos)
{
Console.WriteLine(dinos);
}
I tried doing:
string page = "https://PROJECT_URL.firebaseio.com/Questions/DisplayText.json?orderBy"DisplayText"&limitToFirst=1";
using (HttpClient client = new HttpClient())
using (HttpResponseMessage response = await client.GetAsync(page))
using (HttpContent content = response.Content)
{
// Reading the string.
string result = await content.ReadAsStringAsync();
Console.WriteLine(result);
// Getting a reference to the text component.
questionDisplayText = GetComponent<Text>();
questionDisplayText.text = result.ToString();
questionDisplayText.text = result.Trim(new char[] {'"'});
}
Firebase queries take a two-step approach:
You order the child nodes on their key, their value, or the value of a property.
You then filter on values of the thing you ordered on.
Since you order by key, the filtering operations like StartAt() compare the key to the value you passed. And since there is no key DisplayText, there are no results.
If you want to read the first question, you shouldn't use a startAt().
FirebaseClient("https://PROJECT_URL.firebaseio.com/");
var dinos = await firebase
.Child("Questions")
.OrderByKey()
.LimitToFirst(1)
If you want to return the results ordered by the value of their DisplayText property, it'd be something like this:
FirebaseClient("https://PROJECT_URL.firebaseio.com/");
var dinos = await firebase
.Child("Questions")
.OrderByChild("DisplayText")
.LimitToFirst(1)
Since you indicated that you want to use the REST API, here's an example of how to do that:
https://stackoverflow.firebaseio.com/59384124.json?orderBy="DisplayText"&startAt="How"
If you want to embed this string in your code, you have a few options. The main ones:
string page = "https://PROJECT_URL.firebaseio.com/Questions/DisplayText.json?orderBy=\"DisplayText\"&startAt=\"How\"&limitToFirst=1";
Or
string page = #"https://PROJECT_URL.firebaseio.com/Questions/DisplayText.json?orderBy=""DisplayText""&startAt=""How""&limitToFirst=1";
And don't forget: in order to be able to filter on the server, you'll need to define an index in your security rules. In my case I did so with:
"59384124": { ".indexOn": "DisplayText" },
Also see:
The documentation for the Firebase REST API
This blog post on embedding quotes in C# strings

Why do I get the "reference not set to an instance of an object?

I am working with the new CosmosDB SDK v3 https://learn.microsoft.com/en-us/azure/cosmos-db/sql-api-sdk-dotnet-standard and a very simple insert, I have verified all the objects are indeed not null and have reasonable values but I still get the error message:
[1/12/2019 10:35:04] System.Private.CoreLib: Exception while executing function: HAPI_HM_Seasons. Microsoft.Azure.Cosmos.Direct: Object reference not set to an instance of an object.
I dont see why this is I must be missing something really basic here but I cant put my finger on it.
The code is as below:
List<SeasonInformation> seasonInformationList = new List<SeasonInformation>();
foreach(JObject document in listOfSeasons)
{
SeasonInformation seasonInformation = new SeasonInformation
{
id = Guid.NewGuid().ToString(),
Brand = brand,
IntegrationSource = source,
DocumentType = Enums.DocumentType.Season,
UpdatedBy = "HAPI_HM_Seasons",
UpdatedDate = DateTime.Now.ToString(),
UpdatedDateUtc = string.Format("{0:yyyy-MM-ddTHH:mm:ss.FFFZ}", DateTime.UtcNow),
OriginalData = document
};
seasonInformationList.Add(seasonInformation);
}
database = cosmosClient.GetDatabase(cosmosDBName);
container = database.GetContainer(cosmosDBCollectionNameRawData);
log.LogInformation(string.Format("HAPI_HM_Seasons BASIC setup done at {0:yyyy-MM-ddTHH:mm:ss.FFFZ}", DateTime.UtcNow));
log.LogInformation(string.Format("HAPI_HM_Seasons import {1} items BEGIN at {0:yyyy-MM-ddTHH:mm:ss.FFFZ}", DateTime.UtcNow, seasonInformationList.Count));
foreach(var season in seasonInformationList)
{
ItemResponse<SeasonInformation> response = await container.CreateItemAsync(season);
}
I have verified that the List is populated and that the season variable in the loop contains the correct data so I am a bit stuck here.
The exception happens in the last foreach loop where I try CreateItemAsync into CosmosDB
As a best practice, you need to use Async method with await in all the Cosmosdb methods just to make sure that they are getting executed and you get the response,
and modify your CreateItemAsync as follows,
ItemResponse<SeasonInformation> response = await container.CreateItemAsync(season, new PartitionKey(season.whatever));
Here is the Sample Repository

Return or modify .json file in NancyFX

I am trying to build a simple API with NancyFX, hosted with ASP.NET. When http://myapp/api/get is called, it should return some JSON which is stored in a file called "data.json", which is stored on the root level along with the main module. Also, http://myapp/api/set should set the contents of the JSON file.
My initial approach was this:
Get["/api/get"] = _ =>
{
string allText = System.IO.File.ReadAllText(#"c:\data.json");
object jsonObject = JsonConvert.DeserializeObject(allText);
return jsonObject;
}
Post["/api/set"] = parameters =>
{
string json = JsonConvert.SerializeObject(parameters);
System.IO.File.WriteAllText(#"c:\data.json", json);
return HttpStatusCode.OK;
}
However, the program can't find the file in runtime. After reading some answers in here, i tried doing the following (which didn't work either):
Get["/api/get"] = _ =>
{
return new GenericFileResponse(Directory.GetCurrentDirectory() + #"\sitefiles\data.json", "application/json");
}
The answers i found were from 2011, so i suspect that's why they don't work. What is the updated way to solve this?
After working a bit more, i have found a solution. You have to make a class model representing the data you are going to recieve, in this case the model is called InfoModel. Then i coded the Get and Post as such:
Get["/api/get"] = _ =>
{
DefaultRootPathProvider pathProvider = new DefaultRootPathProvider();
return new GenericFileResponse(pathProvider.GetRootPath() + "data.json", "application/json");
};
Post["/api/set"] = parameters =>
{
DefaultRootPathProvider pathProvider = new DefaultRootPathProvider();
var model = this.Bind<InfoModel>();
string json = JsonConvert.SerializeObject(model);
File.WriteAllText(pathProvider.GetRootPath() + "data.json", json);
return HttpStatusCode.OK;
};

C# Extracting data from Json or DataSets - Porting from Python (Json to Dict)

I have the following Python script which I need to port to C#. This gets a JSON response from a URL and then pops it into a dictionary. Then it checks for the data next_page and if there is data (it's not empty) it then returns true. Underneath I'll paste the C# code I have but I'm really struggling to do the final part. I don't know and I certainly don't want to understand the data in the JSON response, I just want to know if the field next_page is there.
# Gets JSON response
response = requests.get(url, auth=(user, pwd))
if response.status_code != 200:
print('Status:', response.status_code, 'Problem with the request. Exiting.')
exit()
data = response.json()
if(data['next_page']):
return True
else:
return False
So this is the c# code I've got:
using Newtonsoft.Json;
string response = "";
using (WebClient client = new WebClient())
{
client.UseDefaultCredentials = true;
client.Credentials = new NetworkCredential(user, password);
try
{
response = client.DownloadString(url);
} catch (Exception e)
{
throw e;
}
}
XmlDocument xml = JsonConvert.DeserializeXmlNode(json, "RootObject");
XmlReader xr = new XmlNodeReader(xml);
DataSet ds = new DataSet("Json Data");
ds.ReadXml(xr);
From what I've seen on the web DataSets work best when you know what the data inside of it is. I just want to know if there is a field called next_page and if there is, is it empty or does it have data. I'm just struggling to get anything out of the DataSet.
You will want to include the JSON.net nuget package (http://james.newtonking.com/json) this lets you deserialize the JSON response into a dictionary (or preferably a new class) allowing you to access the response.
eg add this into your try catch after including the library
var dict = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(response);
Alternativly you could create a new class that represents the expected JSON and deserialize into that
public class ResponseObject
{
public string next_page { get; set; }
}
var responseResult = Newtonsoft.Json.JsonConvert.DeserializeObject<ResponseObject>(response);

How to get an specific header value from the HttpResponseMessage

I'm making an HTTP call. My response contains a session code X-BB-SESSION in the header section of the HttpResponseMessage object. How do I get that specific header value?
I am using a foreach statement to iterate through all the headers (MSDN link). However the compiler keeps saying that it cannot be done:
foreach statement cannot operate on variables of type
System.net.http.headers.cachecontrolheadervalue because
'System.net.http.headers.cachecontrolheadervalue' doesn't contain
a public definition for 'GetEnumerator'
This is the code I'm trying:
//Connection code to BaasBox
HttpResponseMessage response = await client.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead);
if (response.IsSuccessStatusCode)
{
//get the headers
HttpResponseHeaders responseHeadersCollection = response.Headers;
foreach (var value in responseHeadersCollection.CacheControl) --> HERE
{
string sTemp = String.Format("CacheControl {0}={1}", value.Name, value.Value);
} else
{
Console.WriteLine("X-BB-SESSION: NOT Found");
}
The header content from where I'm trying to get the value (X-BB-SESSION value) is something like:
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: X-Requested-With
X-BB-SESSION: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
You should be able to use the TryGetValues method.
HttpHeaders headers = response.Headers;
IEnumerable<string> values;
if (headers.TryGetValues("X-BB-SESSION", out values))
{
string session = values.First();
}
Using Linq aswell, this is how I solved it.
string operationLocation = response.Headers.GetValues("Operation-Location").FirstOrDefault();
I think it's clean and not too long.
Though Sam's answer is correct. It can be somewhat simplified, and avoid the unneeded variable.
IEnumerable<string> values;
string session = string.Empty;
if (response.Headers.TryGetValues("X-BB-SESSION", out values))
{
session = values.FirstOrDefault();
}
Or, using a single statement with a ternary operator (as commented by #SergeySlepov):
string session = response.Headers.TryGetValues("X-BB-SESSION", out var values) ? values.FirstOrDefault() : null;
If someone like method-based queries then you can try:
var responseValue = response.Headers.FirstOrDefault(i=>i.Key=="X-BB-SESSION").Value.FirstOrDefault();
You are trying to enumerate one header (CacheControl) instead of all the headers, which is strange. To see all the headers, use
foreach (var value in responseHeadersCollection)
{
Debug.WriteLine("CacheControl {0}={1}", value.Name, value.Value);
}
to get one specific header, convert the Headers to a dictionary and then get then one you want
Debug.WriteLine(response.Headers.ToDictionary(l=>l.Key,k=>k.Value)["X-BB-SESSION"]);
This will throw an exception if the header is not in the dictionary so you better check it using ContainsKey first
Below Code Block Gives A formatted view of Response Headers
WebRequest request = WebRequest.Create("https://-------.com");
WebResponse response = request.GetResponse();
foreach (var headerItem in response.Headers)
{
IEnumerable<string> values;
string HeaderItemValue="";
values = response.Headers.GetValues(headerItem.ToString());
foreach (var valueItem in values)
{
HeaderItemValue = HeaderItemValue + valueItem + ";";
}
Console.WriteLine(headerItem + " : " + HeaderItemValue);
}

Categories