Book review: iOS Development with Xamarin Cookbook (Dimitris Tavlikos)

I love to learn and expand my knowledge. Because of this, I was absolutely happy when I was asked for a book review about Dimitris’ iOS book.

The book is a huge collection of iOS recipes using Xamarin. The first three chapters are going deeply into the UI of an iOS application, looking on a lot (almost all) possible aspects of UI elements. What I like very much is that the author shows the code, usually with a step by step guide, and after that delivers a detailed explanation why something works in the way it does.

The next two chapters are all about creating and displaying data, files and sqlite, providing the same experience as the first chapters.

The sixth chapter is all about consuming services, such as web services, REST services or even WCF services (I wasn’t even aware of this being possible). Very good starting point for so many app ideas.

So far, the book shows already a lot of what we can do with Xamarin. But modern apps often contain media content: videos, photos, capturing media – this is what chapter 7 is all about.

Like all modern Smartphone operating systems, iOS provides some methods to let our apps interact with the OS. The 8th chapter is all about those interactions, like contacts, mail and more and has the matching real world scenarios.

The most usable apps use a device’s sensors, touch and gestures. Of course, with Apple being the leader in this space for a long time (we just need to be fair in this point), iOS has a lot of APIs for these. Chapter nine has some good recipes to help us with improving our app’s UX.

If your app needs location services and maps, chapter 10 is your friend. It shows you how to interact with Apple’s map services, add annotations and a lot more.

Users love when apps have some nice animations when something changes in an app. iOS provides a lot of options, and chapter 11 explains a lot about animations and drawing methods.

One of the most important parts when developing an app is lifecycle handling. As with any other OS, also iOS has its specific methods to handle the lifecycle. Background operations are part of this handling. In chapter 12, Dimitri tells us a lot about handling the states of an app as well as background operations.

Chapter 13 consists of tips and recipes for localization of an iOS app.

One of the most important steps when creating an iOS app is deploying the app. Apps should of course be tested on real devices, and this what chapter 14 is about – but not only. Also the required steps to prepare and app for submission as well as the submission to the store are explained.

The final chapter contains some additional recipes that can make your app more valuable like content sharing or text-to-speech.

Conclusion

I only began with Xamarin.iOS a few month ago. This book provides a great insight into development for iOS using the Xamarin IDE. As I said already, I like the approach of showing code first and then explaining what it does exactly and provide additional info if suitable. This book is absolutely worth every single cent if you want to start with iOS and Xamarin.

If you’re interested in the book, you’re just a click away: http://bit.ly/1tnxmGX

Note: This post was completely written on my phone. If you find typos, you can keep them ;-).

Book review: Learning Windows Azure Mobile Services for Windows 8 and Windows Phone 8 (Geoff Webber-Cross)

During the last months, I used the few times of my spare time when I wasn’t in the mood for programming to read Geoff’s latest book for diving deeper into Azure Mobile Services. Geoff is well known in the community for his Azure experience, and I absolutely recommend to follow him! I am really glad he asked me to review his book and need to apologize that it took so long to get this review up.

The book itself is very well structured with a true working XAML based game that utilizes both Windows 8 and Windows Phone 8 and connects them to one single Mobile Service.

Even if you are completely new to Azure, you will quickly get things done as the whole book is full of step-by-step instructions. Let’s have a quick look on what you will learn while reading this book:

  1. Prepare your Azure account and set up your first Mobile Service
  2. Bring your Mobile Service to life and connect Visual Studio
  3. Securing user’s data
  4. Create your own API endpoints
  5. use Git via the console for remote development
  6. manage Push Notifications for both Windows and Windows Phone apps
  7. use the advantages of the Notification hub
  8. Best practices for app development – some very useful general guilty tips!

I already use a Mobile Service with my Windows Phone App TweeCoMinder. I have already started a Windows 8 version of that app, which basically only needs to be connected to my existing Azure Mobile Service to finish it.

Screenshot (359)

While reading Geoff’s book, I learned how I effectively can achieve this and also improve my code for handling the push notifications on both systems. The book is an absolutely worthy investment if you look into Azure and Mobile Services and has a lot of sample code that can be reused in your own application.

As this is my first book review ever, feel free to leave your feedback in the comments.

You can buy the book right here.

Happy coding, everyone!

Save and load multiple selected items with Telerik’s RadListPicker on Windows Phone 8 & 8.1

wp_ss_20140706_0005

While I am continuing to add new features to my current main project UniShare, I am facing also problems that I never had before in my other apps.

One of those problems is to save and load multiple selected items on Telerik’s RadListPicker control. While the control itself is pretty easy to use, there is no documentation and also no blog posts on how to save and load those selected items.

If you are using Windows Phone Toolkit’s ListPicker, you should be fine by following this post I found during research for a solution. If you are using Telerik’s control like I am, this post is for you.

The main problem we have is that the SelectedItems property cannot be set directly. It has only a get accessor, which results in an error from Visual Studio if you try to set it. Luckily, there is still a way to set the saved  SelectedItems.

You need two things before we can go on: of course Telerik’s Windows Phone UI controls, and JSON.net, which we are using to serialize and deserialize our SelectedItems.

We are going to start with adding a ListPicker to our page:

            <telerikInput:RadListPicker 
                x:Name="TestPicker" Header="select items" 
                OkButtonIconUri="/Assets/PickerOK.png" 
                CancelButtonIconUri="/Assets/PickerCancel.png" 
                SelectionMode="Multiple" 
                SelectionChanged="TestPicker_SelectionChanged">
                <telerikInput:RadListPicker.PopupItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding name}" Margin="16 0 0 0" TextWrapping="Wrap"></TextBlock>
                    </DataTemplate>
                </telerikInput:RadListPicker.PopupItemTemplate>
                <telerikInput:RadListPicker.PopupHeaderTemplate>
                    <DataTemplate>
                        <TextBlock Text="choose item:" Margin="16 0 0 0" TextWrapping="Wrap" Style="{StaticResource PhoneTextTitle2Style}"></TextBlock>
                    </DataTemplate>
                </telerikInput:RadListPicker.PopupHeaderTemplate>
            </telerikInput:RadListPicker>

Pretty easy to use, right? Until now, our RadListPicker does nothing except being there. We need to hook up some code to it.

First we declare a data class for our RadListPicker ItemsSource:

        public class PickerItems
        {
            public string name { get; set; }
        }

After that, we need to get some items into our ListPicker. For this demo I am using static items, but this works also with dynamic ones:

