I have been developing an api in c# asp.net with table relationships returning a json format as default and I'm added a custom csv formatter from WebApiContrib.Core.Formatter.Csv
my problem is that when I'm returning csv format from this json data.
[
{
"userId": 1275,
"username": "sample",
"applicationName": "sample",
"email": "samples#gmail.com",
"password": "samplepass1234,
"iUserProfile": {
"profileId": 1275,
"profileName": "sample"
}
}
]
I'm getting a csv format like this.
UserId,Username,ApplicationName,Email,Password,IUserProfile
1275,sample,sample,sample#gmail.com,samplepass1234,Odysseus_API.v2.Models.IUserProfileList
it is not getting the IUserProfile data on the csv format.
this is my custom formatter I get from WebApiContrib.Core.Formatter.Csv
using Microsoft.AspNetCore.Mvc.Formatters;
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace WebApiContrib.Core.Formatter.Csv
{
/// <summary>
/// Original code taken from
/// http://www.tugberkugurlu.com/archive/creating-custom-csvmediatypeformatter-in-asp-net-web-api-for-comma-separated-values-csv-format
/// Adapted for ASP.NET Core and uses ; instead of , for delimiters
/// </summary>
public class CsvOutputFormatter : OutputFormatter
{
private readonly CsvFormatterOptions _options;
private readonly bool useJsonAttributes = true;
public string ContentType { get; private set; }
public CsvOutputFormatter(CsvFormatterOptions csvFormatterOptions)
{
ContentType = "text/csv";
SupportedMediaTypes.Add(Microsoft.Net.Http.Headers.MediaTypeHeaderValue.Parse("text/csv"));
_options = csvFormatterOptions ?? throw new ArgumentNullException(nameof(csvFormatterOptions));
}
protected override bool CanWriteType(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
return IsTypeOfIEnumerable(type);
}
private bool IsTypeOfIEnumerable(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
return typeof(IEnumerable).IsAssignableFrom(type);
}
/// <summary>
/// Returns the JsonProperty data annotation name
/// </summary>
/// <param name="pi">Property Info</param>
/// <returns></returns>
private string GetDisplayNameFromNewtonsoftJsonAnnotations(PropertyInfo pi)
{
if (pi.GetCustomAttribute<JsonPropertyAttribute>(false)?.PropertyName is string value)
{
return value;
}
return pi.GetCustomAttribute<DisplayAttribute>(false)?.GetName() ?? pi.Name;
}
public async override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
{
var response = context.HttpContext.Response;
Type type = context.Object.GetType();
Type itemType;
if (type.GetGenericArguments().Length > 0)
{
itemType = type.GetGenericArguments()[0];
}
else
{
itemType = type.GetElementType();
}
var streamWriter = new StreamWriter(response.Body, _options.Encoding);
if (_options.IncludeExcelDelimiterHeader)
{
await streamWriter.WriteLineAsync($"sep ={_options.CsvDelimiter}");
}
if (_options.UseSingleLineHeaderInCsv)
{
var values = useJsonAttributes
? itemType.GetProperties().Where(pi => !pi.GetCustomAttributes<JsonIgnoreAttribute>(false).Any()) // Only get the properties that do not define JsonIgnore
.Select(pi => new
{
Order = pi.GetCustomAttribute<JsonPropertyAttribute>(false)?.Order ?? 0,
Prop = pi
}).OrderBy(d => d.Order).Select(d => GetDisplayNameFromNewtonsoftJsonAnnotations(d.Prop))
: itemType.GetProperties().Select(pi => pi.GetCustomAttribute<DisplayAttribute>(false)?.Name ?? pi.Name);
await streamWriter.WriteLineAsync(string.Join(_options.CsvDelimiter, values));
}
foreach (var obj in (IEnumerable<object>)context.Object)
{
var vals = useJsonAttributes
? obj.GetType().GetProperties()
.Where(pi => !pi.GetCustomAttributes<JsonIgnoreAttribute>().Any())
.Select(pi => new
{
Order = pi.GetCustomAttribute<JsonPropertyAttribute>(false)?.Order ?? 0,
Value = pi.GetValue(obj, null)
}).OrderBy(d => d.Order).Select(d => new { d.Value })
: obj.GetType().GetProperties().Select(
pi => new
{
Value = pi.GetValue(obj, null)
});
string valueLine = string.Empty;
foreach (var val in vals)
{
if (val.Value != null)
{
var _val = val.Value.ToString();
//Substitute smart quotes in Windows-1252
if (_options.Encoding.EncodingName == "Western European (ISO)")
_val = _val.Replace('“', '"').Replace('”', '"');
//Escape quotes
_val = _val.Replace("\"", "\"\"");
//Replace any \r or \n special characters from a new line with a space
if (_options.ReplaceLineBreakCharacters && _val.Contains("\r"))
_val = _val.Replace("\r", " ");
if (_options.ReplaceLineBreakCharacters && _val.Contains("\n"))
_val = _val.Replace("\n", " ");
//Check if the value contains a delimiter/quote/newline and place it in quotes if so
if (_val.Contains(_options.CsvDelimiter) || _val.Contains("\"") || _val.Contains("\r") || _val.Contains("\n"))
_val = string.Concat("\"", _val, "\"");
valueLine = string.Concat(valueLine, _val, _options.CsvDelimiter);
}
else
{
valueLine = string.Concat(valueLine, string.Empty, _options.CsvDelimiter);
}
}
await streamWriter.WriteLineAsync(valueLine.Remove(valueLine.Length - _options.CsvDelimiter.Length));
}
await streamWriter.FlushAsync();
}
}
}
using System.Text;
namespace WebApiContrib.Core.Formatter.Csv
{
public class CsvFormatterOptions
{
public bool UseSingleLineHeaderInCsv { get; set; } = true;
public string CsvDelimiter { get; set; } = ",";
public Encoding Encoding { get; set; } = Encoding.Default;
public bool IncludeExcelDelimiterHeader { get; set; } = false;
public bool ReplaceLineBreakCharacters { get; set; } = true;
}
}
Object Class with both User and Profile
using System.Runtime.Serialization;
namespace Test_API.Models
{
[DataContract]
public class IUser
{
[DataMember(Name = "UserId")]
public int UserId { get; set; }
[DataMember(Name = "Username")]
public string? Username { get; set; }
[DataMember(Name = "ApplicationName")]
public string? ApplicationName { get; set; }
[DataMember(Name = "Email")]
public string? Email { get; set; }
[DataMember(Name = "Password")]
public string? Password { get; set; }
[DataMember(Name = "IUserProfile")]
public virtual IUserProfileList? IUserProfile { get; set; }
}
[DataContract()]
public class IUserProfileList
{
[DataMember(Name = "ProfileId")]
public int ProfileId { get; set; }
[DataMember(Name = "ProfileName")]
public string? ProfileName { get; set; }
}
}
Related
I want to check each page values from the API and against the values to change the color of the map marker.
This is my API: http://194.141.118.43:3001/?id=0 where id is from 0 to 16
I want:
if from ?id=0 AL = 1 the marker should be green
if from ?id=0 AL = 2 the marker should be yellow
if from ?id=0 AL = 3 the marker should be orange
if from ?id=0 AL = 4 the marker should be red
So I want to check for all 17 stations (from ?id=0 to ?id=16)
I am currently checking the property Alertlevelwebsite in this method with this API: http://194.141.118.43:3001/stations, But now I have to check all the values from this address for each pin and I have to put a color for the largest value for each pin.
http://194.141.118.43:3001/?id=0 (from 0 to 16)
I use this example from xamarin.forms.maps - https://learn.microsoft.com/en-us/samples/xamarin/xamarin-forms-samples/workingwithmaps/ and in CustomMapRenderer class I try to change the colors in this method:
protected override MKAnnotationView GetViewForAnnotation(MKMapView mapView, IMKAnnotation annotation)
{
MKAnnotationView annotationView = null;
if (annotation is MKUserLocation)
return null;
var customPin = GetCustomPin(annotation as MKPointAnnotation);
//Get Value
c_annotation = annotation;
if (customPin == null)
{
throw new Exception("Custom pin not found");
}
annotationView = mapView.DequeueReusableAnnotation(customPin.Name);
if (annotationView == null)
{
annotationView = new CustomMKAnnotationView(annotation, customPin.Name);
annotationView.CalloutOffset = new CGPoint(0, 0);
((CustomMKAnnotationView)annotationView).Name = customPin.Name;
((CustomMKAnnotationView)annotationView).Url = customPin.Url;
((CustomMKAnnotationView)annotationView).Address = customPin.Address;
//Add First Line
((CustomMKAnnotationView)annotationView).AlertLevel = customPin.AlertLevel;
if (customPin.AlertLevel == 1)
{
annotationView.Image = UIImage.FromFile("green.png");
}
else if (customPin.AlertLevel == 2)
{
annotationView.Image = UIImage.FromFile("yellow.png");
}
else if (customPin.AlertLevel == 3)
{
annotationView.Image = UIImage.FromFile("orange.png");
}
else if (customPin.AlertLevel == 4)
{
annotationView.Image = UIImage.FromFile("red.png");
}
//Add Second Line
((CustomMKAnnotationView)annotationView).CodeNum = customPin.CodeNum;
((CustomMKAnnotationView)annotationView).MapCode = customPin.MapCode;
//Here I add the RequestUri for stations
string GenerateRequestUriStations(string endpoint)
{
string requestUri = endpoint;
requestUri += $"stations";
return requestUri;
}
//Here I need the loop from 0 to 16 every page and change the pin icons like above if statement
string GenerateRequestUri(string endpoint)
{
string requestUri = endpoint;
requestUri += $"?id=0";
return requestUri;
}
//This is the value who I need to compare result.WaterData.Ardaforecast but does not allow me to write result.WaterData.Ardaforecast and does not allow me to foreach here .. I don't know why ?
var reusult = _restServiceData.GetWaterDataForecast(GenerateRequestUriStations(Constants.EndPoint), GenerateRequestUri(Constants.EndPoint));
}
annotationView.CanShowCallout = true;
configureDetailView(annotationView);
return annotationView;
}
In the comments above the code I mean that when I write:
var reusult = _restServiceData.GetWaterDataForecast(GenerateRequestUriStations(Constants.EndPoint), GenerateRequestUri(Constants.EndPoint));
foreach (var item in IAsyncResult)
{
}
When I try to write result. automatic puts me IAsyncResult.. I don't know why.. ?
Can I get an example of how to loop all the pages and change colors on the markers ?
My GetDataFromAPI look like this:
public IEnumerable<AlertLevel> GetDataFromAPI(int mapCode)
{
var listAlert = new List<AlertLevel>();
var reusult = _restServiceData.GetWaterDataForecast(GenerateRequestUriStations(Constants.EndPoint), GenerateRequestUri(Constants.EndPoint, mapCode));
foreach (var item in reusult.WaterData.Ardaforecast[0].Items)
{
var currentData = new AlertLevel()
{
dateForecast = item.DateTimeForecast,
levelForecast = item.AlertLevelForecast
};
listAlert.Add(currentData);
}
return listAlert;
}
My GetWaterDataForecast look like this:
using System;
using System.Diagnostics;
using System.Net.Http;
using System.Threading.Tasks;
using MaritsaTundzhaForecast.Models;
using Newtonsoft.Json;
namespace MaritsaTundzhaForecast.Services
{
public class RestServiceData
{
HttpClient _client1;
HttpClient _client2;
public RestServiceData()
{
_client1 = new HttpClient();
_client2 = new HttpClient();
}
public WaterBindingData GetWaterDataForecast(string query, string query2)
{
WaterDataJson waterData = new WaterDataJson();
WaterStationsJson waterStations = new WaterStationsJson();
WaterBindingData result = new WaterBindingData();
try
{
var task = Task.Run(() => _client1.GetAsync(query));
task.Wait();
var response = task.Result;
var task2 = Task.Run(() => _client2.GetAsync(query2));
task2.Wait();
var response2 = task2.Result;
if (response.IsSuccessStatusCode && response2.IsSuccessStatusCode)
{
var content = response.Content.ReadAsStringAsync().Result;
var content2 = response2.Content.ReadAsStringAsync().Result;
var json = content2.Replace("\"ardaforecast\":[[", "\"ardaforecast\":[ {\"items\": [")
.Replace("}],{\"fieldCount\"", "}],\"details\":{\"fieldCount\"")
.Replace("}]}", "}}]}");
waterData = JsonConvert.DeserializeObject<WaterDataJson>(json);
waterStations = JsonConvert.DeserializeObject<WaterStationsJson>(content);
result.WaterData = waterData;
result.WaterStation = waterStations;
}
}
catch (Exception ex)
{
Debug.WriteLine("\t\tERROR {0}", ex.Message);
}
return result;
}
}
}
My WaterBindingData look like:
using System;
namespace MaritsaTundzhaForecast.Models
{
public class WaterBindingData
{
public WaterDataJson WaterData { get; set; }
public WaterStationsJson WaterStation { get; set; }
}
}
My WaterDataJson and WaterStations look like:
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace MaritsaTundzhaForecast
{
public class WaterDataJson
{
public List<ForecastBody> Ardaforecast { get; set; }
}
public class ForecastBody
{
public ForecastItem[] Items { get; set; }
public ForecastDetails Details { get; set; }
}
public class ForecastItem
{
[JsonProperty("Dt")]
public DateTime DateTimeForecast { get; set; }
[JsonProperty("AL")]
public int AlertLevelForecast { get; set; }
}
public class ForecastDetails
{
public int fieldCount { get; set; }
public int affectedRows { get; set; }
public int insertId { get; set; }
public int serverStatus { get; set; }
public int warningCount { get; set; }
public int changedRows { get; set; }
public string message { get; set; }
public bool protocol41 { get; set; }
}
}
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace MaritsaTundzhaForecast.Models
{
public class WaterStationsJson
{
public List<ForecastStations> Stations { get; set; }
}
public class ForecastStations
{
[JsonProperty("Map_code")]
public int MapCode { get; set; }
[JsonProperty("NAME_IME")]
public string NameEN { get; set; }
[JsonProperty("NAME_CYR")]
public string NameBG { get; set; }
[JsonProperty("Alertlevelwebsite")]
public int AlertLevelStation { get; set; }
[JsonProperty("CODENUM")]
public int CodeNum { get; set; }
}
}
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");
}
}
I have the following Code:
using MongoDB.Bson;
using MongoDB.Bson.IO;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson.Serialization.Serializers;
using MongoDB.Driver;
using MongoDBTest;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace protocol.server.API.Clients
{
public class ClientService : ServiceStack.Service
{
class CylinderSerializer : SerializerBase<Cylinder>
{
public override void Serialize(MongoDB.Bson.Serialization.BsonSerializationContext context, MongoDB.Bson.Serialization.BsonSerializationArgs args, Cylinder value)
{
var wr = context.Writer;
wr.WriteStartDocument();
wr.WriteName("_id");
wr.WriteObjectId(ObjectId.GenerateNewId());
wr.WriteName("description");
wr.WriteString(value.description.type);
context.Writer.WriteEndDocument();
}
public override Cylinder Deserialize(MongoDB.Bson.Serialization.BsonDeserializationContext context, MongoDB.Bson.Serialization.BsonDeserializationArgs args)
{
context.Reader.ReadStartDocument();
Cylinder a = new Cylinder();
a.Id = context.Reader.ReadObjectId();
while (context.Reader.State != BsonReaderState.Type && context.Reader.ReadBsonType() != BsonType.EndOfDocument)
{
a.description.type = context.Reader.ReadString();
a.description.kind = context.Reader.ReadString();
a.description.year = (short)context.Reader.ReadInt32();
a.description.producer = context.Reader.ReadString();
}
return a;
}
public async Task<List<Cylinder>> Get(GetObjects request)
{
MongoDB.Bson.Serialization.BsonSerializer.RegisterSerializer(typeof(Cylinder), new CylinderSerializer());
IMongoCollection<Cylinder> collection = Connect._database.GetCollection<Cylinder>("Cylinders");
var results = await collection.Find(_ => true).ToListAsync();
return results;
}
}
}
and get the error:
ReadBsonType can only be called when State is Type, not when State is Value
in line:
while (context.Reader.ReadBsonType() != BsonType.EndOfDocument)
I want to deserialize my objects, they look like this:
{
"_id" : ObjectId("5826010eb831ee1c70df5f16"),
"description" : {
"type" : "Cylinder",
"kind" : "rgdgg",
"year" : NumberInt(1997),
"producer" : "hnnghng",
"brands" : [
"trhr"
],
"model" : [
"Baws"
],
"internalproducerdesignation" : "tw6",
"origin" : "Greece"
},
"elements" : {
"nonspringelements" : NumberInt(0),
"springelements" : NumberInt(11),
"discelements" : NumberInt(0),
"magneticelements" : NumberInt(0),
"activeelements" : NumberInt(11),
"passiveelements" : NumberInt(0),
"totalelements" : NumberInt(11)
},
"profiles" : [
"d1",
"d11"
],
"certifications" : [
"",
""
],
"colors" : [
"brown",
"chrome"
],
"specialfittings" : [
"gf",
"hrthr",
"hgnn",
"ngnn",
"hngngn",
"nghnnn"
],
"cutdepths" : NumberInt(7),
"rareness" : "rare",
"value" : {
"new" : "0",
"used" : "$50"
},
"Blaw" : {
"tgtgt" : 10.0,
"hzhz" : true
},
"availableat" : "gtgtgtgt",
"specialabout" : "jujujuju",
"development" : {
"predecessor" : "",
"follower" : "rfrfr"
},
"media" : [
]
}
My Clinder.cs :
using MongoDB.Bson;
using MongoDB.Bson.IO;
using MongoDB.Bson.Serialization.Attributes;
using System;
using System.Collections.Generic;
using System.Globalization;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
namespace protocol.server.API.Clients
{
public class Cylinder
{
[BsonSerializer(typeof(ProductAttributeSerializer))]
public class ProductAttributeSerializer : IBsonSerializer, IBsonArraySerializer
{
public Type ValueType { get { return typeof(List<string>); } }
public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
var type = context.Reader.GetCurrentBsonType();
List<String> items = new List<String>();
switch (type)
{
case BsonType.Document:
case BsonType.Array:
context.Reader.ReadStartArray();
while (context.Reader.ReadBsonType() != BsonType.EndOfDocument)
{
items.Add(context.Reader.ReadString());
}
context.Reader.ReadEndArray();
return new mode(items);
default:
throw new NotImplementedException($"No implementation to deserialize {type}");
}
}
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
{
var d = value;
var attributes = value as List<string>;
if (attributes != null)
{
context.Writer.WriteStartArray();
foreach (string attr in attributes)
{
context.Writer.WriteString(attr);
}
context.Writer.WriteEndArray();
}
}
public bool TryGetItemSerializationInfo(out BsonSerializationInfo serializationInfo)
{
string elementName = null;
var serializer = BsonSerializer.LookupSerializer(typeof(string));
var nominalType = typeof(string);
serializationInfo = new BsonSerializationInfo(elementName, serializer, nominalType);
return true;
}
}
[BsonId]
public ObjectId Id { get; set; }
[BsonSerializer(typeof(ProductAttributeSerializer))]
public class mode
{
public mode(List<String> pItems)
{
this.items = new List<String>();
this.items.Clear();
this.items.AddRange(pItems);
}
public List<String> items { get; set; }
}
public class des
{
public string type { get; set; }
public string kind { get; set; }
public short year { get; set; }
public string producer { get; set; }
public List<string> brands { get; set; }
public string internalproducerdesignation { get; set; }
public string origin { get; set; }
public mode model { get; set; }
}
public class elem
{
public short nonspringelements { get; set; }
public short springelements { get; set; }
public short discelements { get; set; }
public short magneticelements { get; set; }
public short activeelements { get; set; }
public short passiveelements { get; set; }
public short totalelements { get; set; }
}
public des description = new des();
public elem elements = new elem();
public IEnumerable<string> profiles { get; set; }
public IEnumerable<string> certifications { get; set; }
public IEnumerable<string> colors { get; set; }
public IEnumerable<string> specialfittings { get; set; }
public short cutdepths { get; set; }
public string rareness { get; set; }
public class val
{
public String #new { get; set; }
public String used { get; set; }
}
public val value = new val();
public class Pi
{
public Double difficulty { get; set; }
public bool alreadypicked { get; set; }
}
public Pi Picking = new Pi();
public string availableat { get; set; }
public string specialabout { get; set; }
public class devel
{
public string predecessor { get; set; }
public string follower { get; set; }
}
public devel development = new devel();
public Object[] media;
}
}
How to prevent this error ? I just want to deserialize my objects...
while (context.Reader.ReadBsonType() != BsonType.EndOfDocument)
should be
while (context.Reader.State != BsonReaderState.Type || context.Reader.ReadBsonType() != BsonType.EndOfDocument)
Would cause to check the type if the state is a type. If it is not a type, you will pass and not check the type
Not sure why to use while loop there if you just want to fill properties of one object (description). You can do it like this:
public override Cylinder Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) {
context.Reader.ReadStartDocument();
Cylinder a = new Cylinder();
a.Id = context.Reader.ReadObjectId();
context.Reader.ReadStartDocument();
a.description.type = context.Reader.ReadString();
a.description.kind = context.Reader.ReadString();
a.description.year = (short) context.Reader.ReadInt32();
a.description.producer = context.Reader.ReadString();
return a;
}
Test (File bson.txt is copied verbatim from your question):
static void Main(string[] args) {
var cylinder = new CylinderSerializer().Deserialize(BsonDeserializationContext.CreateRoot(new BsonDocumentReader(BsonDocument.Parse(File.ReadAllText(#"G:\tmp\bson.txt")))));
Console.ReadKey();
}
It's a lot of job to write own serializer this way. This is how i did to for cylinder. I managed to deserialize your sample this way.
Please mention, that there is a one simple help method there to deserialize string array.
You don't have any class for "blaw" data, so i read it in not used variables.
public override Cylinder Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
context.Reader.ReadStartDocument();
Cylinder a = new Cylinder {Id = context.Reader.ReadObjectId()};
context.Reader.ReadStartDocument();
a.description.type = context.Reader.ReadString();
a.description.kind = context.Reader.ReadString();
a.description.year = (short)context.Reader.ReadInt32();
a.description.producer = context.Reader.ReadString();
context.Reader.ReadStartArray();
a.description.brands = new List<string>();
while (context.Reader.ReadBsonType() != BsonType.EndOfDocument)
{
a.description.brands.Add(context.Reader.ReadString());
}
context.Reader.ReadEndArray();
context.Reader.ReadStartArray();
a.description.model = new Cylinder.mode(new List<string>());
while (context.Reader.ReadBsonType() != BsonType.EndOfDocument)
{
a.description.model.items.Add(context.Reader.ReadString());
}
context.Reader.ReadEndArray();
a.description.internalproducerdesignation = context.Reader.ReadString();
a.description.origin = context.Reader.ReadString();
context.Reader.ReadEndDocument();
context.Reader.ReadStartDocument();
a.elements = new Cylinder.elem
{
nonspringelements = (short) context.Reader.ReadInt32(),
springelements = (short) context.Reader.ReadInt32(),
discelements = (short) context.Reader.ReadInt32(),
magneticelements = (short) context.Reader.ReadInt32(),
activeelements = (short) context.Reader.ReadInt32(),
passiveelements = (short) context.Reader.ReadInt32(),
totalelements = (short) context.Reader.ReadInt32()
};
context.Reader.ReadEndDocument();
a.profiles = readStringArray(context);
a.certifications = readStringArray(context);
a.colors = readStringArray(context);
a.specialfittings = readStringArray(context);
a.cutdepths = (short) context.Reader.ReadInt32();
a.rareness = context.Reader.ReadString();
context.Reader.ReadStartDocument();
a.value = new Cylinder.val
{
#new = context.Reader.ReadString(),
used = context.Reader.ReadString()
};
context.Reader.ReadEndDocument();
context.Reader.ReadStartDocument();
var blawInt = context.Reader.ReadDouble();
var blawBool = context.Reader.ReadBoolean();
context.Reader.ReadEndDocument();
a.availableat = context.Reader.ReadString();
a.specialabout = context.Reader.ReadString();
context.Reader.ReadStartDocument();
a.development = new Cylinder.devel
{
predecessor = context.Reader.ReadString(),
follower = context.Reader.ReadString()
};
context.Reader.ReadEndDocument();
var objects=new List<object>();
context.Reader.ReadStartArray();
while (context.Reader.ReadBsonType() != BsonType.EndOfDocument)
{
objects.Add(context.Reader.ReadString());
}
context.Reader.ReadEndArray();
a.media = objects.ToArray();
context.Reader.ReadEndDocument();
return a;
}
private static IEnumerable<string> readStringArray(BsonDeserializationContext context)
{
context.Reader.ReadStartArray();
var strings = new List<string>();
while (context.Reader.ReadBsonType() != BsonType.EndOfDocument)
{
strings.Add(context.Reader.ReadString());
}
context.Reader.ReadEndArray();
return strings;
}
I am having the following criteria:-
1.Create gmail group using query execution in sql db. This query will filter contacts on the basis of region.
2.These contacts may or may not be different for each send request. It depends upon the users those who are active at the time of send.
3.I am able to send mail to group.
Main problem is related with how i can update group each time before sending mail to group members excluding inactive members.
Please let me know if you need more explanation.I will try my best.
UPDATE:
I had done the following code from a Console application:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Google.Contacts;
using Google.GData.Contacts;
using Google.GData.Client;
using Google.GData.Extensions;
namespace IMAPCommands
{
class Program
{
static void Main(string[] args)
{ GoogleContactService.InitializeService("mailid", "password");
List<ContactDetail> test = GoogleContactService.GetContacts("System Group: My Contacts");
//Use break point here
Console.ReadLine();
}
public class GoogleContactService
{
#region Properties
public static ContactsService GContactService = null;
#endregion
#region Methods
public static void InitializeService(string username, string password)
{
GContactService = new ContactsService("Contact Infomation");
GContactService.setUserCredentials(username, password);
}
public static List<ContactDetail> GetContacts(string GroupName = null)
{
List<ContactDetail> contactDetails = new List<ContactDetail>();
ContactsQuery contactQuery = new ContactsQuery(ContactsQuery.CreateContactsUri("default"));
contactQuery.NumberToRetrieve = 1000;
if (!String.IsNullOrEmpty(GroupName))
{
GroupEntry ge = GetGroup(GroupName);
if (ge != null)
contactQuery.Group = ge.Id.AbsoluteUri;
}
else
{
string groupName = "";
GroupEntry ge = GetGroup(groupName);
if (ge != null)
contactQuery.Group = ge.Id.AbsoluteUri;
}
ContactsFeed feed = GContactService.Query(contactQuery);
foreach (ContactEntry entry in feed.Entries)
{
if (entry.Title.Text == "TechnicalBulletinName")
{
int test = entry.Emails.Count;
ContactDetail contact = new ContactDetail
{
Name = entry.Title.Text,
EmailAddress1 = entry.Emails.Count >= 1 ? entry.Emails[0].Address : "",
EmailAddress2 = entry.Emails.Count >= 2 ? entry.Emails[1].Address : "",
Phone1 = entry.Phonenumbers.Count >= 1 ? entry.Phonenumbers[0].Value : "",
Phone2 = entry.Phonenumbers.Count >= 2 ? entry.Phonenumbers[1].Value : "",
Address = entry.PostalAddresses.Count >= 1 ? entry.PostalAddresses[0].FormattedAddress : "",
Details = entry.Content.Content
};
contact.UserDefinedFields = new List<UDT>();
foreach (var udt in entry.UserDefinedFields)
{
contact.UserDefinedFields.Add(new UDT { Key = udt.Key, Value = udt.Value });
}
contactDetails.Add(contact);
}
}
return contactDetails;
}
#endregion
#region Helpers
public static GroupEntry GetGroup(string GroupName)
{
GroupEntry groupEntry = null;
GroupsQuery groupQuery = new GroupsQuery(GroupsQuery.CreateGroupsUri("default"));
groupQuery.NumberToRetrieve = 100;
GroupsFeed groupFeed = GContactService.Query(groupQuery);
foreach (GroupEntry entry in groupFeed.Entries)
{
if (entry.Title.Text.Equals(GroupName, StringComparison.CurrentCultureIgnoreCase))
{
groupEntry = entry;
break;
}
}
return groupEntry;
}
#endregion
}
public class ContactDetail
{
public string Name { get; set; }
public string EmailAddress1 { get; set; }
public string EmailAddress2 { get; set; }
public string Phone1 { get; set; }
public string Phone2 { get; set; }
public string Address { get; set; }
public string Details { get; set; }
public string Pipe { get; set; }
public string Relationship { get; set; }
public string Status { get; set; }
public List<UDT> UserDefinedFields { get; set; }
}
public class UDT
{
public string Key { get; set; }
public string Value { get; set; }
}
}
Still not able to get list of contacts which are member of group TechnicalBulletinName. I am only able to get emailID of this group not members of the group.
I have an issue with serialization. I understand that methods can not be serialized for good reason, so I created a factory class to convert my existing class into a more manageable class.
This is the original class:
using Assets.Components;
using Assets.Data;
using IO.Components;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace Assets
{
[Serializable]
public class Asset
{
#region Fields
Metadata _metadata;
string _fileName;
string _companyId;
#endregion
#region Properties
[Required]
public string DisplayName { get; set; }
public string Description { get; set; }
public string Tags { get; set; }
public int Id { get; set; }
public int CategoryId { get; set; }
public AssetType Type { get; set; }
public int LanguageId { get; set; }
public int StatusId { get; set; }
public DateTime DateCreated { get; set; }
public long DateCreatedMilliseconds { get { return DateCreated.ToJavaScriptMilliseconds(); } }
public int Views { get; set; }
public int Downloads { get; set; }
public string ThumbNail { get; set; }
public string Filename
{
set { _fileName = value; }
}
[Required]
public string CompanyId
{
set { _companyId = value; }
}
public string GetBaseDirectory
{
get { return "/Public/Uploads/" + this._companyId + "/0"; }
}
public double Rating
{
get
{
List<int> Score = new List<int>();
foreach (IRating oRating in this.Ratings())
{
Score.Add(oRating.Score);
}
return (Score.Count > 0) ? Score.Average() : 0;
}
}
public Metadata Metadata
{
get
{
if (_metadata == null)
{
_metadata = new Metadata(this.Id);
if (_metadata.AssetId == 0)
{
try
{
if (GetFilename() != null)
{
string path = System.IO.Path.Combine(HttpContext.Current.Server.MapPath(this.GetBaseDirectory), GetFilename());
if (!System.IO.File.Exists(path))
_metadata = new Metadata();
else
{
_metadata = MetadataExtractor.Create(path, this.Id);
_metadata.save();
}
}
else
{
_metadata = new Metadata();
}
}
catch
{
_metadata = new Metadata();
}
}
}
return _metadata;
}
}
public bool IsConverted { get; set; }
public string UserId { get; set; }
public DateTime DateModified { get; set; }
public long DateModifiedMilliseconds { get { return DateCreated.ToJavaScriptMilliseconds(); } }
public string Culture { get; set; }
public string Language { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public int CategoryCount { get; set; }
public int AssetCount { get; set; }
public bool IgnoreRights { get; set; }
#endregion
#region Contructors
/// <summary>
/// Default constructor
/// </summary>
public Asset()
{
}
/// <summary>
/// Get's the asset from the database, but set's the status to the profiles Requires Approval state.
/// </summary>
/// <param name="Id">Asset Id</param>
/// <param name="IsViewing">Boolean to update the reports table</param>
/// <param name="IsDownloading">Boolean to update the reports table</param>
public Asset(int Id, string UserId, string CompanyId, bool IsViewing, bool IsDownloading)
{
try
{
Asset oAsset = AssetData.GetAsset(Id, IsViewing, IsDownloading, UserId, CompanyId);
// Assign the values to this class
this.Id = oAsset.Id;
this.DisplayName = oAsset.DisplayName;
this.IsConverted = oAsset.IsConverted;
this.StatusId = oAsset.StatusId;
this.Type = oAsset.Type;
this.UserId = oAsset.UserId;
this.UserName = oAsset.UserName;
this.CompanyId = oAsset.GetCompanyId();
this.Description = oAsset.Description;
this.Tags = oAsset.Tags;
this.LanguageId = oAsset.LanguageId;
this.Culture = oAsset.Culture;
this.Language = oAsset.Language;
if (oAsset.ThumbNail != null) this.ThumbNail = oAsset.ThumbNail;
this.Filename = oAsset.GetFilename();
if (oAsset.Views != 0) this.Views = oAsset.Views;
if (oAsset.Downloads != 0) this.Downloads = oAsset.Downloads;
}
catch (Exception ex)
{
Stars.BLL.Error.Handling.LogError("Skipstone", "Asset", "Asset", ex.Message, ex.ToString()); // Record our error
}
}
/// <summary>
/// Used for executing some of the public methods
/// </summary>
/// <param name="Id">Id of the asset to retrieve</param>
/// <param name="CompanyId">The CompanyId of the company for the User</param>
public Asset(int Id, string CompanyId)
{
this.Id = Id;
this.CompanyId = CompanyId;
}
#endregion
#region Public methods
public string GetCompanyId()
{
return _companyId;
}
public string GetFilename()
{
return _fileName;
}
public string GetThumbnail()
{
return this.GetBaseDirectory + "/" + this.ThumbNail;
}
public string GetSmallThumbnail()
{
return this.GetBaseDirectory + "/sml_" + this.ThumbNail;
}
public Collection<IRating> Ratings()
{
Collection<IRating> oRatings = new Collection<IRating>();
try
{
oRatings = RatingData.get(this.Id);
}
catch
{
// record our error
}
return oRatings;
}
public Collection<IComment> Comments()
{
Collection<IComment> oComments = new Collection<IComment>();
try
{
oComments = CommentData.getAssetComments(this.Id);
}
catch (Exception ex)
{
// record our error
}
return oComments;
}
public void SaveMetadata()
{
}
public Collection<GenericType> Categories()
{
return MiscellaneousManager.AssetCategories(this.Id, GetCompanyId());
}
public void Save()
{
if (this.Id > 0)
{
AssetData.update(this);
}
else
{
Asset oAsset = AssetData.create(this);
this.Id = oAsset.Id;
this.DisplayName = oAsset.DisplayName;
this.Type = oAsset.Type;
this.UserId = oAsset.UserId;
this.CompanyId = oAsset.GetCompanyId();
this.Description = oAsset.Description;
this.Tags = oAsset.Tags;
this.LanguageId = oAsset.LanguageId;
this.Culture = oAsset.Culture;
this.Language = oAsset.Language;
if (oAsset.ThumbNail != null) this.ThumbNail = oAsset.ThumbNail;
this.Filename = oAsset.GetFilename();
if (oAsset.Views != 0) this.Views = oAsset.Views;
if (oAsset.Downloads != 0) this.Downloads = oAsset.Downloads;
}
}
public void delete()
{
AssetData.delete(this.Id);
AssetManager.RemoveFromCache(this);
}
#endregion
}
}
and this is my factory method:
private static SerialisedAsset AssetFactory(Assets.Asset Object)
{
SerialisedAsset FactoryObject = new SerialisedAsset()
{
Id = Object.Id,
Name = Object.DisplayName,
UserId = Object.UserId,
UserName = Object.UserName,
CompanyId = Object.GetCompanyId(),
Description = Object.Description,
Tags = Object.Tags,
DateCreated = Object.DateCreated,
Path = Object.GetBaseDirectory,
FileName = Object.GetFilename(),
ThumbnailName = Object.ThumbNail
};
return FactoryObject;
}
which is part of my audittrailmanager class:
using Assets;
using Core;
using Reports.Objects;
using System;
using System.IO;
using System.Xml.Serialization;
namespace Reports.Components
{
public static class AuditTrailManager
{
#region Public methods
public static Audit AuditTrailFactory(Profile Profile, Object Object, Event Event)
{
Audit Audit = new Audit(SerializeObject(Object))
{
UserId = Profile.UserId,
UserName = Profile.UserName,
CompanyId = Profile.CompanyId,
ObjectName = GetObjectNameFromType(Object.GetType().ToString()),
Event = Event
};
return Audit;
}
#endregion
#region Private methods
private static string GetObjectNameFromType(string Type)
{
switch (Type)
{
case "Assets.Asset": return "Asset";
case "Core.SiteSetting": return "CompanySettings";
}
return "";
}
private static string SerializeObject(Object Object)
{
string ObjectType = Object.GetType().ToString();
switch (ObjectType)
{
case "Assets.Asset": return Serialize(AssetFactory((Asset)Object));
}
return ""; // If we fail
}
private static string Serialize(Object Object)
{
XmlSerializer ser = new XmlSerializer(Object.GetType());
using (StringWriter Xml = new StringWriter())
{
ser.Serialize(Xml, Object);
return (Xml.ToString());
}
}
private static SerialisedAsset AssetFactory(Assets.Asset Object)
{
SerialisedAsset FactoryObject = new SerialisedAsset()
{
Id = Object.Id,
Name = Object.DisplayName,
UserId = Object.UserId,
UserName = Object.UserName,
CompanyId = Object.GetCompanyId(),
Description = Object.Description,
Tags = Object.Tags,
DateCreated = Object.DateCreated,
Path = Object.GetBaseDirectory,
FileName = Object.GetFilename(),
ThumbnailName = Object.ThumbNail
};
return FactoryObject;
}
#endregion
}
}
What I am trying to do is create an audit trail which records the object I am working on (in this case an asset) and I am serializing the class and inserting it into the database for use in reporting, etc.
My question is; is this the way to do it. Is there a better way?