I am doing some work with C#, AJAX and JSON and am getting a Self referencing loop error. I am managing to get around this using the JsonIgnore attribute, but I was wondering if someone can give me a proper explanation as to what is actually happening here.
Many thanks.
Dave
We don't get much detail on your problem, but it's probably exactly what you're describing: a loop of self-reference, or a circular chain of references.
Say you've got a variable of the type User that has a property public UserImage Image. Now, say the type UserImage has a property User that references back to the user.
In your .NET code, it's just that. myImage.User gives yo uthe user, myUser.Image gives you the image. But imagine you want to serialize myUser (into JSON, say). Then you have to cycle every property of User and serialize that, recursively. The serializer would start off like this
{ "ID": 1, "Image": { ...
now it has to serialize the user image. And remember UserImage has the variable "User".
{ "ID": 1, "Image": { "Path": "image.src", "User": {
but the user is the very same user that we're trying to reference
{ "ID": 1, "Image": { "Path": "image.src", "User": { "ID": 1, "Image":
now we have to serialize the image for that user, but that, again, is the same image as before:
{
"ID": 1,
"Image": {
"Path": "image.src",
"User": {
"ID": 1,
"Image": {
"Path": "image.src",
"User": {
"ID": 1,
"Image": {
"Path": "image.src",
"User": {
"ID": 1,
"Image": {
"Path": "image.src",
"User":
so we never reach an end product if we're constantly serializing a circular reference.
Related
I have a semi-large project that has been using nlog, and throughout I re-used alot of field names for different datatypes. I started to send my logs (including all log properties/fields) to ElasticSearch, and now its starting to haunt me. I noticed if ElasticSearch is unable to convert a field to it's dataType it will just drop the log entirely. The dynamic index mapping is deciding the dataType depending on what it's seen first.
Is there anyway I can tell the index to use a default dataType like string?
PS; The Instance is cloud hosted, I access it through Kibana, and I have no Idea where to find a log that tells me if/when it drops logs for parsing errors.
Edit
Index Mapping
PUT /indexName
{
"mappings": {
"properties": {
"#domain": {
"type": "keyword"
},
"#logTarget": {
"type": "keyword"
},
"#logger": {
"type": "keyword"
},
"#memUsage": {
"type": "long"
},
"#processID": {
"type": "integer"
},
"#serviceGUID": {
"type": "keyword"
},
"#timestamp": {
"type": "date"
},
"level": {
"type": "keyword"
},
"message": {
"type": "text"
}
}
}
}
Unfortunately I don't know the api for pushing logs to elastic but here are some examples of what they might look like. Theses aren't the best examples but they show the overlapping/re-use of field names.
Example 1:
//NLog structured log
logger.LogInfo("That Lady has {count} cats", 5);
//JSON Object
{
"#domain": "Service1",
"#logTarget": "None",
"#logger": "AppName.Program.Main",
"#memUsage": 100,
"#processID": 17000,
"#serviceGUID": 0,
"level": "INFO",
"message": "That Lady has 5 cats",
"count": 5,
}
Example 2:
//NLog structured log
int count = 3;
logger.LogInfo("Loaded {count}", count + " dogs");
//JSON Object
{
"#domain": "Service1",
"#logTarget": "None",
"#logger": "AppName.Program.Main",
"#memUsage": 100,
"#processID": 17000,
"#serviceGUID": 0,
"level": "INFO",
"message": "Loaded "5 dogs"",
"count": 5,
}
Example 3:
//NLog structured log
object count = nil;
logger.LogInfo("Value is {count}", count);
//JSON Object
{
"#domain": "Service1",
"#logTarget": "None",
"#logger": "AppName.Program.Main",
"#memUsage": 100,
"#processID": 17000,
"#serviceGUID": 0,
"level": "INFO",
"message": "Loaded "5 dogs"",
"count": 5,
}
I'm currently working on an app in Xamarin.Android with one of the features being that, upon clicking a button, the user is taken to a specific calendar event in the Microsoft Outlook app. Thus far I've been using the Microsoft Graph API to get the event items and I've succeeded in opening the Outlook app to the calendar or opening Outlook with an error message saying "Event could not be opened" but I haven't gotten both behaviors to happen, nor the specific event item to open. The way I open the Outlook app is by calling the device's default browser with an Outlook uri scheme. Both are provided below
browserLaunch("ms-outlook://events/open?account={my.account#email.com}&restid={id}");
private async void browserLaunch( string uri ) {
await Browser.OpenAsync(uri, BrowserLaunchMode.SystemPreferred);
}
The exact call I've been making to the Graphs API is as follows
https://graph.microsoft.com/v1.0/me/calendarview?startdatetime=2020-01-23T15:54:40.377Z&enddatetime=2020-01-30T15:54:40.377Z
which returns a list of even items with the following scheme:
"#odata.etag": "string",
"id": "string",
"createdDateTime": "20##-##-##T##:##:##.######Z",
"lastModifiedDateTime": "20##-##-##T#3:##:##.#######Z",
"changeKey": "string",
"categories": [],
"originalStartTimeZone": "Central Standard Time",
"originalEndTimeZone": "Central Standard Time",
"iCalUId": "string",
"reminderMinutesBeforeStart": int,
"isReminderOn": true/false,
"hasAttachments": true/false,
"subject": "string",
"bodyPreview": "string",
"importance": "string",
"sensitivity": "string",
"isAllDay": true/false,
"isCancelled": true/false,
"isOrganizer": true/true,
"responseRequested": true/false,
"seriesMasterId": null,
"showAs": "string",
"type": "string",
"webLink": "https://outlook.office365.com/owa/?itemid={id}&exvsurl={int}&path=/calendar/item",
"onlineMeetingUrl": null,
"recurrence": null,
"responseStatus": {
"response": "none",
"time": "0001-01-01T00:00:00Z"
},
"body": {
"contentType": "html",
"content": "string"
},
"start": {
"dateTime": "20##-##-##T##:##:##.#######",
"timeZone": "UTC"
},
"end": {
"dateTime": "20##-##-##T##:##:##.#######",
"timeZone": "UTC"
},
"location": {
"displayName": "string",
"locationType": "string",
"uniqueId": "string",
"uniqueIdType": "stirng"
},
"locations": [
{
"displayName": "string",
"locationType": "string",
"uniqueId": "hexstrin-hexs-hexs-hexs-hexstringhex",
"uniqueIdType": "string"
}
],
"attendees": [
{
"type": "string",
"status": {
"response": "string",
"time": "0001-01-01T00:00:00Z"
},
"emailAddress": {
"name": "string",
"address": "my.account#email.com"
}
}
],
"organizer": {
"emailAddress": {
"name": "string",
"address": "my.account#email.com"
}
}
I've also tried different ids that are given by the graphs API for the restid param. Thus far I've used the itemid param found in the url of the webLink field, the id of the json object, the changeKey, and the iCalUId but those last two didnt get me anything beyond just opening up Outlook.
I've also just passed in the webLink but it just opens a lightweight browser (and get's stuck on a white page) which I don't want as I need it specifically to go to the Outlook app. Any ideas?
So the best current solution I have been able to find is to open up a lightweight browser using a different url scheme than any prior:
https://outlook.office365.com/calendar/item/{webLinkItemId}
where webLinkItemId is the itemId param from the webLink url gotten from the returned Graphs API json object. You can find that complete object above in my original post but what you're looking for within that object is the following field
"webLink": "https://outlook.office365.com/owa/?itemid={webLinkItemId}&exvsurl={int}&path=/calendar/item"
You want to take the {webLinkItemId} string embedded in the url above and plug it into the corresponding spot in the scheme above
I have this schema extension:
{
"id": "intnovaction_Docu2EventMetadata",
"description": "Eventos de Docu2",
"targetTypes": [
"event"
],
"status": "Available",
"owner": "d1aaf0fa-549f-4692-8929-22eb90b33099",
"properties": [
{
"name": "ActuacionId",
"type": "String"
},
{
"name": "ExpedienteId",
"type": "String"
}
]
}
I am able to extend event properties using this schema. I can set values for 'ActuacionId' and 'ExpedienteId' on an event and I can get these values through this request: https://graph.microsoft.com/v1.0/me/events?$select=id,intnovaction_Docu2EventMetadata
that returns
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('6d418063-df8b-4f47-921b-1072baf4a949')/events(id,intnovaction_Docu2EventMetadata)",
"value": [
{
"#odata.etag": "W/\"FwgXoe8hSUuEcCnxk8/heAAALdjYcQ==\"",
"id": "AAMkAGE1MDUwMDZkLWRmZDctNGMxMi1hN2ZiLTUwNTBlYTc1NmRkYwBGAAAAAABIbknKwqd9SI8d_mLMOg2XBwAXCBeh7yFJS4RwKfGTz_F4AAAAAAENAAAXCBeh7yFJS4RwKfGTz_F4AAAtI8LHAAA=",
"intnovaction_Docu2EventMetadata": {
"ActuacionId": "1",
"ExpedienteId": "2"
}
}
}
the problem comes when I try to filter for those properties:
https://graph.microsoft.com/v1.0/me/events?$select=id,intnovaction_Docu2EventMetadata&$filter=intnovaction_Docu2EventMetadata/ActuacionId eq '1'
Then I am receiving this error response
{
"error": {
"code": "RequestBroker-ParseUri",
"message": "Could not find a property named 'e2_3be22c6901b942889d07616b14e79402_intnovaction_Docu2EventMetadata' on type 'Microsoft.OutlookServices.Event'.",
"innerError": {
"request-id": "4137b6f4-1c8d-4c1e-84fd-02e8ccaab860",
"date": "2017-10-02T19:25:28"
}
}
}
Is it not possible to filter events by schema properties?
It looks like we missed something in our documentation. It's not currently possible to filter on schema extensions defined on Outlook based entity types (events, messages and personal contacts). We could also improve our error messages to make this more clear too. I'll file some items for this.
Hope this helps,
I'm having a problem with the URL of the Facebook Graph API. Is there any possibility to get all the fields of a Facebook post including reactions? I use the following URL for the posts:
https://graph.facebook.com/{pageName}/feed?access_token={access_token}
Now I'm getting data like this (which is quite nice):
{
"data": [
{
"id": "someId",
"from": {
"Name": "Page name",
"category": "Sports Team",
"id": "someId"
},
"message": "Hello world!",
[...]
"shares": {
"count": 1
},
"likes": {
"data": [
{
"id": "someId",
"name": "Some person"
}
]
}
},
[...]
]
}
As for now I have to get the reactions (LOVE, WOW, HAHA, SAD, ANGRY and THANKFUL) by downloading the json from the following URL for every single post (and this is very time consuming):
https://graph.facebook.com/v2.9/{postId}?access_token={access_token}&fields=reactions
The only problem is that I can't get the reactions when using the "normal" URL (without &fields). Is there any chance to get all information including reactions without having to add all the fields to &fields=from,message,likes,shares,reactions?
From CBroe's comment:
I had to pass all the fields I wanted to save to my DB in my URL:
https://graph.facebook.com/v2.9/{pageName}/feed?access_token={access_token}&fields=id,from,message,name,[...],likes,comments,reactions,shares
I am using Andy Crum's EmberDataModelMaker.
Having punched in the following two classes
// app/models/server-item.js
export default DS.Model.extend({
hostName: DS.attr('string'),
syncServers: DS.hasMany('string'),
subscribers: DS.hasMany('string'),
mailHost: DS.attr('string'),
mailHostLogin: DS.hasMany('credentials')
});
// app/models/credentials.js
export default DS.Model.extend({
user: DS.attr('string'),
password: DS.attr('string'),
server: DS.belongsTo('serverItem')
});
It's showing the following three different expected JSON formats (a very nice feature btw.):
DS.RESTAdapter
"serverItems": [
{
"id": 1,
"hostName": "foo",
"syncServers": [
<stringids>
],
"subscribers": [
<stringids>
],
"mailHost": "foo",
"mailHostLogin": [
<Credentialsids>
]
}
],
"credentials": [
{
"id": 1,
"user": "foo",
"password": "foo",
"server": <ServerItemid>
}
]
DS.ActiveModelAdapter
"serverItems": [
{
"id": 1,
"host_name": "foo",
"sync_server_ids": [
<stringids>
],
"subscriber_ids": [
<stringids>
],
"mail_host": "foo",
"mail_host_login_ids": [
<Credentialsids>
]
}
],
"credentials": [
{
"id": 1,
"user": "foo",
"password": "foo",
"server_id": <ServerItemid>
}
]
DS.JSONAPIAdapter
{
"data": {
"type": "server-items",
"id": "1",
"attributes": {
"HostName": "foo",
"MailHost": "foo",
},
"relationships": {
"SyncServers": {
"data": {
"type": "SyncServers",
"id": <SyncServersid>
}
},
"Subscribers": {
"data": {
"type": "Subscribers",
"id": <Subscribersid>
}
},
"MailHostLogin": {
"data": {
"type": "MailHostLogin",
"id": <MailHostLoginid>
}
}
},
"included": [
{
<sideloadedrelationships>
]
}
}
}
{
"data": {
"type": "credentials",
"id": "1",
"attributes": {
"User": "foo",
"Password": "foo",
},
"relationships": {
"Server": {
"data": {
"type": "Server",
"id": <Serverid>
}
}
},
"included": [
{
<sideloadedrelationships>
]
}
}
}
I am going to implement (or rather change) some WebServices on the Server side (using C#, ASP.NET Web API). Currently, the WebService already creates a result that is pretty similar to the format expected with DS.RESTAdapter - obviously, it would be ideal if I could use it without compromising the Data Integrity - can I?
If yes, would it empower Ember Data to send all the requests necessary to maintain the data consistency on the server? Meaning, would the client send a DELETE request to the server not only for the ServerItem but also for the Credentials item that is referenced via the mailHostLogin property when the user wants to delete a ServerItem?
If not: are both of the other two adapters fulfilling the above mentioned consistency requirement? Which of the other two should I implement - any experiences/recommendations out there?
You should choose whichever Adapter closest fits your API data structure as a basis(sounds like DS.RESTAdapter in this case). You can extend the adapters and serializers that are a closest fit to make any necessary adjustments(this can be done both application wide or on a per model basis).
However, I don't think that the Ember Data model relationships(i.e. belongsTo and hasMany) are binding in such a way that will automatically result in the "data consistency" you are looking for. If your application requirements are to delete all associated Credentials records when a ServerItem is deleted, I would recommend doing that server side when handling the DELETE ServerItem API request. That would result in better performance(1 HTTP call instead of 2 or N depending if credentials can be deleted in bulk) and be much less error prone due to potential network or other failure of calls to delete Credentials after a ServerItem is deleted.
After a successful ServerItem delete, you could loop through it's credentials and unload the records from the client side store to keep it in sync with the new state on the server. Something like:
serverItemCredentials.forEach(function(id) {
if (this.store.recordIsLoaded('credential', id)) {
this.store.unloadRecord(this.store.peekRecord('credential', id));
}
});