Windows Phone 7 - No data is delivered

Nov 12, 2012 at 10:33 AM
Edited Nov 14, 2012 at 12:19 AM

Hi Joe,

I don't know, why sometimes data is delivered, and sometimes not.

Here is a simple piece of code that is executed after a successful authentication:

  //This is the first call
                    var timelineResponse =
                               (from tweet in ctx.Status
                                where tweet.Type == StatusType.Home &&
                                tweet.Count == 20
                               select tweet)
                                   .AsyncCallback(tweets =>
                                                      {
                                                          Dispatcher.BeginInvoke(() =>
                                                                                     {
                                                                                         this.sinceID =
                                                                                             tweets.Max(
                                                                                                 x =>
                                                                                                 ulong.Parse(
                                                                                                     x.StatusID));

                                                                                        
                                                                                         maxID = tweets.Min(status => ulong.Parse(status.StatusID)) - 1;
                                                                                         sinceID = tweets.Max(status => ulong.Parse(status.StatusID)) - 1;
                                                                                     });}).ToList(); 

 

Sometimes tweets is 20 and sometimes it is zero. And I am unable to see why.

 

 

Coordinator
Nov 14, 2012 at 12:59 AM

Try this MaterializedAsyncCallback operator to see if it's more comfortable:

            (from tweet in twitterCtx.Status
             where tweet.Type == StatusType.Home
             select tweet)
            .MaterializedAsyncCallback(resp =>
             {
                 if (resp.Status != TwitterErrorStatus.Success)
                     throw resp.Error;

                 Console.WriteLine("\nTweets for " + twitterCtx.UserName + "\n");
                 foreach (var tweet in resp.State)
                 {
                     Console.WriteLine(
                         "Friend: " + tweet.User.Identifier.ScreenName +
                         "\nRetweeted by: " +
                             (tweet.Retweeted ?
                                tweet.RetweetedStatus.User.Name :
                                "Original Tweet") +
                         "\nTweet: " + tweet.Text + "\n");
                 }
             });

I'm not sure that will make a difference, but it's something I added recently because it provides access to exception details and doesn't require superfluous calls to other operators, like ToList, to materialize the query.

A few questions:

1. Do you receive an exception message in the async response?  If so, please post. Look inside the exception message for any message from Twitter, HTTP error messages, or Response properties of the TwitterQueryException.

2. Does Fiddler provide an error message from Twitter? If so, please post. (be sure to sanitize Authorization headers for security)

3. Does Fiddler show that Twitter is returning valid Json data at the times you receive 0 tweets?

Joe

Nov 14, 2012 at 1:16 AM

Hi Joe,

thank you for your reply.

1. I got a WebException, since I changed from the current code, to the code you suggested above. Here is the output of the exception:

System.Net.WebException was unhandled by user code
  HResult=-2146233079
  Message=The remote server returned an error: NotFound.
  Source=TelerikRadDataBoundListSample
  InnerException: System.Net.WebException
       HResult=-2146233079
       Message=The remote server returned an error: NotFound.
       Source=System.Windows
       InnerException: 

2. No, there are no error messages from Twitter available. Only the successful calls are shown. I assume, there is something wrong with the creation of the API call URLS. But I am not sure.

3. No. It shows only valid JSON data, when the call to Twitter was successful.

 

Here again, my whole code from Main.xaml.cs (WP7) project, Visual Studio 2012 and WP8 emu:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using LinqToTwitter;
using Microsoft.Phone.Controls;
using HtmlAgilityPack;
using Telerik.Windows.Data;


namespace TelerikRadDataBoundListSample
{
    public partial class MainPage : PhoneApplicationPage
    {
        private const string ConsumerKey = "REMOVED";
        private const string ConsumerSecret = "REMOVED";
        private PinAuthorizer authorizer = null;
        private PinAuthorizer auth = null;
        private List<Tweet> _myData;
        private TwitterContext _ctx;
        private ulong sinceID;
        private int maxStatuses = 800;
        private string _pin;
        private int _startIndex;
        private int _amount;
        private VirtualizingDataCollection _dataCollection; 
        // Constructor
        public MainPage()
        {
            InitializeComponent();
            this.Loaded += MainPage_Loaded;
        }

        public List<Tweet> MyData
        {
            get { return _myData; }
            set { _myData = value; }
        }

        public VirtualizingDataCollection DataCollection
        {
            get { return _dataCollection; }
            set { _dataCollection = value; }
        }

        private void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            this.webBrowser1.Visibility = Visibility.Visible;
            //Don't forget that, stupid!
            //Nothing works without it!
            this.webBrowser1.IsScriptEnabled = true;
            this.webBrowser1.Navigated += webBrowser1_Navigated;
            this.MyData = new List<Tweet>();
            //Initialize the data collection
            this.DataCollection = new VirtualizingDataCollection(800,20);

          

            rdHighSpeed.ItemsSource = this.DataCollection;