public MainPage()
        {
            InitializeComponent();

            pickerSource = new List<PickerItems>();
            pickerSource.Add(new PickerItems() { name = "item 1" });
            pickerSource.Add(new PickerItems() { name = "item 2" });
            pickerSource.Add(new PickerItems() { name = "item 3" });
            pickerSource.Add(new PickerItems() { name = "item 4" });
            pickerSource.Add(new PickerItems() { name = "item 5" });

            TestPicker.ItemsSource = pickerSource;
            //registering the SummaryForSelectedItemsDelegate event
            TestPicker.SummaryForSelectedItemsDelegate += TestPicker_SummaryForSelectedItemsDelegate;
        }

“pickerSource” is just a List<PickerItems> that is defined globally for the page. Noticed the registration of the SummaryForSelectedItemsDelegate object? Awesome, because we are continuing with exactly that:

        //getting the string that is displayed when our ListPicker is not expanded
        private object TestPicker_SummaryForSelectedItemsDelegate(System.Collections.IList list)
        {
            string summary = string.Empty;

            for (int i = 0; i < list.Count; i++)
            {
                //getting the last item
                bool isLast = i == list.Count - 1;
                //generating the string
                PickerItems groupItem = (PickerItems)list[i];
                summary = String.Concat(summary, groupItem.name);
                summary += isLast ? string.Empty : ", ";
            }

            if (summary == string.Empty)
            {
                summary = "none";
            }

            return summary;
        }

This object is used to get the text that is displayed in the RadListPicker while it is not expanded.

Of course we need to handle the changed selection, that’s why we hook into our TestPicker’s SelectionChanged event:

        private void TestPicker_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

            //saving the selected items
            if (TestPicker.SelectedItems.Count == 0)
            {
                //WP8.1
                //App.SettingsStore.selectedItemsString = string.Empty;

                //WP8
                App.selectedItemsString = string.Empty;
            }
            else
            {
                //WP8.1
                //App.SettingsStore.selectedItemsString = JsonConvert.SerializeObject(TestPicker.SelectedItems);

                //WP8
                App.selectedItemsString = JsonConvert.SerializeObject(TestPicker.SelectedItems);
            }

            //WP8
            if (IsolatedStorageSettings.ApplicationSettings.Contains("selectedItemsString"))
            {
                IsolatedStorageSettings.ApplicationSettings.Remove("selectedItemsString");
            }
            IsolatedStorageSettings.ApplicationSettings.Add("selectedItemsString", App.selectedItemsString);
        }

If we do not have selected items, we are going to save an empty string. Otherwise, we just serialize the selected items (which are an IList<PickerItems>) and save this code to our IsolatedStorage (on WP8) or ApplicationDataContainer (on WP8.1). This way, we can save the selected items without any trouble.

Until now, we only saved our items. Of course we want our app to select those saved items if our users return to this point in our app. The solution to this is a mix of JSON deserialization and LINQ. Add this code to your OnNavigatedTo event:

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            //WP8.1
            //if (App.SettingsStore.selectedItemsString != string.Empty)
            //WP8
            if (App.selectedItemsString != string.Empty)
            {
                try
                {
                    //WP8.1
                    //var selectedItems = JsonConvert.DeserializeObject<List<PickerItems>>(App.SettingsStore.selectedItemsString);
                    //WP8
                    var selectedItems = JsonConvert.DeserializeObject<List<PickerItems>>(App.selectedItemsString);

                    foreach (var item in selectedItems)
                    {
                        //using LINQ to get the matching item from pickerSource
                        var selectedItem = pickerSource.Where(x => x.name == item.name).Single<PickerItems>();
                        //getting the index
                        int index = pickerSource.IndexOf(selectedItem);
                        //setting the item as selected
                        TestPicker.SelectedItems.Add(pickerSource[index]);
                    }
                }
                catch { }
            }

        }

Let me explain what I have done in there. First, I checked if there are selected items by checking if the saved string is empty. If not, I am deserializing the saved JSON string into a List<PickerItems>.

In the next step, we are iterating with a foreach loop over this List<PickerItems>. We are looking for each item that is in this list, and if it exists, we pick up this item from our pickerSource. This item has its own index position within the pickerSource List<PickerItems>. We assign this position as a an integer value to a local object in the foreach loop.

The most important point is the last step: adding the item to the SelectedItems IList<PickerItems>. After adding all items, our SummaryForSelectedItemsDelegate automatically reflects those changes. Bonus: this way, also the order of the selected items is still the same as at the time the user selected those items (which can be a case).

wp_ss_20140706_0004

If you do not want this, you should sort the SelectedItems before saving them. I wrapped the code in a try catch blog to avoid serialization exceptions for this demo project, you should handle/avoid them of course in a real world app.

Once one figured these steps out, pretty easy to solve. And finally, it is also documented by a blog post. As always, I hope this is helpful for some of you.

For your convenience, you can RadListPickerMultiSelect.

Until the next post, happy coding!

Using BugSense to track errors and events in a Windows Phone app

BugSenseWhy BugSense?

Errors/exceptions are annoying and helpful at the same time. They can annoy you while creating your app. At the same time, they help you to improve the quality of your app (most of the time, that is). They annoy your users, if they lead to crash your app. At the same time, they are a good chance to get in contact with your users – for example you could catch unhandled exceptions and ask the user to send it over to you.

But what if your users choose to ignore the error? How should you improve your app’s quality? What if the only thing you get are bad reviews? Pretty hard task, especially if you have a completely new app. I had that situation over and over again – and of course, I was annoyed of that fact.

So I researched the internet for solutions. Google Analytics is one service that works and is mostly used in enterprise apps. I use it in the app I am developing for my 9to5 job on Windows Phone and Android, but I only am able to use it on Windows Phone due to a third party library. If the developer chooses to not continue his efforts, at one point it will stop working or at least needs manual maintenance from my part  (looking at you, TweetSharp).

BugSense was the second alternative I had a look on. They are  a big player in the mobile monitoring market, and have a very good basic model, that fits perfectly for the average developer (500 errors per month, 350000 data points per month for free) to get started, and their first pricing stage if you have more apps comes close to what indie developers like I am need to maintain more than one app.

On top, there is often the possibility to gain promo codes that unlock some of the functionalities for free for a limited time (like DVLUP promo codes etc.).

I can only recommend to give it at least a try. On major point on the plus side was the fact that BugSense also has a Windows Phone app that helps you to keep up to date with the errors and insights while you are on the go.

Setting up an app is also pretty easy, be it tracking errors or tracking events. Let’s have a look at the code.

Error handling

The first thing you’ll need to to install is the BugSense SDK either via Nuget (‘BugSense.WP8′ for WP 8.0 / 8.1 Silverlight, ‘BugSense.WP81′ for WP 8.1 Runtime) or you can download the package manually here and import the dll for SL projects.

Next step is to authorize your app in your app’s constructor:

public App()
{
    //connect your app to the BugSense API’s
    BugSenseHandler.Instance.InitAndStartSession(new ExceptionManager(Current), RootFrame, "");
}

