FreshService API with Restsharp and Dynamic property names - c#

I'm trying to use the FreshService API for assets and getting a list of assets returns JSON like the below. Notice that the properties inside "levelfield_values" have the id appended to the end of their property name.
I'm trying to pull the "license_expiry_date" for all assets but am having problems converting to objects to pull that field since the name changes with each item. Any suggestions?
{"config_item": {"agent_id": 215,
"asset_tag": batch_2017,
"assigned_on": "2014-07-18T03:54:18+05:30",
"ci_type_id": 3,
"created_at": "2014-07-25T14:25:04+05:30",
"deleted": false,
"department_id": 4,
"depreciation_id": null,
"description": null,
"disabled": false,
"display_id": 113,
"expiry_notified": false,
"id": 113,
"impact": 3,
"location_id": 21,
"name": "windows 7",
"salvage": null,
"trashed": false,
"updated_at": "2014-07-25T14:25:04+05:30",
"user_id": 214,
"department_name": "Finance",
"used_by": "Rachel",
"business_impact": "Medium",
"agent_name": "Andrea",
"levelfield_values": {
"product_3": 100,
"vendor_3": 43,
"cost_3": 4000,
"license_validity_3": 24,
"installation_date_3": "2014-07-25T14:25:04+05:30",
"license_expiry_date_3": "2016-07-25T00:00:00+05:30",
"license_key_3": "234_423_543_534",
"version_3": 2,
"license_type_3": "commercial",
"installed_machine_3": "Andrea’s computer",
"installation_path_3": null,
"last_audit_date_3": "2014-07-25T14:25:04+05:30"
},
"ci_type_name": "Software",
"product_name": "windows_os",
"vendor_name": "micosoft",
"state_name": null,
"location_name": "America" } }

You could do something like this
JsonConvert.DeserializeObject<JObject>(jsonString)["config_item"]["levelfield_values"]
.ToObject<JObject>()
.Properties()
.FirstOrDefault(x => x.Name.ToLower().Contains("license_validity"));
basically you;
navigate into config_item
navigate into levelfield_values
get all properties of navigated object (levelfield_values)
find a property that has a name like license_validity

