How to properly call local storage class? - asynchronous

I've just implemented some localStorage functions in a class to a song lyrics app I'm developing and I think I'm calling it wrong in some way but not sure how. Either that or something is blocking the async function from completing.
Storage Class
public class Sections
{
readonly string searchesFileName = "RecentSearches.txt";
readonly string songsFileName = "RecentSongs.txt";
readonly string playlistFileName = "Playlists.txt";
IFolder localFolder = FileSystem.Current.LocalStorage;
public async void VerifySectionFiles()
{
ExistenceCheckResult searchFileExists = await localFolder.CheckExistsAsync(searchesFileName);
if (searchFileExists != ExistenceCheckResult.FileExists)
{
await localFolder.CreateFileAsync(searchesFileName, CreationCollisionOption.FailIfExists);
}
ExistenceCheckResult songsFileExists = await localFolder.CheckExistsAsync(songsFileName);
if (songsFileExists != ExistenceCheckResult.FileExists)
{
await localFolder.CreateFileAsync(songsFileName, CreationCollisionOption.FailIfExists);
}
ExistenceCheckResult playlistFileExists = await localFolder.CheckExistsAsync(playlistFileName);
if (playlistFileExists != ExistenceCheckResult.FileExists)
{
await localFolder.CreateFileAsync(playlistFileName, CreationCollisionOption.FailIfExists);
}
}
public async void AddRecentSong(string title, int id, string artist)
{
Song[] recentSongs = await ReadRecentSongsFromFile() ?? new Song[10];
recentSongs[9] = null;
for (int i = 9; i > 0; i--)
{
recentSongs[i] = recentSongs[i - 1];
}
recentSongs[0] = new Song(title, artist, id);
IFile songFile = await localFolder.CreateFileAsync(songsFileName, CreationCollisionOption.OpenIfExists);
string songsJsonString = JsonConvert.SerializeObject(recentSongs);
await songFile.WriteAllTextAsync(songsJsonString);
}
public async Task<Song[]> ReadRecentSongsFromFile()
{
IFile recentSongs = await localFolder.CreateFileAsync(songsFileName, CreationCollisionOption.OpenIfExists).ConfigureAwait(false);
string songsJsonString = await recentSongs.ReadAllTextAsync();
Song[] songsArray = JsonConvert.DeserializeObject<Song[]>(songsJsonString);
return songsArray;
}
public async void AddRecentSearch(string searchTerm)
{
string[] recentSearches = await ReadRecentSearchesFromFile() ?? new string[10];
recentSearches[9] = null;
for (int i = 9; i > 0; i--)
{
recentSearches[i] = recentSearches[i - 1];
}
recentSearches[0] = searchTerm;
IFile songFile = await localFolder.CreateFileAsync(songsFileName, CreationCollisionOption.OpenIfExists);
string songsJsonString = JsonConvert.SerializeObject(recentSearches);
await songFile.WriteAllTextAsync(songsJsonString);
}
public async Task<string[]> ReadRecentSearchesFromFile()
{
IFile recentSearches = await localFolder.CreateFileAsync(searchesFileName, CreationCollisionOption.OpenIfExists);
string searchesJsonString = await recentSearches.ReadAllTextAsync();
string[] searchesArray = JsonConvert.DeserializeObject<string[]>(searchesJsonString);
return searchesArray;
}
public async void CreatePlaylist(Playlist playlist)
{
List<Playlist> playlists = await ReadPlaylistsFromFile()?? new List<Playlist>();
playlists.Add(playlist);
IFile playlistsFile = await localFolder.CreateFileAsync(playlistFileName, CreationCollisionOption.OpenIfExists);
string playlistsJsonString = JsonConvert.SerializeObject(playlists);
await playlistsFile.WriteAllTextAsync(playlistsJsonString);
}
public async void RemovePlaylist(Playlist playlist)
{
List<Playlist> playlists = await ReadPlaylistsFromFile() ?? new List<Playlist>();
Playlist playlistToRemove = playlists.Find(x => x == playlist);
playlists.Remove(playlistToRemove);
IFile playlistsFile = await localFolder.CreateFileAsync(playlistFileName, CreationCollisionOption.OpenIfExists);
string playlistsJsonString = JsonConvert.SerializeObject(playlists);
await playlistsFile.WriteAllTextAsync(playlistsJsonString);
}
public async Task<List<Playlist>> ReadPlaylistsFromFile()
{
IFile playlists = await localFolder.CreateFileAsync(playlistFileName, CreationCollisionOption.OpenIfExists);
string playlistsString = await playlists.ReadAllTextAsync();
List<Playlist> playlistList = JsonConvert.DeserializeObject<List<Playlist>>(playlistsString);
return playlistList;
}
}
And when it comes to the implementation, I've used both this by instantiating the class inside the page I'm using it:
public partial class MainPortrait : ContentView
{
Sections sections = new Sections();
public string[] RecentSearches = new string[10];
public string Search { get; set; }
public MainPortrait()
{
InitializeComponent();
BindingContext= this;
sections.VerifySectionFiles();
RecentSearches = sections.ReadRecentSearchesFromFile().Result;
//Do stuff with returned string[]
}
And this, where I added it to the App.xaml.cs
public partial class MainPortrait : ContentView
{
public string[] RecentSearches = new string[10];
public string Search { get; set; }
public MainPortrait()
{
InitializeComponent();
BindingContext= this;
((App)App.Current).sections.VerifySectionFiles();
RecentSearches = ((App)App.Current).sections.ReadRecentSearchesFromFile().Result;
//Do stuff with returned string[]
and it had the same problem both times, so I'm assuming it's a problem with the function itself. And if that's the case, there is probably a similar problem with all the functions in the Section class.
Any ideas?

Related

FindOneAndUpdateAsync Intermittently Returning Null

I am using MongoDB.Driver for .NET Core 3.1 and running into an issue were records are not being saved properly. They are intermittently coming back as null when calling FindOneAndUpdateAsync. I have a script that calls my below code 100 times. Out of those 100, 1-5 fail in the last method, SetChildFavoritesAsync. The results came back as null. Any suggestions on what I am doing wrong?
Example Calls
var id = 1;
var childName = "test";
var collectionEntry = await FindByIdOrCreateAsync(id);
collectionEntry.Children = new List<MyCollection.ChildClass>{
new MyCollection.ChildClass{
Name = childName,
Favorites = new List<MyCollection.ChildClass.Favorite>()
}
};
await FindByIdAndUpdateChildrenAsync(collectionEntry.Id, collectionEntry.Children);
var favorites = new List<MyCollection.ChildClass.Favorite>{
Name = "testFavorite"
};
var resultsOfSet = await SetChildFavoritesAsync(id, name, favorites)
//do stuff with resultsOfSet
Example Model
public class MyCollection
{
[MongoDB.Bson.Serialization.Attributes.BsonRepresentation(BsonType.ObjectId)]
[MongoDB.Bson.Serialization.Attributes.BsonId]
public string _Id { get; set; }
[MongoDB.Bson.Serialization.Attributes.BsonRequired]
public int Id { get; set; }
public List<ChildClass> Children { get; set; }
public class ChildClass
{
public string Name { get; set; }
public List<Favorite> Favorites { get; set; }
public class Favorite
{
public string Name { get; set; }
}
}
}
Example Methods
public async Task<MyCollection> FindByIdOrCreateAsync(int id)
{
var filter = Builders<MyCollection>.Filter.Eq(mc => mc.Id, id);
var update = Builders<MyCollection>.Update
.Set(mc => mc.Id, id)
.SetOnInsert(mc => mc.Children, new List<MyCollection.ChildClass>());
var options = new FindOneAndUpdateOptions<MyCollection> { ReturnDocument = ReturnDocument.After, IsUpsert = true };
return await _database.GetCollection<MyCollection>("MyCollectionName").FindOneAndUpdateAsync(filter, update, options);
}
public async Task<MyCollection> FindByIdAndUpdateChildrenAsync(int collectionId, List<MyCollection.ChildClass> children)
{
var filter = Builders<MyCollection>.Filter.Eq(mc => mc.Id, collectionId);
var update = Builders<MyCollection>.Update.Set(mc => mc.Children, children);
var options = new FindOneAndUpdateOptions<MyCollection> { ReturnDocument = ReturnDocument.After, IsUpsert = false };
return await _database.GetCollection<MyCollection>("MyCollectionName").FindOneAndUpdateAsync(filter, update, options);
}
public async Task<MyCollection> SetChildFavoritesAsync(int collectionId, string childName, List<MyCollection.ChildClass.Favorite> favorites)
{
var filter = Builders<MyCollection>.Filter.Eq(mc => mc.Id, collectionId);
filter &= Builders<MyCollection>.Filter.Eq("children.name", childName);
var update = Builders<MyCollection>.Update.Set("children.$.favorites", favorites);
var options = new FindOneAndUpdateOptions<MyCollection> { ReturnDocument = ReturnDocument.After };
var results = await _database.GetCollection<MyCollection>("MyCollectionName").FindOneAndUpdateAsync(filter, update, options);
if (results == null)
{
_log.Error($"Child Favorites didn't save: collectionId:{collectionId}, childName:{childName}");
}
else
{
_log.Debug($"Child Favorites: collectionId:{collectionId}, childName:{childName}, favorites:{Newtonsoft.Json.JsonConvert.SerializeObject(results)}");
}
return results;
}
Appears to be an issue with communication to the database. I added some retry logic, which solved the issue.

Not displaying items from Cosmos db

I have issuse with my display method. I have been following tutorial on MSToDo items for xamarin. https://github.com/Azure-Samples/azure-cosmos-db-sql-xamarin-getting-started
I am able to insert in the database so i know it works but cant get anything out of the database. Can you help me please?
this is my get method
static DocumentClient docClient = null;
static readonly string databaseName = "xxxxx";
static readonly string collectionName = "xxxxx";
static bool Initialize() //connection
{
if (docClient != null)
return true;
try
{
docClient = new DocumentClient(new Uri(AppConstants.CosmosEndpointUrl), AppConstants.CosmosAuthKey);
}
catch (Exception ex)
{
Debug.WriteLine(ex);
docClient = null;
return false;
}
return true;
}
public async static Task<List<Post>> GetPosts()
{
var posts = new List<Post>();
if (! Initialize())
return posts;
var postQuery = docClient.CreateDocumentQuery<Post>(
UriFactory.CreateDocumentCollectionUri(databaseName, collectionName),
new FeedOptions { MaxItemCount = 1, EnableCrossPartitionQuery = true })
.OrderBy(i => i.Date)
.AsDocumentQuery();
while (postQuery.HasMoreResults)
{
var queryResults = await postQuery.ExecuteNextAsync<Post>();
posts.AddRange(queryResults);
}
return posts;
}
public class PostViewModel : BaseViewModel
{
List<Post> posts;
public PostViewModel()
{
Posts = new List<Post>();
RefreshCommand = new Command(async () => await ExecuteRefreshCommand());
}
private PostViewModel _selectedAd;
//private ObservableCollection<Post> _posts;
public List<Post> Posts { get => posts; set { posts = value; OnPropertyChanged(); } }
public ICommand RefreshCommand { get; }
async Task ExecuteRefreshCommand()
{
if (IsBusy) return;
IsBusy = true;
try
{
Posts = await AdService.GetPosts();
}
finally
{
IsBusy = false;
}
}
}
HOmePage
PostViewModel postViewModel;
public HomePage()
{
InitializeComponent();
postViewModel = new PostViewModel();
BindingContext = postViewModel;
}
protected override void OnAppearing()
{
base.OnAppearing();
postViewModel.RefreshCommand.Execute(null);
}
And my xaml
<ListView
ItemsSource="{Binding Posts}" x:Name="AdLogListView"
ItemTemplate="{StaticResource HomePageTemplate}"
SelectionMode="Single" Margin="12,0">
The Binding Source Path should be Posts and not Post. Your modified xaml would be:-
<ListView
ItemsSource="{Binding Posts}" x:Name="AdLogListView"
ItemTemplate="{StaticResource HomePageTemplate}"
SelectionMode="Single" Margin="12,0">

How to disable / invalidate JWT tokens?

This is how I create JWT tokens for my .NET Core API and it's working perfectly fine, but I'd like to implement the possibility to revoke, disable or invalidate JWT tokens when an HTTP request comes asking for it, with the token in the header.
I can think of a way where I would store the token in my database and have a boolean column indicating whether the token is active or not, but is there a way to do it without storing the token in the database at all?
public UserAuthenticationResponse CreateToken(UserAuthenticationRequest userAuth)
{
var user = // try to find user in database...
if (user == null)
{
return null;
}
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim("user_id", userAuth.Id),
}),
Expires = DateTime.UtcNow.AddMinutes(5),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var authenticatedUser = new UserAuthenticationResponse();
authenticatedUser.Id = user.Id;
authenticatedUser.Token = tokenHandler.WriteToken(token);
return authenticatedUser;
}
What I did in the end was create middleware which I put at the top of my pipeline. I held a List<string> that represented a list of blacklisted tokens (which I later clean up once they expire).
When I were validating the token myself, I was checking the BlacklistToken(token, timeout) method. If it returns true, I can blacklist the token and the next time the user tries to access something with that token, it won't let him do it. Then, sometime later, I call CleanupTokens(tokenProvider) which gets all tokens, checks if they're expired (thanks to the tokenProvider that gets the token expiration date) and if so, it removes them from the list.
public class TokenPair
{
[JsonProperty(PropertyName = "token")]
public string Token { get; set; }
[JsonProperty(PropertyName = "userId")]
public string UserID { get; set; }
}
public interface ITokenLocker
{
bool BlacklistToken(string token, int timeout);
void CleanupTokens(ITokenProvider tokenProvider);
bool IsBlacklisted(string token);
}
public class TokenLocker : ITokenLocker
{
private List<string> _blacklistedTokens;
public TokenLocker()
{
_blacklistedTokens = new List<string>();
}
public bool BlacklistToken(string token, int timeout)
{
lock (_blacklistedTokens)
{
if (!_blacklistedTokens.Any(x => x == token))
{
_blacklistedTokens.Add(token);
return true;
}
}
Thread.Sleep(timeout);
lock (_blacklistedTokens)
{
if (!_blacklistedTokens.Any(x => x == token))
{
_blacklistedTokens.Add(token);
return true;
}
else
return false;
}
}
public void CleanupTokens(ITokenProvider tokenProvider)
{
lock (_blacklistedTokens)
{
for (int i = 0; i < _blacklistedTokens.Count; i++)
{
var item = _blacklistedTokens[i];
DateTime expiration = tokenProvider.GetExpiration(item);
if (expiration < DateTime.UtcNow)
{
_blacklistedTokens.Remove(item);
i--;
}
}
}
}
public bool IsBlacklisted(string token)
{
return _blacklistedTokens.Any(tok => tok == token);
}
}
public class TokenMiddleware
{
private readonly RequestDelegate _next;
public TokenMiddleware(RequestDelegate next)
{
_next = next;
}
private string GetToken(HttpContext ctx)
{
ctx.Request.EnableBuffering();
using (var reader = new StreamReader(ctx.Request.Body, Encoding.UTF8, true, 1024, true))
{
var jsonBody = reader.ReadToEnd();
var body = JsonConvert.DeserializeObject<TokenPair>(jsonBody);
ctx.Request.Body.Position = 0;
if (body != null && body.Token != null)
{
return body.Token;
}
}
return string.Empty;
}
public async Task InvokeAsync(HttpContext context,
ITokenLocker tokenLocker
)
{
var ctx = context;
if (tokenLocker.IsBlacklisted(GetToken(ctx)))
{
int statusCode = (int)HttpStatusCode.Unauthorized;
ctx.Response.StatusCode = statusCode;
var response = FaziHttpResponse.Create(statusCode, "Unauthorized: Invalid / Expired token");
await context.Response.WriteAsync(JsonConvert.SerializeObject(response));
return;
}
await _next(context);
}
}

how to properly implement Microsoft.IdentityModel.Clients.ActiveDirectory in xamarin 4

After install the nuget package Microsoft.IdentityModel.Clients.ActiveDirectory
I try to acquire token via
string cloud = "https://login.microsoftonline.com/common/oauth2";
string tenantId = App.tenantId;
string authority = $"{cloud}/{tenantId}";
//
string clientId = App.clientId;
Uri redirectUri = App.redirectUrl;
string resource = clientId;
AuthenticationResult authResult = null;
AuthenticationContext authContext = new AuthenticationContext(authority);
try
{
if (authContext.TokenCache.ReadItems().Count() > 0)
{
authContext = new AuthenticationContext(authContext.TokenCache.ReadItems().First().Authority);
authResult = await authContext.AcquireTokenSilentAsync(resource, clientId);
}
else
{
authResult = await authContext.AcquireTokenAsync(resource, clientId, redirectUri, new PlatformParameters(PromptBehavior.Auto));
}
}
catch (AdalSilentTokenAcquisitionException ee)
{
authResult = await authContext.AcquireTokenAsync(resource,clientId, redirectUri,null);
}
When i try to build i get the following errors
cannot convert from 'Microsoft.IdentityModel.Clients.ActiveDirectory.PromptBehavior' to 'Android.App.Activity'
cannot convert from 'Microsoft.IdentityModel.Clients.ActiveDirectory.PromptBehavior' to 'UIKit.UIViewController'
the line causing this is line that trigger the error
authResult = await authContext.AcquireTokenAsync(resource, clientId, redirectUri, new PlatformParameters(PromptBehavior.Auto));
how do i solve this ?
Xamarin version is 4.0.0.482894
Microsoft.IdentityModel.Clients.ActiveDirectory version 5.1.0
Visual studio 2017
In your Shared project, use IPlatformParameter , something like this:
public class AuthenticationManager
{
private static string _authority;
private static string _resource;
private static string _clientId;
private static string _returnUri;
private static IPlatformParameters _parameters;
private string _accessToken;
public static UserInfo UserInfo { get; private set; }
public static void SetConfiguration(string authority, string resource, string clientId, string returnUri)
{
_authority = authority;
_resource = resource;
_clientId = clientId;
_returnUri = returnUri;
var authContext = new AuthenticationContext(_authority);
authContext.TokenCache.Clear();
}
public static void SetParameters(IPlatformParameters parameters)
{
_parameters = parameters;
}
public async Task<bool> LoginAsync()
{
_accessToken = await GetAccessTokenAsync();
return true;
}
public Task LogoutAsync()
{
var authContext = new AuthenticationContext(_authority);
var cachedToken = authContext.TokenCache.ReadItems().FirstOrDefault(t => t.Authority == _authority && t.ClientId == _clientId && t.Resource == _resource);
if (cachedToken != null)
{
authContext.TokenCache.DeleteItem(cachedToken);
}
UserInfo = null;
_accessToken = null;
return Task.CompletedTask;
}
private async Task<string> GetAccessTokenAsync()
{
var uri = new Uri(_returnUri);
var authContext = new AuthenticationContext(_authority);
var authResult = await authContext.AcquireTokenAsync(_resource, _clientId, uri, _parameters);
UserInfo = authResult.UserInfo;
return authResult.AccessToken;
}
}
Then in platform specific, call SetParameters method:
Example in Android on your MainActivity.cs :
protected override void OnCreate(Bundle bundle)
{
var platformParameters = new PlatformParameters(this);
AuthenticationManager.SetParameters(platformParameters);
}
Similarly on iOS:
public override void ViewDidLoad()
{
var platformParameters = new PlatformParameters(this);
AuthenticationManager.SetParameters(platformParameters);
}
You need to cast it to Activity
new PlatformParameters((Activity) PromptBehavior.Auto));