For WINPRT projects, you’ll leave the Rootframe parameter out.

The official documentation says you don’t need the UnhandledException handler any longer and can remove it. In a real Windows Phone app, this could lead to crashes from exceptions by the BugSense handler that are not caught without any error logging – thanks to Sara Silva for pointing me to that (follow her!). I’ll leave it up to you if you leave it there to handle those errors or if you are fine with your app being crashing in this case.

I am also telling you what I did: I left the UnhandledException handler in there because my users are already used to another thing I used before: Telerik’s RadDiagnostics, which enables users to send those error messages via mail. I left it there for two reasons:

  • to keep the interaction with my user that I already had when an error showed up
  • to prevent my app from crashing – no matter if the error comes from BugSense or my code

For error logging, there is only one point left to do. After my experience, error logging only works after registering a new instance of the BugSense handler (I am doing this in my first page’s Loaded event):

BugSenseHandler.Instance.RegisterAsyncHandlerContext();

That’s all, now all your errors are collected into your BugSense account.

Event tracking

If you want to track events in your app, BugSense is helpful on that task, too. The easiest way to achieve is this one:

await BugSenseHandler.Instance.LogEventAsync(“");

Conclusion

With BugSense you don’t need a complex setup to collect errors and track events remotely from your users devices. Pricing is moderate, and you even have a mobile app that allows you to keep track of errors when your are not on your dev machine. BugSense has a lot more options, for getting started, I hope this post is helpful for some of you.

Until the next post, happy coding!

How to load a list of a user’s twitter friends/followers in your Windows Phone app

TwitterFriendsList_WP_Blog During the last days, I was adding a new function to UniShare that suggests users the Twitter handles while typing in some text. The base of this new function is a list of the user’s twitter friends. In this post, I am going to show you how to generate this list and save it for further use. First thing I need to talk about: you can only load a maximum of 3000 friends at once due to the rate limit on Twitter’s part. At the end of the post, I’ll give you also an idea how to continue this after the first 3000 users were loaded. For the most scenarios, 3000 should be enough to cover the major part of your users. To be able to load all friends we first create a Task that fetches 200 entries of our user’s friends list. To be able to perform paging through all entries, Twitter uses so called cursors, which are 64-bit signed integers (long). You can read more about that here on Twitter’s API documentation. Let’s have a look on this Task:

        private async Task<string> TwitterFriendsListString(long twitterCursor)
        {
            ShowProgressIndicator("generating mention suggestion base...");

            //needed for generating the Signature
            string twitterRequestUrl = "https://api.twitter.com/1.1/friends/list.json";

            //used for sending the request to the API
            //for usage of the url parameters, go to https://dev.twitter.com/docs/api/1.1/get/friends/list
            string twitterUrl = string.Format("https://api.twitter.com/1.1/friends/list.json?cursor={0}&screen_name={1}&count=200&skip_status=true&include_user_entities=false", twitterCursor, App.SettingsStore.twitterName);

            string timeStamp = GetTimeStamp();
            string nonce = GetNonce();

            string response = string.Empty;

            //we need to include all url parameters in the signature
            //IMPORTANT: Twitter's API demands them to be sorted alphabetically, otherwise the Signature will not be accepted
            string sigBaseStringParams = "count=200";
            sigBaseStringParams += "&" + "cursor=" + twitterCursor;
            sigBaseStringParams += "&" + "include_user_entities=false";
            igBaseStringParams += "&" + "oauth_consumer_key=" + twitterConsumerKey;
            sigBaseStringParams += "&" + "oauth_nonce=" + nonce;
            sigBaseStringParams += "&" + "oauth_signature_method=HMAC-SHA1";
            sigBaseStringParams += "&" + "oauth_timestamp=" + timeStamp;
            sigBaseStringParams += "&" + "oauth_token=" + App.SettingsStore.twitteroAuthToken;
            sigBaseStringParams += "&" + "oauth_version=1.0";
            sigBaseStringParams += "&" + "screen_name=" + App.SettingsStore.twitterName;
            sigBaseStringParams += "&" + "skip_status=true";
            string sigBaseString = "GET&";
            sigBaseString += Uri.EscapeDataString(twitterRequestUrl) + "&" + Uri.EscapeDataString(sigBaseStringParams);

            string signature = GetSignature(sigBaseString, twitterConsumerSecret, App.SettingsStore.twitteroAuthTokenSecret);

            string authorizationHeaderParams =
                "oauth_consumer_key=\"" + twitterConsumerKey +
                "\", oauth_nonce=\"" + nonce +
                "\", oauth_signature=\"" + Uri.EscapeDataString(signature) +
                "\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"" + timeStamp +
                "\", oauth_token=\"" + Uri.EscapeDataString(App.SettingsStore.twitteroAuthToken) +
                "\", oauth_version=\"1.0\"";

            HttpClient httpClient = new HttpClient();

            httpClient.DefaultRequestHeaders.Authorization = new HttpCredentialsHeaderValue("OAuth", authorizationHeaderParams);
            var httpResponseMessage = await httpClient.GetAsync(new Uri(twitterUrl));

            response = await httpResponseMessage.Content.ReadAsStringAsync();

            return response;
        }

As you can see, we need to create our signature based on the url parameters we are requesting. Twitter demands them to be sorted alphabetically. If you would not sort them this way, the Signature is wrong and your request gets denied by Twitter. We are overloading this Task with the above mentioned cursor to get the next page of our user’s friends list. If you need the GetNonce() and GetSignature() methods, take a look at this post, I am using them for all requests to Twitter. Now that we have this Task ready to make our requests, lets load the complete list. First, declare these objects in your page/model:

        public List<TwitterMentionSuggestionBase> twitterMentionSuggestionsList;
        public long nextfriendlistCursor = -1;
        public string friendsResponseString = string.Empty;
        public string friendsJsonFileName = "twitterFriends.json";

Then we need to create a loop to go through all pages Twitter allows us until we are reaching the rate limit of 15 requests per 15 minutes. I using a do while loop, as this is the most convenient way for this request:

            //to avoid double entries, make sure the list is we are using is empty
            if (twitterMentionSuggestionsList.Count != 0)
            {
                twitterMentionSuggestionsList.Clear();
            }
            //starting the do while loop
            do
            {
                //fetching the Json response
                //to get the first page of the list from Twitter, the cursor needs to be -1
                friendsResponseString = await TwitterFriendsListString(nextfriendlistCursor);

                //using Json.net to deserialize the string
                var friendslist = JsonConvert.DeserializeObject<TwitterFriendsClass.TwitterFriends>(friendsResponseString);
                //setting the cursor for the next request
                nextfriendlistCursor = friendslist.next_cursor;

                //adding 200 users to our list
                foreach (var user in friendslist.users)
                {
                    //using the screen name ToLower() to make the further usage easier
                    TwitterMentionSuggestionsList.Add(new TwitterMentionSuggestionBase() { name = "@" + user.screen_name.ToLower() });
                }

                //once the last page is reached, the cursor will be 0
                if (nextfriendlistCursor == 0)
                {
                    //break will continue the code after the do while loop
                    break;
                }
            }
            //the while condition needs to return true if you would set up a Boolean for it!
            while (nextfriendlistCursor != 0);

As long as the cursor is not 0, the loop will load the json string with 200 entries. The class you’ll need for deserializing can be easily generated. Just set a breakpoint after the call of our Task, copy the whole response string and go to http://json2csharp.com to get your class. The TwitterMentionSuggestionBase class only contains a string property for the name and can be extended for you needs:

    public class TwitterMentionSuggestionBase
    {
        public string name { get; set; }
    }

Of course we need to save the list for further use. The code I use is pretty much the same you’ll find when you search for “saving json string to file” with your favorite search engine and works with Windows Phone 8 and 8.1:

            //saving the file to Isolated Storage
            var JsonListOfFriends = JsonConvert.SerializeObject(twitterMentionSuggestionsList);
            try
            {
                //getting the localFolder our app has access to
                StorageFolder localFolder = ApplicationData.Current.LocalFolder;
                //create/overwrite a file
                StorageFile friendsJsonFile = await localFolder.CreateFileAsync(friendsJsonFileName, CreationCollisionOption.ReplaceExisting);
                //write the json string to the file
                using (IRandomAccessStream writeFileStream = await FriendsJsonFile.OpenAsync(FileAccessMode.ReadWrite))
                {
                    using (DataWriter streamWriter = new DataWriter(writeFileStream))
                    {
                        streamWriter.WriteString(JsonListOfFriends);
                        await streamWriter.StoreAsync();
                    }
                }
            }
            catch
            {

            }

This way, we can easily generate a friends list for our users, based on their Twitter friends. Some points that might be helpful:

  • users with more than 3000 friends will receive an error after reaching this point on our task. Catch this error, but continue to save the already loaded list. Save the latest cursor for the next page and prompt the user to continue loading after 15 minutes to continue loading.
  • if you want to have a list with more details about a user’s friends, extend the TwitterMentionSuggestionBase class with the matching properties.
  • this code can also be used to determine the followers of a user, you just need to change the url parameters as well as the signature parameters according to the matching Twitter endpoint

As always, I hope this is helpful for some of you. Until the next post, happy coding!

How to connect your Windows Phone 8 & 8.1 app to Yammer

In my recent project UniShare I also added Yammer, because some of users asked for it and we use it also at Telefónica.

This post is all about how to connect you Yammer. First, we need to prepare our app. Five steps are needed for preparation.

First, we need an uri scheme to launch our app. To add an uri scheme, right click on the WMAppManifest.xml and click on ‘Open With…’ and select ‘XML (Text) Editor with Encoding’. After the ‘Tokens’ section, add your custom uri scheme within the ‘Extensions’ tag, for example:

      <Protocol Name="yourapp-yammercallback" NavUriFragment="encodedLaunchUri=%s" TaskID="_default" />

Next step is to add a proper UriMapper:

public class UriMapper : UriMapperBase
{
    public override Uri MapUri(Uri uri)
    {
        if (uri.ToString().Contains("yourapp-yammercallback"))
        {
            string decodedUri = HttpUtility.UrlDecode(uri.ToString());

            int redirectUriIndex = decodedUri.IndexOf("yourapp-yammercallback");
            string redirectParams = new Uri(decodedUri.Substring(redirectUriIndex)).Query;
            // Map the OAuth response to the app page
            return new Uri("/MainPage.xaml" + redirectParams, UriKind.Relative);
        }

        else return uri;
    }
}

If you want to learn more about uri schemes, you can read my blog post here.

The third step is to generate your app on Yammer to get your Tokens. Open https://www.yammer.com/client_applications, click on ‘Register New App’ and fill in the form:

Screenshot (354)

After clicking on continue, click on ‘Basic Info’ and add your uri scheme in the field ‘Redirect Uri’ and click on ‘Save’.

Screenshot (356)

The fourth step starts with downloading the Yammer oAuth SDK for Windows Phone from Github. Open the solution and built all projects. After that, you can close the solution. Go back into your project, and right click on ‘References’, followed by ‘Add Reference’. Browse to the folder ‘\WPYammer-oauth-sdk-demo-master\windows-phone-oauth-sdk-demo-master\Yammer.OAuthSDK\Bin\Release’ and add the file with the name ‘Yammer.OAuthSDK.dll’.

The last step is to add your keys and the redirect uri in your app’s resource dictionary:

<model:OAuthClientInfo xmlns:model="clr-namespace:Yammer.OAuthSDK.Model;assembly=Yammer.OAuthSDK" x:Key="MyOAuthClientInfo"
    ClientId="your client id" 
    ClientSecret="your client secret" 
    RedirectUri="yourapp-yammercallback" />

Now that our app is prepared, we can finally launch the oAuth process. First, we need to read our values from our app’s resource dictionary. Add this to the constructor to do so:

YammerClientId = App.MyOAuthClientInfo.ClientId;
YammerClientSecret = App.MyOAuthClientInfo.ClientSecret;
YammerCallbackUri = App.MyOAuthClientInfo.RedirectUri;

To kick the user out to the oAuth process, which happens in the phone’s browser, just add these two lines to your starting event (for example a button click event).

OAuthUtils.LaunchSignIn(YammerClientId, YammerCallbackUri);
App.Current.Terminate();

You might notice the app gets terminated. We have to do this because only this way, the uri scheme we added earlier can do its work. If the app is not terminated, the values cannot be passed into our app. Technically, it would also be possible to use the WebAuthenticationBroker on 8.1 for this. Sadly, the Yammer authorization pages do not work well with the WAB. The best way to use it with this library, is to kick the user to the browser.

Once we are receiving the values of the authentication, we can continue the authentication process to get the final access token. Add this code to your OnNavigatedTo event:

ShowProgressIndicator("connecting to Yammer...");

if (NavigationContext.QueryString.ContainsKey(Constants.OAuthParameters.Code) && NavigationContext.QueryString.ContainsKey(Constants.OAuthParameters.State) && e.NavigationMode != NavigationMode.Back)
{
    OAuthUtils.HandleApprove(
        YammerClientId,
        YammerClientSecret,
        NavigationContext.QueryString[Constants.OAuthParameters.Code],
        NavigationContext.QueryString[Constants.OAuthParameters.State],
        onSuccess: () =>
        {
            GetYammerCurrentUserData();
        }, onCSRF: () =>
        {
            MessageBox.Show("Please contact us via the 'help & support' page.", "Invalid redirect", MessageBoxButton.OK);
        }, onErrorResponse: errorResponse =>
        {
            Dispatcher.BeginInvoke(() => MessageBox.Show(errorResponse.OAuthError.ToString(), "Invalid operation", MessageBoxButton.OK));
            HideProgressIndicator();
        }, onException: ex =>
        {
            Dispatcher.BeginInvoke(() => MessageBox.Show(ex.ToString(), "Unexpected error", MessageBoxButton.OK));
            HideProgressIndicator();
        }
    );
}
// "Deny"
else if (NavigationContext.QueryString.ContainsKey(Constants.OAuthParameters.Error) && e.NavigationMode != NavigationMode.Back)
{
    string error, errorDescription;
    error = NavigationContext.QueryString[Constants.OAuthParameters.Error];
    NavigationContext.QueryString.TryGetValue(Constants.OAuthParameters.ErrorDescription, out errorDescription);

    string msg = string.Format("error: {0}\nerror_description:{1}", error, errorDescription);
    MessageBox.Show(msg, "Error", MessageBoxButton.OK);

    if (NavigationContext.QueryString != null)
    {
        string[] NavigationKeys = NavigationContext.QueryString.Keys.ToArray();
        ClearNavigationContext(NavigationKeys);
    }

    OAuthUtils.DeleteStoredToken();

}

With this, you are handling all errors and events properly. If the call ends successfully, we are finally able to get our user’s data:

public void GetYammerCurrentUserData()
{
    ShowProgressIndicator("connecting to Yammer...");

    var baseUrl = new Uri("https://www.yammer.com/api/v1/users/current.json", UriKind.Absolute);

    OAuthUtils.GetJsonFromApi(baseUrl,
        onSuccess: response =>
        {
            //do something with the result (json string)

            HideProgressIndicator();

        }, onErrorResponse: errorResponse =>
        {
            Dispatcher.BeginInvoke(() =>
            {
                MessageBox.Show(errorResponse.OAuthError.ToString(), "Invalid operation", MessageBoxButton.OK);
                HideProgressIndicator();

            });
        }, onException: ex =>
        {
            Dispatcher.BeginInvoke(() =>
            {
                MessageBox.Show(ex.ToString(), "Unexpected error", MessageBoxButton.OK);
                HideProgressIndicator();

            });
        }
    );
}

As you can see above, the result is a json string that contains the current user’s data. You can either create a class/model to deserialize the values or use anonymous deserialization methods.

One important point: you cannot publish your app outside your home network until it got approved as a global app by Yammer. I am waiting for nearly two weeks now for UniShare to get approved and hope it will become available for all soon.

As always, I hope this post is helpful for some of you.

Happy coding!

How to use the WebAuthenticationBroker in a Windows Phone 8.1 Silverlight app

oAuthDance

I already wrote how to use the WebAuthenticationBroker (WAB) in a Windows Phone Runtime app. With the need for me to switch back to Silverlight for UniShare, I needed to perform some rewriting of the WAB code.

The WAB needs some other code to work properly in a Silverlight project, and this post will got through all steps that are needed for this. I will reference to the above blog post where the methods itself are the same. I am just highlighting the changes that are needed in an 8.1 Silverlight project.

Preparing our App

First, we need to set up the proper continuation event in App.xaml.cs. We are doing this by adding this line of code in the App class:

public WebAuthenticationBrokerContinuationEventArgs WABContinuationArgs { get; set; }

This event is used when we are coming back to our app after the WAB logged the user in. The next step we need to do, is to tell our app that we have performed an authentication, and pass the values back to our main code. Unlike in the Runtime project, we are using the Application_ContractActivated event for this:

        private void Application_ContractActivated(object sender, Windows.ApplicationModel.Activation.IActivatedEventArgs e)
        {
            var _WABContinuationArgs = e as WebAuthenticationBrokerContinuationEventArgs;
            if (_WABContinuationArgs != null)
            {
                this.WABContinuationArgs = _WABContinuationArgs;
            }
        }

If you are upgrading from a WP8 project, you might have to add this event manually. Our app is now prepared to get results from the WAB.

Preparing oAuth

I am going to show you the oAuth process of Twitter to demonstrate the usage of the WAB. First, we need again the GetNonce(), GetTimeStamp () and GetSignature(string sigBaseString, string consumerSecretKey, stringoAuthTokenSecret=null) methods from my former blog post.

Performing the oAuth process

In the oAuth authentication flow, we need to obtain a so called Request Token, which allows our app to communicate with the API (in this case Twitter’s API).

Add the following code to your “connect to Twitter”- Button event:

                        string oAuth_Token = await GetTwitterRequestTokenAsync(TwitterCallBackUri, TwitterConsumerKey);
                        string TwitterUrl = "https://api.twitter.com/oauth/authorize?oauth_token=" + oAuth_Token;

                        WebAuthenticationBroker.AuthenticateAndContinue(new Uri(TwitterUrl), new Uri(TwitterCallBackUri));

Like in a Runtime app, we are getting the request token first (code is also in my former blog post), once we obtained the request token, we are able to get the oAuth token that enables us to get the final user access tokens.

Once the user has authenticated our app, we’ll receive the above mentioned oAuth tokens. To use them, add the following code to your OnNavigatedTo event:

                var appObject = Application.Current as App;

                if (appObject.WABContinuationArgs != null)
                {
                    WebAuthenticationResult result = appObject.WABContinuationArgs.WebAuthenticationResult;

                    if (result.ResponseStatus == WebAuthenticationStatus.Success)
                    {
                        await GetTwitterUserNameAsync(result.ResponseData.ToString());
                    }
                    else if (result.ResponseStatus == WebAuthenticationStatus.ErrorHttp)
                    {
                        MessageBox.Show(string.Format("There was an error connecting to Twitter: \n {0}", result.ResponseErrorDetail.ToString()), "Sorry", MessageBoxButton.OK);

                    }
                    else
                    {
                        MessageBox.Show(string.Format("Error returned: \n{0}", result.ResponseStatus.ToString()), "Sorry", MessageBoxButton.OK);
                        HideProgressIndicator();
                    }
                }

The WebAuthenticationResult now holds all values that we need to perform the final actions. To complete the oAuth process on Twitter, you can use the GetTwitterUserNameAsync(string webAuthResultResponseData) method from my former blog post. If you are not using other methods to control the result of the WAB, don’t forget to set appObject.WABContinuationArgs to null after you finished obtaining all tokens and data from Twitter (or other services).

As you can see, there are some structural differences in using the WAB when creating a Silverlight app, but we are also able to use a lot of code from my Runtime project. I hope this post is helpful for some of you to get the oAuth dance going.

In my next post, I will show you how to authenticate your app with Yammer (Microsoft’s enterprise social network).

Until then, happy coding!

How to send a mail from your Windows Phone 8.1 app

The old way

Sometimes, we need to pass some values to a newly generated E-Mail. In Windows Phone, we always had the EmailComposeTask for that:

EmailComposeTask mailTask = new EmailComposeTask();
mailTask .To = "mail@domain.com";
mailTask .Subject = "this is the Subject";
mailTask.Body = "this is the Body";

mailTask.Show();

This way was pretty straight forward. It will work in a Windows Phone 8.1 Silverlight app, but not in a WINPRT app.

The new way

I looked around and found the EmailManager class, which is also pretty easy to use. Let’s go through the code. First, we need to declare the EmailRecipient(s):

EmailRecipient sendTo = new EmailRecipient()
{
    Address = "mail@domain.com"
};

After that, we are now able to set up our EmailMessage, which works in a similar way like the old EmailComposeTask:

EmailMessage mail = new EmailMessage();
mail.Subject = "this is the Subject";
mail.Body = "this is the Body";

After setting up the Subject and the Body, we need to add our recipients to the EMailMessage. This is the only way to add “To”, “Bcc” and “CC” objects to our EMailMessage:

mail.To.Add(sendTo);
//mail.Bcc.Add(sendTo);
//mail.CC.Add(sendTo);

Last but not least, we are calling the  ShowComposeNewEmailAsync() method of the EmailManager class, which will open the Share contract with mail only:

await EmailManager.ShowComposeNewEmailAsync(mail);

 

wp_ss_20140424_0002

Here is once again the complete code for you to copy:

//predefine Recipient
EmailRecipient sendTo = new EmailRecipient()
{
    Address = "mail@domain.com"
};

//generate mail object
EmailMessage mail = new EmailMessage();
mail.Subject = "this is the Subject";
mail.Body = "this is the Body";

//add recipients to the mail object
mail.To.Add(sendTo);
//mail.Bcc.Add(sendTo);
//mail.CC.Add(sendTo);

//open the share contract with Mail only:
await EmailManager.ShowComposeNewEmailAsync(mail);

The new way works for both Windows Phone 8.1 Runtime and Silverlight apps.

The dirty way:

I found also another way that works with an Uri including the values as parameters launched by LaunchUriAsync() that gets recognized by the OS:

var mail = new Uri("mailto:?to=tickets@msiccdev.uservoice.com&subject=this is the Subject&body=this is the Body");
await Launcher.LaunchUriAsync(mail);

The parameters get automatically parsed by the Mail app.

I’ll leave it up to you which way you are using.

As always, I hope this is helpful for some of you.

Happy coding!

How to detect all urls in a string to match Twitter’s requirements (Windows 8(.1) and Windows Phone 8(.1))

url

As you might guess, I am still working on that app I mentioned in my last blog post. As I was diving deeper into the functions I want, I recognized that Twitter does a very well url handling server side.

Like the official documentation says, every url will be shortened with a link that has 22 characters (23 for https urls).

I was trying to write a RegEx expression to detect all the links that can be:

  • http
  • https
  • just plain domain names like “msicc.net”

This is not as easy as it sounds, and so I was a bit struggling. I then talked with @_MadMatt (follow him!) who has a lot of experience with twitter. My first attempt was a bit confusing as I did first only select http and https, then the plain domain names.

I found the names by their domain ending, but had some problems to get their length (which is essential). After the very helpful talk with Matthieu, I finally found a very good working RegEx expression here on GitHub.

I tested it with tons of links, and I got the desired results and it is now also very easy for me to get their length.

Recovering the amount of time I needed for this, I decided to share my solution with you. Here is the method I wrote:

        public int CalculateTweetCountWithLinks(int currentCount, string text)
        {
            int resultCount = 0;

            if (text != string.Empty)
            {
                //detailed explanation: https://gist.github.com/gruber/8891611
                string pattern = @"(?i)\b((?:https?:(?:/{1,3}|[a-z0-9%])|[a-z0-9.\-]+[.](?:com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)/)(?:[^\s()<>{}\[\]]+|\([^\s()]*?\([^\s()]+\)[^\s()]*?\)|\([^\s]+?\))+(?:\([^\s()]*?\([^\s()]+\)[^\s()]*?\)|\([^\s]+?\)|[^\s`!()\[\]{};:'.,<>?«»“”‘’])|(?:(?<!@)[a-z0-9]+(?:[.\-][a-z0-9]+)*[.](?:com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)\b/?(?!@)))";

                //generating a MatchCollection
                MatchCollection linksInText = Regex.Matches(text, pattern, RegexOptions.Multiline);

                //going forward only when links where found
                if (linksInText.Count != 0)
                {
                    //important to set them to 0 to get the correct count
                    int linkValueLength = 0;
                    int httpOrNoneCount = 0;
                    int httpsCount = 0;

                    foreach (Match m in linksInText)
                    {
                        //https urls need 23 characters, http and others 22
                        if (m.Value.Contains("https://"))
                        {
                            httpsCount = httpsCount + 1;
                        }
                        else
                        {
                            httpOrNoneCount = httpOrNoneCount + 1;
                        }

                        linkValueLength = linkValueLength + m.Value.Length;
                    }

                    //generating summaries of character counts
                    int httpOrNoneReplacedValueLength = httpOrNoneCount * 22;
                    int httpsReplacedValueLength = httpsCount * 23;

                    //calculating final count
                    resultCount = (currentCount - linkValueLength) + (httpOrNoneReplacedValueLength + httpsReplacedValueLength);                    
                }
                else
                {
                    resultCount = currentCount;
                }
            }
            return resultCount;
        }

First, we are detecting links in the string using the above mentioned RegEx expression and collect them in a MatchCollection.

As https urls have a 23 character length on t.co (Twitter’s url shortener), I am generating two new counts – one for https, one for all other urls.

The last step is to substract the the length of all Match values and add the newly calculated replaced link values lengths.

Add this little method to your TextChanged event, and you will be able to detect the character count on the fly.

As always, I hope this is helpful for some of you.

Happy coding, everyone!

 

How to use the WebAuthenticationBroker for oAuth in a Windows Phone Runtime WP8.1 app

oAuthDance

After playing around with WP8.1 for a few days (like everyone else), I decided to dig a bit into development of WP8.1.

As oAuth is the common authentication method nowadays for Apps and Websites, I was curios about the implementation of the WebAuthenticationBroker in a WINPRT app.

I used it before with Windows 8 for my TweeCoMinder app, but that’s a few month back (it didn’t make it into the Store yet (another goal, right – porting TweeCoMinder to Universal will be a lot of fun and learning for me ;-)).

Before we continue: This is a pretty huge topic. Be prepared that it may take you more than one time to read and understand what is going on.

Let’s dive into it. Unlike the Windows WebAuthenticationBroker, the Phone version does not use the AuthenticateAsync method. It uses AuthenticateAndContinue instead. This is related to the lifecycle on phone, as it is more likely that an WINPRT app is suspended than on Windows (at least that’s the official reason).

Preparing our App

But we are able to get it working, no worries. First, we need the so called ContinuationManager. This class brings the user back to the app where the fun begun.

You can download the complete class from here (it is a 1:1 copy from the official MSDN reference). The only thing you need to do is to add your app’s Namespace into it.

The next step we need to do: some modifications at the App.xaml.cs file.

1. Add an OnActivated event (it isn’t there in the Phone template)

        protected async override void OnActivated(IActivatedEventArgs e)
        {
            CreateRootFrame();

            // Restore the saved session state only when appropriate
            if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
            {
                try
                {
                    await SuspensionManager.RestoreAsync();
                }
                catch (SuspensionManagerException)
                {
                    //Something went wrong restoring state.
                    //Assume there is no state and continue
                }
            }

            //Check if this is a continuation
            var continuationEventArgs = e as IContinuationActivatedEventArgs;
            if (continuationEventArgs != null)
            {
                continuationManager.Continue(continuationEventArgs);
            }

            Window.Current.Activate();
        }

First, we check the SuspensionManager and let him restore a saved state – if there is one. If you do not have a Folder  ”Common” with the SuspensionManager, just add a new Basic page. This will generate the Common folder with the SuspenstionManager class for you.

After that, we are checking if the activation is a Continuation. We need this check there, otherwise the app will not be able to receive the Tokens after returning from the WebAuthenticationBroker. Note: declare the ContinuationManager globally in App.xaml.cs with this to avoid multiple instances (which will crash the app for sure).

public static ContinuationManager continuationManager { get; private set; }

2. Add a CreateRootFrame() method with some little changes to the default behavior

        private void CreateRootFrame()
        {
            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame != null)
                return;

            // Create a Frame to act as the navigation context and navigate to the first page
            rootFrame = new Frame();

            //Associate the frame with a SuspensionManager key                                
            SuspensionManager.RegisterFrame(rootFrame, "AppFrame");

            // Set the default language
            rootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];

            rootFrame.NavigationFailed += OnNavigationFailed;

            // Place the frame in the current Window
            Window.Current.Content = rootFrame;
        }