That example Json is awful and incorrect, but.. here is how I'll make serialization seamless.
levelfield_values to definied as Expando object
defining a class for levelfield_values clean (no id in properties)
Add regenerative properties between Expando to defined class property and viceversa
I used visual studio paste special to write initially the class.
Example or fiddle:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var example = new Config
{
config_item = new Config_Item
{
LevelfieldValuesParshed = new CleanLevelfield_Values
{
Id = 2,
product = 1232
}
}
};
var serialized = JsonConvert.SerializeObject(example); // should have "product_2" : 2 inside
// VOILA deserialization with property parsing in a clean object
var deserialzed = JsonConvert.DeserializeObject<Config>(serialized);
if (example.config_item.LevelfieldValuesParshed.Id != deserialzed.config_item.LevelfieldValuesParshed.Id ||
example.config_item.LevelfieldValuesParshed.product != deserialzed.config_item.LevelfieldValuesParshed.product)
{
throw new Exception("Impossible to happen!!!");
}
}
}
public class Config
{
public Config_Item config_item { get; set; }
}
public class Config_Item
{
public int agent_id { get; set; }
public string asset_tag { get; set; }
public DateTime assigned_on { get; set; }
public int ci_type_id { get; set; }
public DateTime created_at { get; set; }
public bool deleted { get; set; }
public int department_id { get; set; }
public object depreciation_id { get; set; }
public object description { get; set; }
public bool disabled { get; set; }
public int display_id { get; set; }
public bool expiry_notified { get; set; }
public int id { get; set; }
public int impact { get; set; }
public int location_id { get; set; }
public string name { get; set; }
public object salvage { get; set; }
public bool trashed { get; set; }
public DateTime updated_at { get; set; }
public int user_id { get; set; }
public string department_name { get; set; }
public string used_by { get; set; }
public string business_impact { get; set; }
public string agent_name { get; set; }
// Regenerative property with backing filed => _levelfieldValuesParshed
[JsonIgnore] // Ignore property at serialization
public CleanLevelfield_Values LevelfieldValuesParshed
{
get
{
if (_levelfieldValuesParshed == null)
{
if (_levelfield_values != null) // if null everything is null
{
var propsByName = (IDictionary<string, object>)_levelfield_values; // Expando Object to dictionary
var product = propsByName.Keys.FirstOrDefault(x => x.StartsWith("product_", StringComparison.InvariantCultureIgnoreCase)); // user first to fail if not found, it can be smarter but it works
if (!string.IsNullOrEmpty(product))// hurray we know the id
{
if (int.TryParse(product.Replace("product_", ""), out int id)) // C# 7
{
// Cleaner code can be written (generic method to set get object props with reflection)
_levelfieldValuesParshed = new CleanLevelfield_Values
{
Id = id
};
_levelfieldValuesParshed.product = !string.IsNullOrEmpty(propsByName.Keys.FirstOrDefault(x => x.Equals($"product_{id}", StringComparison.InvariantCultureIgnoreCase)))
? Convert.ToInt32(propsByName.First(x => x.Key.Equals($"product_{id}", StringComparison.InvariantCultureIgnoreCase)).Value) : 0;
_levelfieldValuesParshed.vendor = !string.IsNullOrEmpty(propsByName.Keys.FirstOrDefault(x => x.Equals($"vendor_{id}", StringComparison.InvariantCultureIgnoreCase)))
? Convert.ToInt32(propsByName.First(x => x.Key.Equals($"vendor_{id}", StringComparison.InvariantCultureIgnoreCase)).Value) : 0;
_levelfieldValuesParshed.cost = !string.IsNullOrEmpty(propsByName.Keys.FirstOrDefault(x => x.Equals($"cost_{id}", StringComparison.InvariantCultureIgnoreCase)))
? Convert.ToInt32(propsByName.First(x => x.Key.Equals($"cost_{id}", StringComparison.InvariantCultureIgnoreCase)).Value) : 0;
_levelfieldValuesParshed.license_validity = !string.IsNullOrEmpty(propsByName.Keys.FirstOrDefault(x => x.Equals($"license_validity_{id}", StringComparison.InvariantCultureIgnoreCase)))
? Convert.ToInt32(propsByName.First(x => x.Key.Equals($"license_validity_{id}", StringComparison.InvariantCultureIgnoreCase)).Value) : 0;
_levelfieldValuesParshed.installation_date = !string.IsNullOrEmpty(propsByName.Keys.FirstOrDefault(x => x.Equals($"installation_date_{id}", StringComparison.InvariantCultureIgnoreCase)))
? Convert.ToDateTime(propsByName.First(x => x.Key.Equals($"installation_date_{id}", StringComparison.InvariantCultureIgnoreCase)).Value) : DateTime.MinValue;
_levelfieldValuesParshed.license_expiry_date = !string.IsNullOrEmpty(propsByName.Keys.FirstOrDefault(x => x.Equals($"license_expiry_date_{id}", StringComparison.InvariantCultureIgnoreCase)))
? Convert.ToDateTime(propsByName.First(x => x.Key.Equals($"license_expiry_date_{id}", StringComparison.InvariantCultureIgnoreCase)).Value) : DateTime.MinValue;
_levelfieldValuesParshed.license_key = !string.IsNullOrEmpty(propsByName.Keys.FirstOrDefault(x => x.Equals($"license_key_{id}", StringComparison.InvariantCultureIgnoreCase)))
? Convert.ToString(propsByName.First(x => x.Key.Equals($"license_key_{id}", StringComparison.InvariantCultureIgnoreCase)).Value) : string.Empty;
_levelfieldValuesParshed.version = !string.IsNullOrEmpty(propsByName.Keys.FirstOrDefault(x => x.Equals($"version_{id}", StringComparison.InvariantCultureIgnoreCase)))
? Convert.ToInt32(propsByName.First(x => x.Key.Equals($"version_{id}", StringComparison.InvariantCultureIgnoreCase)).Value) : 0;
_levelfieldValuesParshed.license_type = !string.IsNullOrEmpty(propsByName.Keys.FirstOrDefault(x => x.Equals($"license_type_{id}", StringComparison.InvariantCultureIgnoreCase)))
? Convert.ToString(propsByName.First(x => x.Key.Equals($"license_type_{id}", StringComparison.InvariantCultureIgnoreCase)).Value) : string.Empty;
_levelfieldValuesParshed.installed_machine = !string.IsNullOrEmpty(propsByName.Keys.FirstOrDefault(x => x.Equals($"installed_machine_{id}", StringComparison.InvariantCultureIgnoreCase)))
? Convert.ToString(propsByName.First(x => x.Key.Equals($"installed_machine_{id}", StringComparison.InvariantCultureIgnoreCase)).Value) : string.Empty;
_levelfieldValuesParshed.installation_path = !string.IsNullOrEmpty(propsByName.Keys.FirstOrDefault(x => x.Equals($"installation_path_{id}", StringComparison.InvariantCultureIgnoreCase)))
? propsByName.First(x => x.Key.Equals($"installation_path_{id}", StringComparison.InvariantCultureIgnoreCase)).Value : new object();
_levelfieldValuesParshed.last_audit_date = !string.IsNullOrEmpty(propsByName.Keys.FirstOrDefault(x => x.Equals($"last_audit_date_{id}", StringComparison.InvariantCultureIgnoreCase)))
? Convert.ToDateTime(propsByName.First(x => x.Key.Equals($"last_audit_date_{id}", StringComparison.InvariantCultureIgnoreCase)).Value) : DateTime.MinValue;
}
}
}
}
return _levelfieldValuesParshed;
}
set
{
_levelfieldValuesParshed = value;
_levelfield_values = null;
}
}
private CleanLevelfield_Values _levelfieldValuesParshed;
// Regenerative Expando property with backing field => _levelfield_values
public System.Dynamic.ExpandoObject levelfield_values
{
get
{
if (_levelfieldValuesParshed != null)
{
_levelfield_values = new ExpandoObject();
// Cleaner code can be written with a foreach (generic method to set get object props with reflection)
var keValuesPairs = (IDictionary<string, object>)_levelfield_values;
keValuesPairs.Add($"product_{_levelfieldValuesParshed.Id}", _levelfieldValuesParshed.product);
keValuesPairs.Add($"vendor_{_levelfieldValuesParshed.Id}", _levelfieldValuesParshed.vendor);
keValuesPairs.Add($"cost_{_levelfieldValuesParshed.Id}", _levelfieldValuesParshed.cost);
keValuesPairs.Add($"license_validity_{_levelfieldValuesParshed.Id}", _levelfieldValuesParshed.license_validity);
keValuesPairs.Add($"installation_date_{_levelfieldValuesParshed.Id}", _levelfieldValuesParshed.installation_date);
keValuesPairs.Add($"license_expiry_date_{_levelfieldValuesParshed.Id}", _levelfieldValuesParshed.license_expiry_date);
keValuesPairs.Add($"license_key_{_levelfieldValuesParshed.Id}", _levelfieldValuesParshed.license_key);
keValuesPairs.Add($"version_{_levelfieldValuesParshed.Id}", _levelfieldValuesParshed.version);
keValuesPairs.Add($"license_type_{_levelfieldValuesParshed.Id}", _levelfieldValuesParshed.license_type);
keValuesPairs.Add($"installed_machine_{_levelfieldValuesParshed.Id}", _levelfieldValuesParshed.installed_machine);
keValuesPairs.Add($"installation_path_{_levelfieldValuesParshed.Id}", _levelfieldValuesParshed.installation_path);
keValuesPairs.Add($"last_audit_date_{_levelfieldValuesParshed.Id}", _levelfieldValuesParshed.last_audit_date);
return _levelfield_values;
}
return null;
}
set
{
_levelfield_values = value;
_levelfieldValuesParshed = null; // remove cleaned object, it will regenerated itself when opened
}
}
private ExpandoObject _levelfield_values;
public string ci_type_name { get; set; }
public string product_name { get; set; }
public string vendor_name { get; set; }
public object state_name { get; set; }
public string location_name { get; set; }
}
public class CleanLevelfield_Values
{
public int Id { get; set; }
public int product { get; set; }
public int vendor { get; set; }
public int cost { get; set; }
public int license_validity { get; set; }
public DateTime installation_date { get; set; }
public DateTime license_expiry_date { get; set; }
public string license_key { get; set; }
public int version { get; set; }
public string license_type { get; set; }
public string installed_machine { get; set; }
public object installation_path { get; set; }
public DateTime last_audit_date { get; set; }
}
}

