As I have already developed a news reader app for my blog, I got asked quite a few times if I want to share my code to help others creating their apps. As I need to redesign my blog reader to match the latest OS features of Windows and Windows Phone, I decided to create my WordPressUniversal library.
Automattic, the company behind WordPress, integrated a powerful JSON API into their JetPack plugin. My library is based on this API. Please make sure the JSON API is active on the blog you are developing your app for.
The library currently provides the following features:
getting a list posts or pages
getting a list of all categories
getting a list of comments for the site and single posts
supports Windows Phone 8 & 8.1 Silverlight, Windows Phone 8.1 RT, Windows 8, Xamarin.iOS and Xamarin.Android
The library deserializes all data into C# objects you can immediately work with.
It is still a work in progress, but as it provides already a bunch of options to get you started, I am making this public already.
I am constantly working on the library, so be sure to follow the project along.
Note: JetPack’s JSON API does not support guest commenting at the moment. I already reached out to Automattic to (hopefully) find a solution for this. If you cannot wait, Disqus has a portable solution for Windows Phone apps.
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) [updated: added missing continuationManager initialization]
protected async override void OnActivated(IActivatedEventArgs e)
{
continuationManager = new ContinuationManager();
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:
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:
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:
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):
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.