This simply creates the RootFrame for our app. Place this one in the OnLaunched and OnActivated events. Instead of creating the RootFrame in the OnLaunched method, declare it globally in App.xaml.cs with this:

public static Frame rootFrame { get; set; }

3. Handle the HardwareButtons_BackPressed event

        private void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
        {
            Frame frame = Window.Current.Content as Frame;
            if (frame == null)
            {
                return;
            }

            if (frame.CanGoBack)
            {
                frame.GoBack();
                e.Handled = true;
            }
        }

This just handles the BackButton press globally (you can still handle it on individual pages/frames/controls).

4. Handle Navigation Errors in the OnNavigationFailed event

private void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{

    //change this code for your needs
    throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}

5. Add the Save method to the OnSuspending event

await SuspensionManager.SaveAsync();

This is just to save the current state of our app while the App gets suspended.

Preparing oAuth

Now, we have our app prepared  to be continued after the WebAuthenticationBroker has finished. Pretty much to do so far, but now we are going to start with the real fun: The oAuth process. We are going to use Twitter in this case, as it is very popular to be added as a sharing option in apps (yes, I recently saw a lot of them).

Before we are able to connect to Twitter, we need some preparing methods. The first one is to get a random character chain. Twitter demands a 32 digit chain that contains random alphanumeric values, the so called oAuth-nonce. A lot of samples use a chain that is shorter, which will be fine for the initial authentication, but not for additional request. Here is my method:

string GetNonce()
{
   StringBuilder builder = new StringBuilder();
   Random random = new Random();
   char ch;
   for (int i = 0; i < 32; i++)
   {
     ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
     builder.Append(ch);
   }

   return builder.ToString().ToLower();
 }

We also need a timestamp in Milliseconds, this one is pretty straight forward:

string GetTimeStamp()
{
  TimeSpan SinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
  return Math.Round(SinceEpoch.TotalSeconds).ToString();
}

On top, we need a signature for our Authentication request:

        string GetSignature(string sigBaseString, string consumerSecretKey, string oAuthTokenSecret=null)
        {
            IBuffer KeyMaterial = CryptographicBuffer.ConvertStringToBinary(consumerSecretKey + "&" + oAuthTokenSecret, BinaryStringEncoding.Utf8);
            MacAlgorithmProvider HmacSha1Provider = MacAlgorithmProvider.OpenAlgorithm("HMAC_SHA1");
            CryptographicKey MacKey = HmacSha1Provider.CreateKey(KeyMaterial);
            IBuffer DataToBeSigned = CryptographicBuffer.ConvertStringToBinary(sigBaseString, BinaryStringEncoding.Utf8);
            IBuffer SignatureBuffer = CryptographicEngine.Sign(MacKey, DataToBeSigned);
            string Signature = CryptographicBuffer.EncodeToBase64String(SignatureBuffer);

            return Signature;
        }