Related

System.ArgumentNullException: Value cannot be null Parameter name: value - How to fix this error?

Please help! I am getting error in the line :
details.NominalVoltage = String.Join(",", paneldetails?.NominalVoltage?.ToArray());
I have below code in my builder.
foreach (var panel in panelAddresses.Take(2))
{
var paneldetails = new SM_NFPA72ReportPage1();
details.batteryDetails = new List<Battery>();
var AssociatedPrimaryPowers = new Repository(new BuildConnection()).GetPanelPrimarypowerDevcies(reportInput.UseroId, panel, reportInput.BuildingId, reportInput.TestSessionId[0]).Result;
AssociatedPrimaryPowers.ForEach(x => paneldetails?.batteryDetails?.Add(new Battery
{
NominalVoltage = deviceDetailsList?.CustomProperty?.Where(y => y.fieldName == "nominalVoltage")?.FirstOrDefault()?.Value,
NominalAmps = deviceDetailsList?.CustomProperty?.Where(y => y.fieldName == "nominalAmps")?.FirstOrDefault()?.Value,
NominalLocation = deviceDetailsList?.CustomProperty?.Where(y => y.fieldName == "disconnectLocation")?.FirstOrDefault()?.Value,
Protection = deviceDetailsList?.CustomProperty?.Where(y => y.fieldName == "overCurrentType")?.FirstOrDefault()?.Value,
ProtectionAmps = deviceDetailsList?.CustomProperty?.Where(y => y.fieldName == "overCurrentAmps")?.FirstOrDefault()?.Value,
ProtectionLocation = deviceDetailsList?.CustomProperty?.Where(y => y.fieldName == "powerLocation")?.FirstOrDefault()?.Value,
}));
details.NominalVoltage = String.Join(",", paneldetails?.NominalVoltage?.ToArray());
details.NominalAmps = String.Join(",", paneldetails?.NominalAmps?.ToArray());
details.NominalLocation = String.Join(",", paneldetails?.NominalLocation?.ToArray());
details.Protection = String.Join(",", paneldetails?.Protection?.ToArray());
details.ProtectionAmps = String.Join(",", paneldetails?.ProtectionAmps?.ToArray());
details.ProtectionLocation = String.Join(",", paneldetails?.ProtectionLocation?.ToArray());
}
Below attached is my model for above builder:
public class SM_NFPA72ReportPage1 : IReportModel
{
public string NominalVoltage { get; set; }
public string NominalAmps { get; set; }
public string NominalLocation { get; set; }
public string Protection { get; set; }
public string ProtectionAmps { get; set; }
public string ProtectionLocation { get; set; }
public List<Battery> batteryDetails { get; set; }
public List<PanelDetailsInfo> panelInfo { get; set; }
}
I am reusing the Battery model to fetch the values from repository
public class Battery
{
public string NominalVoltage { get; set; }
public string NominalAmps { get; set; }
public string NominalLocation { get; set; }
public string Protection { get; set; }
public string ProtectionAmps { get; set; }
public string ProtectionLocation { get; set; }
}
The exception tells you that the parameter value is null, that should mean that:
paneldetails?.NominalVoltage?.ToArray()
...gives you a null result, and that the string.Join method does not accept it.
You need to make sure that you do not provide a null value to the method.
This can be achieved in multiple ways, for example by checking for null value before calling the method:
if (panelDetails?.NominalVoltage != null)
{
details.NominalVoltage = String.Join(",", paneldetails.NominalVoltage.ToArray());
}
or by returning a empty array by default if it is null:
details.NominalVoltage = String.Join(",", paneldetails?.NominalVoltage?.ToArray() ?? Array.Empty<string>());

