I am trying to figure out how to loop through multiple documents, fetched in a firebase cloud function, in Unity, but not sure how?
Here is my cloud script:
exports.getUserData = functions.https.onCall(async(data, context) => {
if (!context.auth) {
throw new functions.HttpsError(
'unauthenticated',
'only autehnticated users can make requests!'
);
}
const userData = await admin.firestore().collection('users').get(data.userid);
const myGroupMemberships = await admin.firestore().collection('groupMembers').where("playerId", "==", data.userid).get();
var myGroups = [];
myGroupMemberships.forEach(group => {
const thisGroup = admin.firestore().collection('groups').get(group.groupId);
myGroups.push(thisGroup);
})
return { "groups": myGroups };
});
As you can see, I first have to find the memberships for the user in "groupMembers", then loop through the records to get the group documents. I am not sure I am sending them correct, but thought that putting them in an array would be easies!?! Not sure thats the case.
In my Unity script I try to get them like this:
var func = FirebaseManager.instance.functions.GetHttpsCallable("getUserData");
var data = new Dictionary<string, object>();
data["userid"] = userId;
var task = func.CallAsync(data).ContinueWithOnMainThread((callTask) => {
if (callTask.IsFaulted)
{
// The function unexpectedly failed.
GA.Log("FAILED!");
GA.Log(string.Format(" Error: {0}", callTask.Exception));
return;
}
var result = (IDictionary)callTask.Result.Data;
// The function succeeded.
GA.Log(string.Format("Whats in the groups: {0}", result["groups"]));
List<Group> theGroups = result["groups"] as List<Group>;
foreach (Group thisGroup in theGroups)
{
GA.Log("GroupName: " + thisGroup.groupName);
}
});
yield return new WaitUntil(() => task.IsCompleted);
The log: Whats in the groups returns this: System.Collections.Generic.List`1[System.Object]
I do not get any logs on the "Groupname" inside the foreach loop!
Where am going wrong and how should I accomplish this?
Any help is appreciated and thanks in advance :-)
Related
I am importing an old database into a new one. The new database requires each record to have a type when imported. The first record does not have a type, therefore I would like to discard it from the import. I am unsure how to write this in C#
At the moment I have
`public async Task RunImport()
` {
_logger.LogInformation(DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss") + " | BATHWORKS IMPORT : Start Import");
//BATHWORKS COMPONENT
string type = null;
IEnumerable<BathworksItem> bathworksItem = await GetBathworksItem();
IEnumerable<BathworksItemDto> BathworksItem = await GetBathworksPortalItems();
IEnumerable<BathworksItem> missingBathworksPortalItems = bathworksItems.Where(x => !bathworksportalItem.Any(y => y.Serial == x.Name));
foreach (BathworksItem missingBathworksPortalItem in bathworksItems)
if (!missingBathworksPortalItem.IsNullOrEmpty(type))
{
BathworksItemDto bathworksItemDto = new BathworksItemDto();
bathworksItemDto.ItemNumber = missingBathworksPortalItem.ItemNumber;
bathworksItemDto.Stock = missingBathworksPortalItem.Stock;
bathworksItemDto.Availbility = missingBathworksPortalItem.Availbility;
bathworksItemDto.Company = missingBathworksPortalItem.Company;
bathworksItemDto.Lastupdate = missingBathworksPortalItem.Lastupdate;
bathworksItemDto.Type = missingBathworksPortalItem.Type;
bathworksItemDto.Name = missingBathworksPortalItem.Name;
await _bathworksItem.InsertItem(bathworksItemDto);
}`
I have tried the above and it does not quite do what I was expecting as it does not discard the rogue record, instead I recieve a error 500.
I've been working on C# app to amend the ipaddress/s of a Named Location in conditional access in AAD.
I can authenticate and return the request collection. For whatever reason I cant access the isTrusted property or the ipRanges odata.
I can see the properties and the vales when I run through in debug, but cant output them.
I think its something to do with the list type, I'm using Microsoft.Graph.NamedLocation, there is Microsoft.Graph.IpNamedLocation type available but it can be converted from Microsoft.Graph.NamedLocation, which the api call makes.
The image shows what's available during runtime.
Code Below:
private static async Task GetnamedLocations(IConfidentialClientApplication app, string[] scopes)
{
GraphServiceClient graphServiceClient = GetAuthenticatedGraphClient(app, scopes);
var namedlocationsList = new List<Microsoft.Graph.NamedLocation>();
var namedLocations = await graphServiceClient.Identity.ConditionalAccess.NamedLocations
.Request()
.Filter("isof('microsoft.graph.ipNamedLocation')")
.GetAsync();
// var ipNamedLocations = new List<Microsoft.Graph.IpNamedLocation>();
namedlocationsList.AddRange(namedLocations.CurrentPage);
foreach (var namedLocation in namedlocationsList)
{
Console.WriteLine(namedLocation.Id + namedLocation.DisplayName + namedLocation.ODataType + namedLocation);
if (namedLocation.ODataType == "#microsoft.graph.ipNamedLocation")
{
Console.WriteLine("Write out all the properties");
}
}
Console.WriteLine(($"Named location: {namedLocations}"));
}
Any pointers gratefully received, I'm not a C# developer so be gentle :-)
You need to cast namedLocation to IpNamedLocation type.
foreach (var namedLocation in namedlocationsList)
{
Console.WriteLine(namedLocation.Id + namedLocation.DisplayName + namedLocation.ODataType + namedLocation);
if (namedLocation is IpNamedLocation ipNamedLocation)
{
var isTrusted = ipNamedLocation.IsTrusted;
var ipRanges = ipNamedLocation.IpRanges;
if (ipRanges is IEnumerable<IPv4CidrRange> ipv4cidrRanges)
{
foreach(var ipv4cidrRange in ipv4cidrRanges)
{
Console.WriteLine($"{ipv4cidrRange.CidrAddress}");
}
}
Console.WriteLine("Write out all the properties");
}
}
I couldn't get the updated answer to work, it still didn't evaluate the if statement to true, after a bit of googling and trying different options, the following returns the IP address, not sure if its the right way to go about it but it works.
var ipv4CidrRanges = ipRanges.Cast<IPv4CidrRange>().ToList();
foreach (var ipv4CidrRange in ipv4CidrRanges)
{
Console.WriteLine(ipv4CidrRange.CidrAddress);
}
Many thanks to user2250152 who solved the first conundrum for me.
I have the following function that allows me to make REST request via this function:
static Observation GetData(string baseUrl, string provider, string key, string sensor)
{
var client = new RestClient(String.Format("{0}/data/{1}/{2}", baseUrl, provider, sensor));
client.Timeout = -1;
var request = new RestRequest(Method.GET);
request.AddHeader("IDENTITY_KEY", key);
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
var observationsModel = JsonSerializer.Deserialize<SentiloResponse>(response.Content, options);
Console.WriteLine("This is observationsModel:");
Console.WriteLine(observationsModel);
Console.WriteLine("This is the outcome of GetData:");
Console.WriteLine(observationsModel.Observations.FirstOrDefault());
return observationsModel.Observations.FirstOrDefault();
}
The outcome from it is the following (see screenshot):
Now, from this point
In the next section I call GetData, I would like to select Value and Timestamp Variables to do other tasks, but I'm unable to (my attempts are in lines where myTest and myTest_2 are being declared):
static void Main(string[] args)
{
configuration = JsonSerializer.Deserialize<SentiloConfig>(File.ReadAllText("configuration.json"), options);
Console.WriteLine("Configuration Loaded");
foreach(var componentMapping in configuration.ComponentMappings)
{
var inputComponent = componentMapping.InputComponent;
Console.WriteLine("Getting data");
var sensorsContent = inputComponent.Sensors.AsParallel().Select(s =>
new SensorContent{
Sensor = GetSensorString(s.SensorName),
Observations = new List<Observation>() {
GetData(
inputComponent.ServerUrl,
inputComponent.Provider,
inputComponent.Token,
GetSensorString(s.SensorName)
)
}
}
).Where(s => s.Observations.First() != null).ToList();
var myTest = sensorsContent.Select(s => s.Observations.First().Value).ToList();
var myTest_2 = sensorsContent.Select(s => s.Observations.First().Value.ToList());
Console.WriteLine(myTest.ToString());
Console.WriteLine(myTest_2);
Console.WriteLine("data retrieved");
if (!sensorsContent.Any())
{
Console.WriteLine("No sensor data for component {0} with sensors: {1}, check configuration", inputComponent.ComponentName, string.Join(",", inputComponent.Sensors.Select(s => s.SensorName)));
continue;
}
var sensorRequest = new SentiloPutRequest { Sensors = sensorsContent };
}
System.Threading.Thread.Sleep(configuration.SendTime*1000);
}
But the outcome of myTest and myTest_2 are the following:
System.Collections.Generic.List1[System.String] System.Linq.Enumerable+SelectListIterator2[SentiloSpoofer.SensorContent,System.Collections.Generic.List`1[System.Char]]
I'm thinking perhaps is best to call GetData outside of the Lambda and bypass these issues, but if I wanted to retrieve this data, what could be a good way to do so?
It's just the way you are writing to the console. Use string.Join or a foreach.
Essentially, you are trying to magic the values out of a list. Technically List<T> doesn't have an override of ToString() that knows how you want to format it. It's up to you. So it just returns the type name (which is what you are seeing).
Try instead:
foreach(var value in myTest)
Console.WriteLine(value);
// or
Console.WriteLine(string.Join(",",myTest));
You are trying to access a List as a String.
The values are there if you wanna show it in your console, just use an aggregate in your List.
Example:
var myTestString = myTest.Select(i => i).Aggregate((i, j) => i + "," + j);
Console.WriteLine(myTestString)
// Or
myTest.ForEach(x => Console.WriteLine(x));
The method is supposed to receive data from a server, check if new tokens have been added, and if there are, add them to the database. If the token already exists, update its status but don't add a new row in the table. This is the code I've written so far.
IEnumerable<Token> serverTokens = JsonConvert.DeserializeObject<IEnumerable<Token>>
(server.GetTokens().Content);
IEnumerable<Token> dbTokens = _tokenService.GetAllTokens();
foreach (var token in serverTokens)
{
var dbToken = dbTokens.Where(x => x.Symbol == token.Symbol).FirstOrDefault();
if (dbToken != null)
{
Token editedToken = dbToken;
editedToken.UpdatedOn = DateTime.Now;
editedToken.Active = token.Active;
_tokenService.AddToken(editedToken);
}
else
{
token.UpdatedOn = DateTime.Now;
_tokenService.AddToken(token);
}
}
dbContext.SaveChanges();
The AddToken method is just a simple AddOrUpdate operation.
public void AddToken(Token token)
{
_dbContext.Tokens.AddOrUpdate(token);
//_dbContext.SaveChanges();
}
Now, this code does what it's supposed to, however it's extremely slow. How would I go about optimizing it?
dbTokens.Where(x => x.Symbol == token.Symbol) is IEnumerable
So he will load it each time you call it on the loop.
Store in in a list before the loop
List<Token> dbTokens = _tokenService.GetAllTokens().ToList()
I'm trying to get some working C# code of the results being parsed from FB.GetDeepLinks()
Here's the Facebook docs
Unfortunately their example code always returns -1.
The results I'm getting for the deeplink look like this:
{APPID}://authorize/#access_token={ACCESS_TOKEN}&expires_in=3600&target_url=http%3A%2F%2Fwww.facebook.com%2Fappcenter%2F{APPID}%3Frequest_ids%3D291251114389454%252C297829280380986%26ref%3Dnotif%26app_request_type%3Duser_to_user
Any help at all would be tremendously appreciated as this is just about my last roadblock from completing this project.
Thanks!
Edit: to be specific, I'm looking for the ability to extract the "request_ids" data from the response.
Try this.. was working for me a while back
void MyCallback(FBResult result)
{
if (result != null)
{
var response = DeserializeResponse(result.Text);
foreach(object c in response)
{
var jsonObject = c as Dictionary<string, object>;
string[] ids = jsonObject["id"].ToString().Split('_');
FB.API (string.Format ("/{0}", ids[0]), Facebook.HttpMethod.GET, MyCallbackGet);
}
}
}
public List<object> DeserializeResponse (string response)
{
var responseObject = Json.Deserialize (response) as Dictionary<string, object>;
object scoresh;
var scores = new List<object> ();
if (responseObject.TryGetValue ("data", out scoresh))
{
scores = (List<object>)scoresh;
}
return scores;
}