You will find a lot of samples that don’t use the oAuthTokenSecret in the basic method. We will need this for additional requests, so I am using a nullable string overload. This way,  I need only one method after all.

Performing the Authentication process

To start the Authentication process, we are using this code in our Button_Click event:

        private async void connectToTwitterButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                string oAuth_Token = await GetTwitterRequestTokenAsync(TwitterCallBackUri, TwitterConsumerKey);
                string TwitterUrl = "https://api.twitter.com/oauth/authorize?oauth_token=" + oAuth_Token;

                WebAuthenticationBroker.AuthenticateAndContinue(new Uri(TwitterUrl), new Uri(TwitterCallBackUri), null, WebAuthenticationOptions.None);
            }
            catch
            { 
                //error handling here
            }
        }

First, we need a RequestToken that authenticates our request for the oAuthToken, that’s why we are awaiting the GetTwitterRequestTokenAsync(TwitterCallBackUri, TwitterConsumerKey) Task. The Task itself is this one:

        private async Task<string> GetTwitterRequestTokenAsync(string twitterCallbackUrl, string consumerKey)
        {
            //
            // Acquiring a request token
            //
            string TwitterUrl = "https://api.twitter.com/oauth/request_token";

            string nonce = GetNonce();
            string timeStamp = GetTimeStamp();
            string SigBaseStringParams = "oauth_callback=" + Uri.EscapeDataString(twitterCallbackUrl);
            SigBaseStringParams += "&" + "oauth_consumer_key=" + consumerKey;
            SigBaseStringParams += "&" + "oauth_nonce=" + nonce;
            SigBaseStringParams += "&" + "oauth_signature_method=HMAC-SHA1";
            SigBaseStringParams += "&" + "oauth_timestamp=" + timeStamp;
            SigBaseStringParams += "&" + "oauth_version=1.0";
            string SigBaseString = "GET&";
            SigBaseString += Uri.EscapeDataString(TwitterUrl) + "&" + Uri.EscapeDataString(SigBaseStringParams);
            string Signature = GetSignature(SigBaseString, TwitterConsumerSecret);

            TwitterUrl += "?" + SigBaseStringParams + "&oauth_signature=" + Uri.EscapeDataString(Signature);
            HttpClient httpClient = new HttpClient();
            string GetResponse = await httpClient.GetStringAsync(new Uri(TwitterUrl));

            string request_token = null;
            string oauth_token_secret = null;
            string[] keyValPairs = GetResponse.Split('&');

            for (int i = 0; i < keyValPairs.Length; i++)
            {
                string[] splits = keyValPairs[i].Split('=');
                switch (splits[0])
                {
                    case "oauth_token":
                        request_token = splits[1];
                        break;
                    case "oauth_token_secret":
                        oauth_token_secret = splits[1];
                        break;
                }
            }

            return request_token;
        }