Unable to fetch data from Azure Cosmos DB

I am having the below model class CallbackResponse.cs :
public class CallbackResponse
{
public Callback Data { get; set; }
}
public class Callback
{
public IEnumerable<ReviewInProgressActivityFeed> ActivitiesFeed { get; set; }
}
public class ReviewInProgressActivityFeed
{
public ReviewInProgressStatus ReviewerSession { get; set; }
}
public class ReviewInProgressStatus
{
public Guid ReviewActivityId { get; set; }
public string ReviewerName { get; set; }
public string ReviewComments { get; set; }
public DateTime ActivityDateTime { get; set; }
}
Sample Payload:
{
"data":
{
"activitiesFeed": [
{
"reviewerSession":
{
"reviewActivityId": "dd9937c3-7c01-4a4a-bc8d-05ef37b07ee5",
"ReviewerName": "Verification Team",
"reviewComments": "upload business verification document for further verification.",
"activityDateTime": "2021-03-31T18:34:26.5978962Z"
},
},
{
"reviewerSession":
{
"reviewActivityId": "dd9937c3-7c01-4a4a-bc8d-05ef37b07ee5",
"ReviewerName": "Other Team",
"reviewComments": "other documents required for verification.",
"activityDateTime": "2021-03-31T19:34:26.5978962Z"
},
}
]
}
}
I am trying to get the data from DB via the CallbackResponse model class. Please find the code for below.
public async Task<CallbackResponse> CallbackActivityFeedAsync(Guid Id)
{
CallbackResponse containerItems = new CallbackResponse();
IQueryable<HumanReviewRequest> query = cosmosReviewRequestContainer.GetItemLinqQueryable<HumanReviewRequest>(true);
query = query.Where(x => x.id == Id);
FeedIterator<HumanReviewRequest> feedIterator = query.ToFeedIterator();
while (feedIterator.HasMoreResults)
{
FeedResponse<HumanReviewRequest> r = await feedIterator.ReadNextAsync().ConfigureAwait(false);
foreach (HumanReviewRequest requestModel in r)
{
containerItems = new CallbackResponse
{
Data = new Callback
{
ActivitiesFeed = new List<ReviewInProgressActivityFeed>
{
new ReviewInProgressActivityFeed
{
ReviewerSession = new ReviewInProgressStatus
{
ReviewActivityId = requestModel.ReviewActivities.Select(x => x.ReviewerSession.ReviewActivityId).LastOrDefault(),
ActivityDateTime = requestModel.ReviewActivities.Select(x => x.ReviewerSession.ActivityDateTime).LastOrDefault(),
ReviewComments = requestModel.ReviewActivities.Select(x => x.ReviewerSession.ReviewerComments).LastOrDefault(),
ReviewerName = requestModel.ReviewActivities.Select(x => x.ReviewerSession.ReviewerName).LastOrDefault()
}
}
}
}
};
}
}
return containerItems;
}
The Problem here is I could not able to fetch all the records present in activitiesFeed array in DB. Instead I could only able to fetch the last record in that array(I am using Azure Cosmos DB). Please help me in this.
HumanReviewRequest.cs (which is DB Class)for reference:
public class HumanReviewRequest
{
public Guid Id { get; set; }
public IEnumerable<ReviewActivity> ReviewActivities { get; set; }
public class ReviewActivity
{
public ReviewerSession ReviewerSession { get; set; }
public string UserComments { get; set; }
}
public class ReviewerSession
{
public Guid ReviewActivityId { get; set; }
public Guid ReviewerUserId { get; set; }
public DateTime ActivityDateTime { get; set; }
public string ReviewerComments { get; set; }
}
This is because you are creating a new List<ReviewInProgressActivityFeed>, a new ReviewInProgressActivityFeed and reading only the last element in activitiesFeed for each iteration:
ReviewerSession = new ReviewInProgressStatus
{
ReviewActivityId = requestModel.ReviewActivities.Select(x => x.ReviewerSession.ReviewActivityId).LastOrDefault(),
ActivityDateTime = requestModel.ReviewActivities.Select(x => x.ReviewerSession.ActivityDateTime).LastOrDefault(),
ReviewComments = requestModel.ReviewActivities.Select(x => x.ReviewerSession.ReviewerComments).LastOrDefault(),
ReviewerName = requestModel.ReviewActivities.Select(x => x.ReviewerSession.ReviewerName).LastOrDefault()
}
Try below code instead of the above code:
public async Task<CallbackResponse> CallbackActivityFeedAsync(Guid Id)
{
CallbackResponse containerItems = new CallbackResponse();
containerItems.Data = new Callback();
containerItems.Data.ActivitiesFeed = new List<ReviewInProgressActivityFeed>();
IQueryable<HumanReviewRequest> query = cosmosReviewRequestContainer.GetItemLinqQueryable<HumanReviewRequest>(true);
query = query.Where(x => x.id == Id);
FeedIterator<HumanReviewRequest> feedIterator = query.ToFeedIterator();
while (feedIterator.HasMoreResults)
{
FeedResponse<HumanReviewRequest> r = await feedIterator.ReadNextAsync().ConfigureAwait(false);
if (r != null || r.ReviewActivities != null)
{
foreach (HumanReviewRequest requestModel in r.ReviewActivities)
{
containerItems.Data.ActivitiesFeed.Add(
new ReviewInProgressActivityFeed
{
ReviewerSession = new ReviewInProgressStatus
{
ReviewActivityId = requestModel.ReviewerSession.ReviewActivityId,
ActivityDateTime = requestModel.ReviewerSession.ActivityDateTime,
ReviewComments = requestModel.ReviewerSession.ReviewerComments,
ReviewerName = requestModel.ReviewerSession.ReviewerName
}
});
}
}
}
};
}
}
return containerItems;
}