            if (this.IsTwitterDataAvailable())
            {
                this.webBrowser1.Visibility = Visibility.Collapsed;
                GetTimeLineData();
            }
            else
            {
                //Start the fun!
                GrabTwitterCredentials();
            }


            this.DataCollection.ItemsLoading += DataCollection_ItemsLoading;
        }

        void DataCollection_ItemsLoading(object sender, VirtualizingDataCollectionItemsLoadingEventArgs e)
        {

            this._startIndex = e.StartIndex;
            this._amount = e.Count;

            GetTimeLineData();
            
        }

        /// <summary>
        /// Gets the time line data.
        /// </summary>
        /// <param name="page">The page.</param>
        /// <param name="amount">The amount.</param>
        /// <returns></returns>
        private void GetTimeLineData()
        {
            if (this.auth.IsAuthorized)
            {

                TwitterContext ctx = new TwitterContext(this.auth);

                if (_amount == 0)
                {

                    //This is the first call
                   
                        (from tweet in ctx.Status
                         where tweet.Type == StatusType.Home
                         select tweet)
                            .MaterializedAsyncCallback(tweets =>
                                                           {

                                                               if (tweets.Status != TwitterErrorStatus.Success)
                                                                   throw tweets.Error;
                                                    

                                                               if (tweets == null)
                                                               {
                                                                   return;
                                                               }
                                                               Dispatcher.BeginInvoke(() =>
                                                                                          {
                                                                                              this.sinceID =
                                                                                                  tweets.State.Max(
                                                                                                      x =>
                                                                                                      ulong.Parse(
                                                                                                          x.StatusID));


                                                                                              maxID =
                                                                                                  tweets.State.Min(
                                                                                                      status =>
                                                                                                      ulong.Parse(
                                                                                                          status.
                                                                                                              StatusID)) -
                                                                                                  1;
                                                                                              sinceID =
                                                                                                  tweets.State.Max(
                                                                                                      status =>
                                                                                                      ulong.Parse(
                                                                                                          status.
                                                                                                              StatusID)) -
                                                                                                  1;
                                                                                          });
                                                               Dispatcher.BeginInvoke(() =>
                                                                                          {

                                                                                              //foreach (
                                                                                              //    var statuse in tweets)
                                                                                              //{
                                                                                              //    this.MyData.Add(new Tweet
                                                                                              //                        ()
                                                                                              //                        {
                                                                                              //                            Avatar
                                                                                              //                                =
                                                                                              //                                statuse
                                                                                              //                                .
                                                                                              //                                User
                                                                                              //                                .
                                                                                              //                                ProfileImageUrl,
                                                                                              //                            ScreenName
                                                                                              //                                =
                                                                                              //                                statuse
                                                                                              //                                .
                                                                                              //                                User
                                                                                              //                                .
                                                                                              //                                Name,
                                                                                              //                            Text
                                                                                              //                                =
                                                                                              //                                statuse
                                                                                              //                                .
                                                                                              //                                Text
                                                                                              //                        });
                                                                                              //}

                                                                                              //DataCollection.LoadItems(
                                                                                              //    this._startIndex,
                                                                                              //    this.MyData.Skip(
                                                                                              //        this._startIndex).
                                                                                              //        Take(
                                                                                              //            this._amount -
                                                                                              //            1));
                                                                                          });
                                                           });
                }
                //else
                //{
                //    var timelineResponse =
                //        (from tweet in ctx.Status
                //         where tweet.Type == StatusType.Home &&
                //               tweet.Count == 20 &&
                //               tweet.SinceID == sinceID &&
                //               tweet.MaxID == maxID
                //                select tweet)
                //                   .AsyncCallback(tweets =>
                //                   {
                //                       Dispatcher.BeginInvoke(() =>
                //                       {
                //                           this.sinceID =
                //                               tweets.Max(
                //                                   x =>
                //                                   ulong.Parse(
                //                                       x.StatusID));

                //                           maxID = tweets.Min(status => ulong.Parse(status.StatusID)) - 1;
                //                       });
                //                       Dispatcher.BeginInvoke(() =>
                //                       {
                //                           foreach (var status in tweets)
                //                           {

                //                               this.MyData.Add(new Tweet()
                //                               {
                //                                   Avatar =
                //                                       status.
                //                                       User.
                //                                       ProfileImageUrl,
                //                                   ScreenName =
                //                                       status.User.Name,
                //                                   Text =
                //                                       status.
                //                                       Text
                //                               });



                //                           }

                //                           if (this._amount == 0)
                //                           {
                //                               this._amount = 19;
                //                           }
                //                           DataCollection.LoadItems(this._startIndex, this.MyData.Skip(this._startIndex-1).Take(this._amount - 1));
                //                       });
                //                   }).ToList(); 
                //}


            }
        }