After receiving the RequestToken, we are able to call the the AuthenticateAndContinue(Uri, Uri, ValueSet, WebAuthenticationOptions) method. The WebAuthenticationBroker opens and the user needs to login. After finishing, the user will get redirected back into our app.

If you think that’s all of our code, I need to disappoint you. The fun goes on. We prepared our app to be recognized as continued app. To effectifely continue our app, we need to use the ContinueWebAuthentication(WebAuthenticationBrokerContinuationEventArgs args) event from our ContinuationManager class:

 

        public async void ContinueWebAuthentication(WebAuthenticationBrokerContinuationEventArgs args)
        {
            WebAuthenticationResult result = args.WebAuthenticationResult;

            if (result.ResponseStatus == WebAuthenticationStatus.Success)
            {
                await GetTwitterUserNameAsync(result.ResponseData.ToString());
            }
            else if (result.ResponseStatus == WebAuthenticationStatus.ErrorHttp)
            {
                MessageDialog HttpErrMsg = new MessageDialog(string.Format("There was an error connecting to Twitter: \n {0}", result.ResponseErrorDetail.ToString()), "Sorry");
                await HttpErrMsg.ShowAsync();
            }
            else
            {
                MessageDialog ErrMsg = new MessageDialog(string.Format("Error returned: \n{0}", result.ResponseStatus.ToString()), "Sorry");
                await ErrMsg.ShowAsync();
            }
        }

