I have some code that uses Azure Storage as a repository for serialized JSON objects. I recently set up a method to go through and pick up every file named location.json containing a single object inside a number of directories.
When I first tested the code the deserialization failed because there were brackets around my object. However, when I downloaded the file, the array declaration was not there. I cannot for the life of me figure out where the array declaration is coming from in my code, and it's forcing me to change the way I think about using storage as a result. Has anyone else run into this?
Here's what I ended up using, which works but is also very slow.
public async Task<List<T>> GetAllAsync<T>(string delimiter)
{
var ret = new List<T>();
var blobs = client.GetBlobsByHierarchyAsync(delimiter:delimiter); // "*/location.json"
await foreach (var blobItem in blobs)
{
if (blobItem == null) continue;
log.LogInformation("{Prefix}",blobItem.Prefix);
var blob = client.GetBlobClient(blobItem.Blob.Name);
await using var stm = await blob.OpenReadAsync(new BlobOpenReadOptions(allowModifications: false)
{ Position = 0 });
if (stm == null) continue;
using var sr = new StreamReader(stm);
var s = await sr.ReadToEndAsync();
if (s.First() == '[')
{
log.LogInformation("{Type} serialized as array, taking 'first' item",typeof(T));
var list = JsonSerializer.Deserialize<List<T>>(s);
if (list == null)
{
log.LogInformation("deserialized a null array");
continue;
}
ret.Add(list[0]);
}
else
{
var l = JsonSerializer.Deserialize<T>(s);
ret.Add(l);
}
}
return ret;
}
I have the problem with counting the messages of mailbox.
I use c# and Microsoft.Graph 1.18.0
Here is my code
public async Task<long> GetItemsCountAsync(string userId)
{
var countOption = new QueryOption("$count", "true");
var request = ServiceClient.Value.Users[userId].Messages.Request();
request.QueryOptions.Add(countOption);
var resultMessages = new List<Message>();
var count = 0L;
do
{
var messagesResult = await request.GetAsync();
if (messagesResult.AdditionalData != null && messagesResult.AdditionalData.TryGetValue("#odata.count", out var messagesCount))
{
count = (long)messagesCount;
}
resultMessages.AddRange(messagesResult);
request = messagesResult.NextPageRequest;
}
while (request != null);
return count;
}
And I have at the end count = 1417 and resultMessages.Count = 760
Did I miss something?
Thank you for any help!
Everything is fine with the provided example. It appears $count for List messages endpoint could not be trusted here since API does not return accurate count for messages from a specified search folder (refer, for example, this answer for a more details).
To get messages count List mailFolders endpoint could be utilized instead:
GET /users/{id | userPrincipalName}/mailFolders?$select=totalItemCount
where totalItemCount represents the number of items in the mail folder.
C# example
var folders = await graphClient.Users[userId].MailFolders.Request().Select(f =>f.TotalItemCount).GetAsync();
var totalMessagesCount = folders.Sum(folder => folder.TotalItemCount);
I have this piece of code in C# using InstaSharper to return information of a media id from Instagram.
public async Task<UserSessionData> SignIn(string userName, string password)
{
userSessionData = new UserSessionData();
userSessionData.UserName = "username";
userSessionData.Password = "password";
api = InstaApiBuilder.CreateBuilder()
.SetUser(userSessionData)
.Build();
var loginRequest = await api.LoginAsync();
if (loginRequest.Succeeded && api.IsUserAuthenticated)
{
IResult<InstaUser> userSearch = await api.GetUserAsync(userName);
IResult<InstaMediaList> media = await api.GetUserMediaAsync(userName, PaginationParameters.MaxPagesToLoad(1));
IResult<InstaMedia> mediaInfo = await api.GetMediaByIdAsync("1924613027431050955");
return userSessionData;
}
else
{
return null;
}
}
GetMediaByIdAsync method correctly returns data about the requested media but the Likers and Tags collection is empty. Is there any way to include those data?
Had the same issue, I found the solution.
Try using this code:
var posts = await api.GetUserMediaAsync("username", PaginationParameters.MaxPagesToLoad(Int32.MaxValue)); // If you want to load all of the posts. If not, replace the "Int32.MaxValue" with the amount of posts you want to load
foreach (var post in posts.Value)
{
var likers = await api.GetMediaLikersAsync(post.InstaIdentifier);
foreach (var liker in likers.Value)
{
Console.WriteLine(liker.UserName);
}
}
This works fine for me, try it out, Im sure it will work for you as well.
I am trying to perform paginated search on Active Directory using System.DirectoryServices.Protocols.PageResultRequestControl.
I do get the search results in pages, however, the searchResponse that I get does NOT have the correct TotalCount for total number of pages.
Is it not supported? Or am I missing something here?
This is sample code that I have used in order to implement above. I am using System.DirectoryServices.Protocols to query Active Directory.
When PageResultRequestControl is added with page number, everything works perfectly except for totalSize.
For example, in this code
LdapConnection connection = new LdapConnection(ldapDirectoryIdentifier, credential);
SearchRequest sr = new SearchRequest("", "(displayName=*)", System.DirectoryServices.Protocols.SearchScope.Subtree, new[] { "displayName"});
PageResultRequestControl pr = new PageResultRequestControl(50);
SearchOptionsControl so = new SearchOptionsControl(SearchOption.DomainScope);
sr.Controls.Add(pr);
sr.Controls.Add(so);
SearchResponse searchResponse;
while (true)
{
searchResponse = (SearchResponse)connection.SendRequest(sr);
if (searchResponse.Controls.Length != 1 || !(searchResponse.Controls[0] is PageResultResponseControl))
{
totalPageCount = 0;
return null;
}
PageResultResponseControl pageResponse = (PageResultResponseControl)searchResponse.Controls[0];
totalPageCount = pageResponse.TotalCount;
if (pageResponse.Cookie.Length == 0)
{
break;
}
else
{
pageRequest.Cookie = pageResponse.Cookie;
}
}
As documentation says, the TotalCount property contains the estimated result set count (https://technet.microsoft.com/en-us/library/system.directoryservices.protocols.pageresultresponsecontrol.totalcount)
I want to get Bitcoin value for corresponding USD value and store it in table or variable. I got this URL from which I can get a Bitcoin value for USK amount. I searched on blockchain and I found this URL.
For example:
500usd = 0.76105818 btc
I tried:
https://blockchain.info/tobtc?currency=USD&value=500
at the end, its USD value which we want to convert in Bitcoin.
I want to get the result in the variable in C# (backend).
How can I accomplish this?
You need to just make call to server and parse the response.
var uri = String.Format("https://blockchain.info/tobtc?currency=USD&value={0}", 500);
WebClient client = new WebClient();
client.UseDefaultCredentials = true;
var data = client.DownloadString(uri);
var result = Convert.ToDouble(data);
Install-Package CoinMarketCapClient
using CoinMarketCap;
public static async Task<double> GetBitcoinInUsd(double usd){
//https://api.coinmarketcap.com/v1/ticker/bitcoin/
CoinMarketCapClient client = CoinMarketCapClient.GetInstance();
var entity = await client.GetTickerAsync("bitcoin");
return entity.PriceUsd * usd;
}
var uri = String.Format(#"https://blockchain.info/tobtc?currency=USD&value={0}",1);
WebClient client = new WebClient();
client.UseDefaultCredentials = true;
var data = client.DownloadString(uri);
var result = 1/Convert.ToDouble(data.Replace('.',',')); //you will receive 1 btc = result;
There are several APIs out there that will allow you to request the prices for a list of crypto currencies, and/or fiat currencies. The problem is that all the APIs do it in a disparate way. The follow on from that is that any one could be down at any given time, so you need to have some failure tolerance built in. I.e. the code should attempt to use one API, and if that fails, move to the next. Of course, this is further complicated by the fact that price is subjective and localised to a given country, exchange and so on. So, getting an accurate value is very difficult.
Here is example Crypto Compare client from CryptoCurrency.Net (https://github.com/MelbourneDeveloper/CryptoCurrency.Net/blob/master/src/CryptoCurrency.Net/APIClients/PriceEstimationClients/CryptoCompareClient.cs):
public class CryptoCompareClient : PriceEstimationClientBase, IPriceEstimationClient
{
public CryptoCompareClient(IRestClientFactory restClientFactory) : base(restClientFactory)
{
RESTClient = restClientFactory.CreateRESTClient(new Uri("https://min-api.cryptocompare.com"));
}
protected override Func<GetPricesArgs, Task<EstimatedPricesModel>> GetPricesFunc { get; } = async a =>
{
var retVal = new EstimatedPricesModel();
if (a.Currencies.ToList().Count == 0)
{
return retVal;
}
retVal.LastUpdate = DateTime.Now;
var symbolsPart = string.Join(",", a.Currencies.Select(c => c.Name));
var priceJson = await a.RESTClient.GetAsync<string>($"data/pricemultifull?fsyms={symbolsPart}&tsyms={a.FiatCurrency}");
var jObject = (JObject)JsonConvert.DeserializeObject(priceJson);
var rawNode = (JObject)jObject.First.First;
foreach (JProperty coinNode in rawNode.Children())
{
var fiatNode = (JProperty)coinNode.First().First;
var allProperties = fiatNode.First.Children().Cast<JProperty>().ToList();
var change24HourProperty = allProperties.FirstOrDefault(p => string.Compare(p.Name, "CHANGEPCT24HOUR", true) == 0);
var priceProperty = allProperties.FirstOrDefault(p => string.Compare(p.Name, "PRICE", true) == 0);
var price = (decimal)priceProperty.Value;
var change24Hour = (decimal)change24HourProperty.Value;
retVal.Result.Add(new CoinEstimate { CurrencySymbol = new CurrencySymbol(coinNode.Name), ChangePercentage24Hour = change24Hour, FiatEstimate = price, LastUpdate = DateTime.Now });
}
//Extreme hack. It's better to show zero than nothing at all and get the coins stuck
foreach (var currency in a.Currencies)
{
if (retVal.Result.FirstOrDefault(ce => ce.CurrencySymbol.Equals(currency)) == null)
{
retVal.Result.Add(new CoinEstimate { ChangePercentage24Hour = 0, CurrencySymbol = currency, FiatEstimate = 0, LastUpdate = DateTime.Now });
}
}
return retVal;
};
}
The PriceEstimationManager will flick through APIs until it finds one that works (https://github.com/MelbourneDeveloper/CryptoCurrency.Net/blob/master/src/CryptoCurrency.Net/APIClients/PriceEstimationClients/PriceEstimationManager.cs):
public class PriceEstimationManager
{
#region Fields
private readonly Collection<IPriceEstimationClient> _Clients = new Collection<IPriceEstimationClient>();
#endregion
#region Constructor
public PriceEstimationManager(IRestClientFactory restClientFactory)
{
foreach (var typeInfo in typeof(PriceEstimationManager).GetTypeInfo().Assembly.DefinedTypes)
{
var type = typeInfo.AsType();
if (typeInfo.ImplementedInterfaces.Contains(typeof(IPriceEstimationClient)))
{
_Clients.Add((IPriceEstimationClient)Activator.CreateInstance(type, restClientFactory));
}
}
}
#endregion
#region Public Methods
/// <summary>
/// TODO: This needs to be averaged. The two current clients give wildly different values. Need to include some Australian exchanges etc.
/// </summary>
public async Task<EstimatedPricesModel> GetPrices(IEnumerable<CurrencySymbol> currencySymbols, string fiatCurrency)
{
//Lets try a client that hasn't been used before if there is one
var client = _Clients.FirstOrDefault(c => c.AverageCallTimespan.TotalMilliseconds == 0);
var currencies = currencySymbols.ToList();
if (client != null)
{
try
{
return await client.GetPrices(currencies, fiatCurrency);
}
catch
{
//Do nothing
}
}
foreach (var client2 in _Clients.OrderBy(c => c.SuccessRate).ThenBy(c => c.AverageCallTimespan).ToList())
{
try
{
return await client2.GetPrices(currencies, fiatCurrency);
}
catch (Exception ex)
{
Logger.Log("Error Getting Prices", ex, nameof(PriceEstimationManager));
}
}
throw new Exception("Can't get prices");
}
#endregion
}
At a higher level, you can use the code like this (https://github.com/MelbourneDeveloper/CryptoCurrency.Net/blob/master/src/CryptoCurrency.Net.UnitTests/PricingTests.cs):
public async Task GetUSDBitcoinPrice()
{
var priceEstimationManager = new PriceEstimationManager(new RESTClientFactory());
var estimatedPrice = await priceEstimationManager.GetPrices(new List<CurrencySymbol> { CurrencySymbol.Bitcoin }, "USD");
Console.WriteLine($"Estimate: {estimatedPrice.Result.First().FiatEstimate}");
}
As more pricing clients are added, it will get more and more reliable.