        /// <summary>
        /// Handles the Navigated event of the webBrowser1 control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Navigation.NavigationEventArgs" /> instance containing the event data.</param>
        private void webBrowser1_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)


        {
            //We loaded some kind of webpage ... was about time!
            if (webBrowser1.SaveToString().Contains("code"))
            {
                this.webBrowser1.Visibility = Visibility.Collapsed;

                HtmlDocument doc = new HtmlDocument();
                doc.LoadHtml(webBrowser1.SaveToString());
                var code =
                    doc.GetElementbyId("oauth_pin").ChildNodes[1].ChildNodes[3].ChildNodes[0].InnerText;

                if (code != null)
                {
                    this._pin = code;
                    SaveTwitterData(this._pin);

                }


                //Save the whole pin shit and the tokens for later re-use
            }
        }


        /// <summary>
        /// Saves the twitter data.
        /// </summary>
        private void SaveTwitterData(string pin)
        {

            

            authorizer.CompleteAuthorize(
                pin,
                completeResp => Dispatcher.BeginInvoke(() =>
                                                           {
                                                               switch (completeResp.Status)
                                                               {
                                                                   case TwitterErrorStatus.Success:
                                                                       var cred =
                                                                           authorizer.Credentials as
                                                                           IsolatedStorageCredentials;
                                                                       
                                                                       cred.Save();
                                                                       this._ctx = new TwitterContext(authorizer);
                                                                       break;
                                                                   case TwitterErrorStatus.TwitterApiError:
                                                                   case TwitterErrorStatus.RequestProcessingException:
                                                                       MessageBox.Show(
                                                                           completeResp.Error.ToString(),
                                                                           completeResp.Message,
                                                                           MessageBoxButton.OK);
                                                                       break;
                                                               }
                                                           }));
        }


        /// <summary>
        /// Determines whether [is twitter data available].
        /// </summary>
        private bool IsTwitterDataAvailable()
        {

            
            this.auth =
                new PinAuthorizer
                    {
                        Credentials = new IsolatedStorageCredentials()
                    };

        

            if (this.auth != null && this.auth.IsAuthorized)
            {

                //this._ctx = new TwitterContext(this.auth);

               
                return true;
            }
            else
            {
                return false;
            }
        }


        
        /// <summary>
        /// Grabs the twitter credentials.
        /// </summary>
        private void GrabTwitterCredentials()
        {


        authorizer = new PinAuthorizer
            {
                Credentials = new IsolatedStorageCredentials
                {
                    ConsumerKey = "REMOVED",
                    ConsumerSecret = "REMOVED"

                },
               
               GetPin = () => this._pin,
                GoToTwitterAuthorization =
                     (pageLink) =>
                     Dispatcher.BeginInvoke(
                         () =>
                         {
                             webBrowser1.Navigate(new Uri(pageLink, UriKind.Absolute));
                         }),
                OAuthAccessTokenUrl = "https://api.twitter.com/oauth/access_token",
                OAuthAuthorizeUrl = "https://api.twitter.com/oauth/authorize",
                OAuthRequestTokenUrl = "https://api.twitter.com/oauth/request_token",
               
            };





            authorizer.BeginAuthorize(
                resp => Dispatcher.BeginInvoke(() =>
                {
                    switch (resp.Status)
                    {
                        case TwitterErrorStatus.Success:
                         
                            break;
                        case TwitterErrorStatus.TwitterApiError:
                        case TwitterErrorStatus.RequestProcessingException:
                            MessageBox.Show(
                                resp.Error.ToString(),
                                resp.Message,
                                MessageBoxButton.OK);
                            break;
                    }
                }));
         
        }

        public ulong maxID { get; set; }
    }


    public class Tweet:INotifyPropertyChanged
    {

        /// <summary>
        /// The _screen name
        /// </summary>
        private string _screenName;

        /// <summary>
        /// The _text
        /// </summary>
        private string _text;

        /// <summary>
        /// The _avatar
        /// </summary>
        private string _avatar;


        /// <summary>
        /// The _screen name
        /// </summary>
        public string ScreenName
        {
            get { return _screenName; }
            set { _screenName = value; RaisePropertyChanged("ScreenName");}
        }

        /// <summary>
        /// The _text
        /// </summary>
        public string Text
        {
            get { return _text; }
            set { _text = value; RaisePropertyChanged("Text"); }
        }

        /// <summary>
        /// The _avatar
        /// </summary>
        public string Avatar
        {
            get { return _avatar; }
            set { _avatar = value; RaisePropertyChanged("Avatar"); }
        }

        #region INotifyPropertyChanged Implementation
        public event PropertyChangedEventHandler PropertyChanged;

      

        private void RaisePropertyChanged(string memberName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(memberName));
            }
        } 
        #endregion
    }
}

 

 

 

 

 

 

 

Nov 14, 2012 at 2:13 AM

Hi Joe,

after further investigations I could nail the problem:

It was my anti-virus software, messing around with Hyper-V.

As a tip for everybody else, using AVG-Antivirus (I use the free edition) add each and every Hyper-V folder to the exceptions list of AVG-Antivir. You can check your settings under Hyper-V settings (on the right side) of the Hyper-V manager.

I feel really like "Why did you not check the antivirus stuff at first place! It's always the anti-virus!"

Please excuse any inconvenience.

Thank you.

Ilija