The WebAuthenticationResult holds our accessToken and accessTokenSecret, that we are going to exchange for our final oAuthToken and oAuthTokenSecret (we need them for all further requests).

If all goes well, we are now able to call the final Authentication Task GetTwitterUserNameAsync(string webAuthResultResponseData):

        private async Task GetTwitterUserNameAsync(string webAuthResultResponseData)
        {

            string responseData = webAuthResultResponseData.Substring(webAuthResultResponseData.IndexOf("oauth_token"));
            string request_token = null;
            string oauth_verifier = null;
            String[] keyValPairs = responseData.Split('&');

            for (int i = 0; i < keyValPairs.Length; i++)
            {
                String[] splits = keyValPairs[i].Split('=');
                switch (splits[0])
                {
                    case "oauth_token":
                        request_token = splits[1];
                        break;
                    case "oauth_verifier":
                        oauth_verifier = splits[1];
                        break;
                }
            }

            String TwitterUrl = "https://api.twitter.com/oauth/access_token";

            string timeStamp = GetTimeStamp();
            string nonce = GetNonce();

            String SigBaseStringParams = "oauth_consumer_key=" + TwitterConsumerKey;
            SigBaseStringParams += "&" + "oauth_nonce=" + nonce;
            SigBaseStringParams += "&" + "oauth_signature_method=HMAC-SHA1";
            SigBaseStringParams += "&" + "oauth_timestamp=" + timeStamp;
            SigBaseStringParams += "&" + "oauth_token=" + request_token;
            SigBaseStringParams += "&" + "oauth_version=1.0";
            String SigBaseString = "POST&";
            SigBaseString += Uri.EscapeDataString(TwitterUrl) + "&" + Uri.EscapeDataString(SigBaseStringParams);

            String Signature = GetSignature(SigBaseString, TwitterConsumerSecret);

            HttpStringContent httpContent = new HttpStringContent("oauth_verifier=" + oauth_verifier, Windows.Storage.Streams.UnicodeEncoding.Utf8);
            httpContent.Headers.ContentType = HttpMediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");
            string authorizationHeaderParams = "oauth_consumer_key=\"" + TwitterConsumerKey + "\", oauth_nonce=\"" + nonce + "\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"" + Uri.EscapeDataString(Signature) + "\", oauth_timestamp=\"" + timeStamp + "\", oauth_token=\"" + Uri.EscapeDataString(request_token) + "\", oauth_version=\"1.0\"";

            HttpClient httpClient = new HttpClient();

            httpClient.DefaultRequestHeaders.Authorization = new HttpCredentialsHeaderValue("OAuth", authorizationHeaderParams);
            var httpResponseMessage = await httpClient.PostAsync(new Uri(TwitterUrl), httpContent);
            string response = await httpResponseMessage.Content.ReadAsStringAsync();

            String[] Tokens = response.Split('&');
            string oauth_token_secret = null;
            string oauth_token = null;
            string screen_name = null;

            for (int i = 0; i < Tokens.Length; i++)
            {
                String[] splits = Tokens[i].Split('=');
                switch (splits[0])
                {
                    case "screen_name":
                        screen_name = splits[1];
                        break;
                    case "oauth_token":
                        oauth_token = splits[1];
                        break;
                    case "oauth_token_secret":
                        oauth_token_secret = splits[1];
                        break;
                }
            }

            if (oauth_token != null)
            {
                App.SettingsStore.TwitteroAuthToken = oauth_token;
            }

            if (oauth_token_secret != null)
            {
                App.SettingsStore.TwitteroAuthTokenSecret = oauth_token_secret;
            }
            if (screen_name != null)
            {
                App.SettingsStore.TwitterName = screen_name;
            }
        }

At the end of this Task, we will have all Tokens and the ScreenName of our user and can save them for further usage.

The whole oAuth process is a pretty huge thing as you can see. I hope this blog post helps you all to understand how to use the WebAuthenticationBroker and get the required Tokens for all further requests.

Here are some useful links to the MSDN, if you want to dive deeper:

As always, this covers my experience. If anyone has tips or tricks to make this all easier (except of using already existing libraries), feel free to add a comment below.

Until the next post,  happy coding!