Xamarin forms: Load more items without button click

Dears,
I am implementing load more items to listview without a button.
My code:
public partial class DashBoardPage : ContentPage
{
ObservableCollection<string> Items;
bool isLoading;
public DashBoardPage()
{
InitializeComponent();
Items = new ObservableCollection<string>();
var listview = new ListView();
listview.ItemsSource = Items;
listview.ItemAppearing += (sender, e) =>
{
if (isLoading || Items.Count == 0)
return;
//hit bottom!
if (e.Item.ToString() == Items[Items.Count - 1])
{
LoadItems();
}
};
LoadItems();
}
public async void LoadItems()
{
isLoading = true;
HttpClient client = new HttpClient();
var response = await client.GetAsync("My Url");
string tweetJson = await response.Content.ReadAsStringAsync();
UserTweetResponse userTweetResponse = new UserTweetResponse();
if (tweetJson != "")
{
userTweetResponse = JsonConvert.DeserializeObject<UserTweetResponse>(tweetJson.ToString());
foreach (var tweet in userTweetResponse.userTweetsList)
{
Items.Add(tweet.ToString());
}
}
ListView1.ItemsSource = userTweetResponse.userTweetsList;
isLoading = false;
}
}
I refer the following link and confused with the for loop inside LoadItems():
https://montemagno.com/load-more-items-at-end-of-listview-in/
for (int i = 0; i < 20; i++)
{
Items.Add (string.Format("Item {0}", Items.Count));
}
In my case I am using itemSource property to bind the response to list view.
My model class:
public class UserTweetResponse
{
public List<UserTweetsList> userTweetsList { get; set; }
}
public class UserTweetsList
{
public int tweetId { get; set; }
public string tweetData { get; set; }
public string createdTime { get; set; }
public int commentCount { get; set; }
public int likeCount { get; set; }
public int flagCount { get; set; }
public string mediaUrl { get; set; }
public string tweetUser { get; set; }
public bool userLiked { get; set; }
public bool userFlagged { get; set; }
public bool isMediaUrlNull { get { return string.IsNullOrEmpty(mediaUrl); } }
}
How can I fix this?
Thanks in advance
You need to add your new tweets to your Items collection
public async void LoadItems()
{
isLoading = true;
HttpClient client = new HttpClient();
var response = await client.GetAsync("My Url");
string tweetJson = await response.Content.ReadAsStringAsync();
UserTweetResponse userTweetResponse = new UserTweetResponse();
if (tweetJson != "")
{
userTweetResponse = JsonConvert.DeserializeObject<UserTweetResponse>(tweetJson.ToString());
foreach (var tweet in userTweetResponse.userTweetsList)
{
Items.Add(tweet);
}
}
isLoading = false;
}
because the Observable collection is the ListView item source the new items will appear in the list.
Pasete this whole:
using System;
using System.Diagnostics;
using System.Net.Http;
using Newtonsoft.Json;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
namespace SmartTweet
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class DashBoardPage : ContentPage
{
int i = 1;
bool loadMore;
ObservableCollection<UserTweetsList> Items =new ObservableCollection<SmartTweet.UserTweetsList>();
bool isLoading;
UserTweetResponse userTweetResponse;
public DashBoardPage()
{
InitializeComponent();
ListView1.ItemAppearing += (sender, e) =>
{
if (isLoading || Items!=null && Items.Count == 0)
return;
//hit bottom
if (userTweetResponse.userTweetsList!=null && userTweetResponse.userTweetsList.Count>0)
{
UserTweetsList item = userTweetResponse.userTweetsList[userTweetResponse.userTweetsList.Count - 1];
if ((e.Item as UserTweetsList).tweetId.ToString() == item.tweetId.ToString())
{
Debug.WriteLine("Enter bottom");
loadMore = true;
UserTweetsList();
}
}
};
}
protected async override void OnAppearing()
{
await UserTweetsList();
base.OnAppearing();
}
async void ButtonClicked(Object sender, EventArgs e)
{
loadMore = true;
// await UserTweetsList();
}
public async Task UserTweetsList()
{
isLoading = true;
if (loadMore)
{
i = i + 1;
}
int countInInt = i * 3;
try
{
string applicationId = "1";
string siteId = "5";
string userId = "225";
string ownedBy = "me";
string period = "before";
string count = countInInt.ToString();
DateTime dt = DateTime.Now.ToLocalTime();
string date = dt.Year.ToString() + "-" + dt.Month.ToString() + "-" + dt.Day.ToString() + " " + dt.Hour.ToString() + ":" + dt.Minute.ToString() + ":" + dt.Second.ToString() + "." + dt.Millisecond.ToString();
HttpClient client = new HttpClient();
var response = await client.GetAsync("web service url");
string tweetJson = await response.Content.ReadAsStringAsync();
Debug.WriteLine("tweetList:>" + tweetJson);
userTweetResponse = new UserTweetResponse();
if (tweetJson != "")
{
userTweetResponse = JsonConvert.DeserializeObject<UserTweetResponse>(tweetJson.ToString());
foreach (var tweet in userTweetResponse.userTweetsList)
{
if (!Items.Contains(tweet))
{
Items.Add(tweet);
}
//Items.Add(tweet.ToString());
}
}
ListView1.ItemsSource = userTweetResponse.userTweetsList;
isLoading = false;
if (userTweetResponse.userTweetsList.Count == 0)
{
//loadMoreButton.IsVisible = false;
blue_holo_circle.IsVisible = false;
blueLine.IsVisible = false;
}
else
{
//loadMoreButton.IsVisible = true;
blue_holo_circle.IsVisible = true;
blueLine.IsVisible = true;
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Exception:>" + ex);
}
}
}
}

Resources