Firebase database timestamp is not serializing, getting error {"Unexpected character encountered while parsing value: {. Path 'date',

i want to retrieve timestamp data of firestore collection, but im getting error - {"Unexpected character encountered while parsing value: {. Path 'date',
date field data screenshot
data screenshot
sample data set
{"Tyres":"12","sr_no":"","TruckNumber":"TS 12345","image_url":"https://firebasestorage.googleapis.com/v0/b/truck-41c31.appsp.jpg?alt=media&token=2dc86208-7f71-4e3c-876c-70a80d4822bf","date":{}}
code
Query truckQuery = fireStoreDb.Collection("users/QRRsqyWUas/orders");
QuerySnapshot truckQuerySnapshot = await truckQuery.GetSnapshotAsync();
List<Truck> lstTruck = new List<Truck>();
foreach (DocumentSnapshot documentSnapshot in truckQuerySnapshot.Documents)
{
if (documentSnapshot.Exists)
{
Dictionary<string, object> city = documentSnapshot.ToDictionary();
string json = JsonConvert.SerializeObject(city);
Truck newtruck = JsonConvert.DeserializeObject<Truck>(json);
newtruck.TruckNumber = documentSnapshot.Id;
newtruck.date = documentSnapshot.CreateTime.Value.ToDateTime();
lstTruck.Add(newtruck);
}
}
model
public class Truck
{
[FirestoreProperty]
[Required]
public string TruckNumber { get; set; }
[FirestoreProperty]
[Required]
public string Tyres { get; set; }
public DateTime date { get; set; }
[FirestoreProperty]
[Required]
public string image_url { get; set; }
[FirestoreProperty]
[Required]
public string sr_no { get; set; }
}
firestore date field data - 29 June 2020 at 22:23:44 UTC+5:30
foreach (DocumentSnapshot documentSnapshot in truckQuerySnapshot.Documents)
{
if (documentSnapshot.Exists)
{
Dictionary<string, object> city = documentSnapshot.ToDictionary();
city["date"] = DateTime.Now.ToString();//modified here for resolve
string json = JsonConvert.SerializeObject(city);
Truck newtruck = JsonConvert.DeserializeObject<Truck>(json);
newtruck.Docid = documentSnapshot.Id;
newtruck.date = documentSnapshot.CreateTime.Value.ToDateTime();
lstTruck.Add(newtruck);
}
}
i have assigned datetime now before the serializeObject(city), and my error gone.
I face the same Error in .netcore 5 with firebase Database
Solution :
Change in property : DateTime To DateTimeOffset
ex... "**public DateTimeOffset date { get; set; }**"
And in databse insert Date always in utc
ex... **object.date = DateTime.UtcNow;**
I Hope this helps everyone....
I face this problem and I solve it
I don't know if this consider a solution but I will share it here
Also, I use this method to convert returned Dictionary to Observablecollection Model
using Google.Cloud.Firestore;
FirestoreDb fdb;
private ObservableCollection<Items_Model> _result = new ObservableCollection<Items_Model>();
public ObservableCollection<Items_Model> result
{
get { return _result; }
}
public Page_Items()
{
InitializeComponent();
MyListView.ItemsSource = result;
GetAllItems();
}
Items_Model
using System;
using System.ComponentModel;
using System.Text.Json.Serialization;
namespace WPFApp1.Models
{
public class Items_Model : INotifyPropertyChanged
{
private string _Name { get; set; }
public Guid id { get; set; }
public string Name
{
get { return _Name; }
set { _Name = value; NotifyPropertyChanged("Name"); }
}
public string iid { get; set; }
public string Barcode { get; set; }
public string ImageUrl { get; set; }
public string Section { get; set; }
public string Notes { get; set; }
[JsonIgnore]
public DateTime AddDate { get; set; }
[JsonIgnore]
public DateTime UpdateDate { get; set; }
public string AddBy { get; set; }
public string UpdateBy { get; set; }
[JsonIgnore]
public string Key { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
Here is my solution
public async void GetAllItems()
{
try
{
CollectionReference customersRef = fdb.Collection("Items");
FirestoreChangeListener listener = customersRef.Listen(snapshot =>
{
foreach (var change in snapshot.Changes)
{
var dic = change.Document.ToDictionary();
//Here I Convert to DateTime
string AddD = dic["AddDate"].ToString();
string stringAddDate = AddD.Split(new string[] { "Timestamp: " }, StringSplitOptions.None).Last();
DateTime AddDate = Convert.ToDateTime(stringAddDate);
string UpD = dic["UpdateDate"].ToString();
string stringUpdateDate = UpD.Split(new string[] { "Timestamp: " }, StringSplitOptions.None).Last();
DateTime UpdateDate = Convert.ToDateTime(stringUpdateDate);
var obj = new Items_Model();
obj.id = Guid.Parse(dic["id"].ToString());
obj.iid = (dic["iid"] == null ? "" : dic["iid"].ToString());
obj.Name = (dic["Name"] == null ? "" : dic["Name"].ToString()) ;
obj.Barcode = (dic["Barcode"] == null ? "" : dic["Barcode"].ToString()) ;
obj.ImageUrl = (dic["ImageUrl"] == null ? "" : dic["ImageUrl"].ToString());
obj.Section = (dic["Section"] == null ? "" : dic["Section"].ToString());
obj.Notes = (dic["Notes"] == null ? "" : dic["Notes"].ToString());
obj.AddDate = AddDate;
obj.UpdateDate = UpdateDate;
obj.AddBy = (dic["AddBy"] == null ? "" : dic["AddBy"].ToString());
obj.UpdateBy = (dic["UpdateBy"] == null ? "" : dic["UpdateBy"].ToString());
if (change.ChangeType.ToString() == "Added")
{
App.Current.Dispatcher.Invoke((Action)delegate
{
result.Add(obj);
});
}
else if (change.ChangeType.ToString() == "Modified")
{
if (result.Where(c => c.id == obj.id).Any())
{
var item = result.Where(c => c.id == obj.id).FirstOrDefault();
//item = obj;
App.Current.Dispatcher.Invoke((Action)delegate
{
result.Insert(result.IndexOf(item), obj);
result.Remove(item);
});
}
}
else if (change.ChangeType.ToString() == "Removed")
{
if (result.Where(c => c.id == obj.id).Any())
{
var item = result.Where(c => c.id == obj.id).FirstOrDefault();
App.Current.Dispatcher.Invoke((Action)delegate
{
result.Remove(item);
});
}
}
}
});
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
}
}

How to select object and its properties base on its properties which is list with linq?

I have an object which has a property which is list. Based on that list I want to filter property of it along with other properties of an object.
I have following object
{
Adult: 1,
Child: 0,
Infant: 0,
Origin: 'ABC',
Destination: 'XYZ',
DomesticFlightInfos: [{
FlightID: flightId1,
FareID: fareId1,
IsInbound: true
},
{
FlightID: flightId2,
FareID: fareId2,
IsInbound: false
}
]
};
I want following two objects
{
Adult: 1,
Child: 0,
Infant: 0,
Origin: 'ABC',
Destination: 'XYZ',
DomesticFlightInfos: [{
FlightID: flightId1,
FareID: fareId1,
IsInbound: true
}]
};
Adult: 1,
Child: 0,
Infant: 0,
Origin: 'ABC',
Destination: 'XYZ',
DomesticFlightInfos: [{
FlightID: flightId2,
FareID: fareId2,
IsInbound: false
}]
I was trying to do reservation.DomesticFlightInfos.Where(x => !x.IsInbound); which was wrong and got casting issue. What could be the best solution for it?
C# Object
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
new DomesticFlightReservation()
{
Adult = 1,
Child = 0,
Infant = 0,
Origin = "ABC",
Destination = "XYZ",
DomesticFlightInfos = new List<DomesticFlightInfo>(){
new DomesticFlightInfo{
FlightID= "flightId1",
FareID= "fareId1",
IsInbound= true
},
new DomesticFlightInfo {
FlightID= "flightId2",
FareID= "fareId2",
IsInbound= false
}
}
};
}
}
public class DomesticFlightReservation
{
public int Adult { get; set; } = 0;
public int Child { get; set; } = 0;
public int Infant { get; set; } = 0;
public string Origin { get; set; }
public string Destination { get; set; }
public List<DomesticFlightInfo> DomesticFlightInfos { get; set; }
}
public class DomesticFlightInfo
{
public string FlightID { get; set; }
public string FareID { get; set; }
// True for inbound, false for outbound
public bool IsInbound { get; set; }
}
Since you haven't provided C# object, assuming your C# objects to be defined as
public class DomesticFlightInfo
{
public string FlightID { get; set; }
public string FareID { get; set; }
public bool IsInbound { get; set; }
}
public class RootObject
{
public int Adult { get; set; }
public int Child { get; set; }
public int Infant { get; set; }
public string Origin { get; set; }
public string Destination { get; set; }
public List<DomesticFlightInfo> DomesticFlightInfos { get; set; }
}
If your intention is to separate the Inbounds and Outbound flights to separate groups, you could
var reservation = JsonConvert.DeserializeObject<RootObject>(str);
var flattenedReservation = new[]{reservation}.SelectMany(x=>x.DomesticFlightInfos
.GroupBy(v=>v.IsInbound)
.Select(c =>
{
x.DomesticFlightInfos = c.ToList();
return x;
}));
var jsonCollection = flattenedReservation.Select(x=> JsonConvert.SerializeObject(x,settings));
If your intention is to separate out each flight info into separate jsons, you could
var flattenedReservation = new[]{reservation}.SelectMany(x=>x.DomesticFlightInfos
.Select(c =>
{
x.DomesticFlightInfos = new List<DomesticFlightInfo>{c};
return x;
}));
var jsonCollection = flattenedReservation.Select(x=> JsonConvert.SerializeObject(x));
Output
If you have a list as a collection, you can use SelectMany
So, if you have a list
List<RootObject> rootObjects
then you can do this like flatten the list to get individual items:
rootObjects.SelectMany(x=> x.DomesticFlightInfos).Where(y => !y.IsInbound);

Automapper 8 Ignore Attribute doesn't work on child descendant

I use AutoMapper 8.1.0 in a asp.net core project. I have an Automapper mapping that doesn't work as I expected. I reproduced the configuration so you can test it by yourself. So I have an ExpenseReport with a collection of ExpenseReportItem and this one with another collection. I have to keep the data of eTaxCollection after the mapping, but they are lost in the process.
So the question is why values of eTaxCollections are lost after calling _mapper.Map(vmodel, model) and how can I keep them?
The ignore attribute don't work. I also tried UseDestinationValue(). I lost 2 days trying to figure it out and I'm exhausted.
public void WeatherForecasts()
{
int[] excludeTaxes = new int[] { 2 };
var vmodel = new ExpenseReportCreateEditModel();
vmodel.Expenses.Add(new ExpenseReportItemModel()
{
ExcludeTaxIds = excludeTaxes,
Total = 12,
Id = 1
});
// fetch from bd
var model = new ExpenseReport();
// values will be lost after _mapper.Map...
var eTaxCollections = new HashSet<ExcludeExpenseReportItemTax>();
eTaxCollections.Add(new ExcludeExpenseReportItemTax()
{
TaxId = 1,
ExpenseReportItemId = 1
});
model.Items.Add(new ExpenseReportItem()
{
ExcludeTaxes = eTaxCollections,
ExpenseReportId = 1,
Id = 9
});
_mapper.Map(vmodel, model);
}
public class ExpenseReportCreateEditModelProfile : Profile
{
public ExpenseReportCreateEditModelProfile()
{
CreateMap<ExpenseReportCreateEditModel, ExpenseReport>()
.ForMember(d => d.Items, s => s.MapFrom(m => m.Expenses));
}
}
public class ExpenseReportItemModelProfile : Profile
{
public ExpenseReportItemModelProfile()
{
CreateMap<ExpenseReportItemModel, ExpenseReportItem>()
.ForMember(d => d.ExcludeTaxes, s => s.Ignore()); // <<<==== data are lost
}
}
public class ExpenseReportCreateEditModel
{
public int Id { get; set; }
public ICollection<ExpenseReportItemModel> Expenses { get; set; }
public ExpenseReportCreateEditModel()
{
Expenses = new HashSet<ExpenseReportItemModel>();
}
}
public class ExpenseReportItemModel
{
public int Id { get; set; }
public ICollection<int> ExcludeTaxIds { get; set; }
public decimal Total { get; set; }
public ExpenseReportItemModel()
{
ExcludeTaxIds = new HashSet<int>();
}
}
public class ExpenseReport
{
public int Id { get; set; }
public virtual ICollection<ExpenseReportItem> Items { get; set; }
public ExpenseReport()
{
Items = new HashSet<ExpenseReportItem>();
}
}
public class ExpenseReportItem
{
public int Id { get; set; }
public int ExpenseReportId { get; set; }
public virtual ICollection<ExcludeExpenseReportItemTax> ExcludeTaxes { get; set; }
public ExpenseReportItem()
{
ExcludeTaxes = new HashSet<ExcludeExpenseReportItemTax>();
}
}
public class ExcludeExpenseReportItemTax
{
public int ExpenseReportItemId { get; set; }
public virtual ExpenseReportItem ExpenseReportItem { get; set; }
public int TaxId { get; set; }
}
Thank you for any help
Edit
I execute the execution plan and perhaps this is the problem:
$typeMapDestination = ($dest ?? .New WebApplication1.Controllers.SampleDataController+ExpenseReportItem());
This is only way I can lost the values.
I have to find a solution now
Here the complete execution plan :
.If ($src == null) {
.Default(WebApplication1.Controllers.SampleDataController+ExpenseReportItem)
} .Else {
.Block() {
$typeMapDestination = ($dest ?? .New WebApplication1.Controllers.SampleDataController+ExpenseReportItem());
.Try {
.Block(System.Int32 $resolvedValue) {
.Block() {
$resolvedValue = .If (
$src == null || False
) {
.Default(System.Int32)
} .Else {
$src.Id
};
$typeMapDestination.Id = $resolvedValue
}
}
} .Catch (System.Exception $ex) {
.Block() {
.Throw .New AutoMapper.AutoMapperMappingException(
"Error mapping types.",
$ex,
.Constant<AutoMapper.TypePair>(AutoMapper.TypePair),
.Constant<AutoMapper.TypeMap>(AutoMapper.TypeMap),
.Constant<AutoMapper.PropertyMap>(AutoMapper.PropertyMap));
.Default(System.Int32)
}
};
$typeMapDestination
}
}

Categories

Resources