Building Social Apps Using Yammer Windows Phone 8 SDK
In last chapter you learned about Yammer JavaScript SDK. The JavaScript SDK helps you integrate HTML-based line-of-business applications with Yammer. In this chapter, you will learn about the Yammer Windows Phone SDK, released by Yammer. The Windows Phone SDK allows you to integrate Windows phone apps with Yammer. You can leverage the Windows Phone SDK to allow users to log in to your Windows Phone SDK using Yammer. You can implement the “Sign In with Yammer” button using the Windows Phone SDK to speed up the registration process and build a functional login system in minutes.
Introduction to Windows Phone 8 SDK
Yammer Windows Phone SDK is an open source program that enables developers to build Windows mobile apps on the Yammer platform or integrate Yammer functionality into their existing Windows phone apps. Like Yammer’s other SDKs for enterprise applications, the Windows Phone SDK helps organizations build more mobile capabilities and develop integrations with Yammer.
The Yammer Windows Phone SDK is a class library project that’s best suitable for Microsoft Windows Phone 8 apps.
The Windows Phone SDK enables:
The Windows Phone SDK is available at https://github.com/yammer/windows-phone-oauth-sdk-demo. This SDK consists of two projects:
Note This chapter does not explain how to develop Windows Phone 8 mobile apps. Refer to MSDN or other Apress books to explore Windows Phone 8 app development.
In the next section, you will learn about the basic setup required in order to leverage the Windows Phone SDK.
Setup Required to Use Windows Phone App 8 SDK
Before you learn about the different methods and functions, it’s important to understand the basic setup required to integrate the Windows Phone SDK.
Step 1: Register Your Yammer App and Set the Redirect URI
Register a new Yammer app as explained in Chapter 3 and configure the redirect URI to a custom one. The redirect URI has be unique to your WP8 app. For example, SPDSWP8App://Yammer. Make sure the scheme name (in this case SPDSWP8App) is unique to your company and Windows phone 8 app.
Step 2: Create an Instance of the Yammer.OAuthSDK.Model.OAuthClientInfo Class
The Yammer App registered in your Yammer network is identified by a unique ClientID, a client secret key, and a redirect URI, as shown in Figure 8-1.
Figure 8-1. Registered Yammer app’s keys and tokens
The first step in setting up your Windows phone app is to create an instance of the class called Yammer.OAuthSDK.Model.OAuthClientInfo. This class defines the properties that store the Yammer App configuration values. The best place to do this is in the resource dictionary in your Yammer App.xaml file.
Define an object of class model OAuthClientInfo in the App.xaml file with the ClientID, ClientSecret, and RedirectURI values matching the Yammer app configuration values.
<model:OAuthClientInfo xmlns:model="clr-namespace:Yammer.OAuthSDK.Model;assembly=Yammer.OAuthSDK" x:Key="MyOAuthClientInfo"
ClientId="ZaV9YiPAdnqa273m3HTH5w"
ClientSecret="BzLv9AsfUrVaCY7XTvgFBxjGizsxGK7BPcs5YftkVtE"
RedirectUri="SPDSWP8App://Yammer" />
You can now define a property in App.xaml.cs. A property declared in App.xaml.cs will be available application-wide. Add the following code in App.xaml.cs for the getter property.
public OAuthClientInfo MyOAuthClientInfo
{
get
{
return Resources["MyOAuthClientInfo"] as OAuthClientInfo;
}
}
Step 3: Configure a URI Association
This step is important from the user experience perspective, as during the login process in your Windows phone app, the user will be redirected to an IE browser Windows app. The developer needs to do URI association so that the after a successful login, users are redirected to the Windows phone app from the IE browser.
Configure Project Manifest “WMAppManifest.xml”
The configuration of URI association is done in the WMAppManifest.xml file, which is part of your Windows phone project.
The next step is to add an Extensions element in the app manifest file. Add the following code (below the tokens element) to WMAppManifest.xml. The Extensions element uses the Protocol element to specify the URI association (using a scheme name). Your Extensions element should look like this:
<Extensions>
<Protocol Name="SPDSWP8App" NavUriFragment="encodedLaunchUri=%s" TaskID="_default" />
</Extensions>
Updating App.xaml.cs
Now you need to override the default URI-mapper class with the app’s redirect URI in the InitializePhoneApplication() method in App.xaml.cs:
// Override the default URI-mapper class with our OAuth URI handler.
RootFrame.UriMapper = new OAuthResponseUriMapper(MyOAuthClientInfo.RedirectUri);
That is all the basic setup required to use the Windows Phone SDK in your Windows phone app. Exercise 8-1 demonstrates the step-by-step process to leverage the Windows Phone SDK, including the basic setup required in order to leverage the capabilities of Yammer’s Windows Phone SDK.
Understanding Windows Phone SDK
Before we jump into the implementation of Yammer SDK for Windows Phone, let’s explore the Windows Phone SDK’s project structure and the functions provided by the SDK project. Later in this section, you will see the actual implementation of each function provided by the SDK.
Project “Yammer.OAuthSDK” Structure
Yammer.OAuthSDK is the C# class library project that contains all essential classes methods to integrate Yammer functionality into the Windows Phone App. This is a mandatory project you have to add to your Windows Phone App Visual Studio Solution to create an app for integration with Yammer. We will also explain how to implement this app in your project using an example later in this chapter.
Look at the class structure of the Yammer.OAuthSDK project, as shown in Figure 8-2.
Figure 8-2. Class structure of the Windows Phone SDK
As you can see, this SDK project contains a folder named Model in the Yammer.OAuthSDK project. This folder contains all the model classes required for OAuth authentication for the Windows phone app.
All the classes under the Model folder are defined in the Yammer.OAuthSDK.Model namespace. The purpose of each class is listed in Table 8-1.
Table 8-1. List of Classes Available in the Yammer.OAuthSDK.Model Namespace
Class Name |
Purpose |
Methods |
---|---|---|
AccessToken |
The object that contains the actual access token. |
Token |
AuthenticationResponse |
The root object that desterilizes from a Yammer OAuth API call response. |
AccessToken OAuthError |
OAuthClientInfo |
Constants used to identify your app on the Yammer platform. |
ClientId ClientSecret RedirectUri |
OAuthError |
Object used to deserialize an error response from a Yammer API call. |
Type Message Code Stat HttpStatusCode HttpStatusDescription |
There is another folder named Util in the Yammer.OAuthSDK project, also shown in Figure 8-1, that contains utility classes. All these classes are defined in the Yammer.OAuthSDK.Utils namespace. Table 8-2 provides details of these classes.
Table 8-2. List of Classes Available in the Yammer.OAuthSDK.Utils Namespace
Class Name |
Purpose |
Available Methods |
---|---|---|
Constants |
This class defines all constants for constants that point to the Yammer API endpoints and constants that are used as the URL parameters for the API calls and responses. |
Private variable: ApiEndpoints OAuthParameters |
CryptoUtils |
Utils class to handle cryptographic and encoding related operations. |
Private variable: redirectUri Method: GenerateUrlFriendlyNonce() EncryptAndStoreMapUri() DecryptStored() UrlTokenEncode() UrlTokenDecode() |
OAuthResponseUriMapper |
Converts a uniform resource identifier (URI) into a new URI to be redirected and based on the OAuth parameters received. |
Private variable: redirectUri Method: OAuthResponseUriMapper() MapUri() |
OAuthUtils |
Utils class to handle Yammer OAuth API operations. |
Private variable: const string tokenFilePath const string nonceFilePath string AccessToken Method: LaunchSignIn() HandleApprove() GetJsonFromApi() DeleteStoredToken() HandleExceptions() |
SerializationUtils |
Utils class to handle serialization operations. |
Private variable: Method: DeserializeJson() |
StorageUtils |
Utils class to handle storage-related operations. |
Method: DeleteFromIsolatedStorage() WriteToIsolatedStorage() WriteToIsolatedStorage() ReadStringFromIsolatedStorage() ReadBytesFromIsolatedStorage() |
The Yammer.OAuth.Model and Yammer.OAuthSDK.Utils namespaces both contain important and mandatory classes to support Yammer integration with the Windows phone app.
In the next section, we will deep dive into some important functions mentioned in these classes.
Important Methods of Yammer.OAuthSDK
Before developing a Windows phone app, let’s look at the Windows Phone App SDK methods that are available in the Yammer.OAuthSDK.Utils namespace. Table 8-3 lists three important methods provided by the SDK.
Table 8-3. Important Windows Phone 8 SDK Functions
Method |
Purpose |
---|---|
LaunchSignIn |
Initiates the user login. |
HandleApprove |
Handles the OAuth approved response asynchronously by storing the information received from Yammer, like Code and State. |
GetJsonFromApi |
Calls the Yammer REST APIs asynchronously. |
In the following section, you will dive deeply into each of these methods listed in Table 8-3. You will learn the actual implementation of each method with the syntax and parameter of each method.
The LaunchSignIn method initiates the user login. Developers can invoke this method from a Windows phone app by using a “Login with Yammer” button. When called, this methods invokes the Internet Explorer browser on the Windows phone. The IE browser navigates to the Yammer login URL (https://www.yammer.com/dialog/oauth?client_id={0}&redirect_uri={1}&state={2}), which allows Yammer to authenticate the user as well as authorize the Yammer app.
The syntax of LaunchSignIn is as follows:
OAuthUtils.LaunchSignIn(clientId, redirectUri);
The LaunchSignIn method accepts two parameters, as listed in Table 8-4.
Table 8-4. LaunchSignIn Method Parameters
The following code snippet provides the actual implementation of LaunchSignIn() method:
public static void LaunchSignIn(string clientId, string redirectUri)
{
var ieTask = new WebBrowserTask();
// need to generate and store this nonce to identify the request is ours when it comes back
string nonce = CryptoUtils.GenerateUrlFriendlyNonce();
StorageUtils.WriteToIsolatedStorage(nonce, nonceFilePath);
string url = string.Format(Constants.ApiEndpoints.OAuthUserAuthentication, clientId, redirectUri, nonce);
ieTask.Uri = new Uri(url, UriKind.Absolute);
ieTask.Show();
}
This is another very important method for Windows Phone SDK. HandleApprove is invoked after the user is redirected back to the Windows phone app. This method handles the OAuth-approved response asynchronously by storing the information received from Yammer, like Code and State.
The syntax of HandleApprove is as follows:
OAuthUtils.HandleApprove(clientId, clientSecret, Code, State,[ onSuccess],[onFailure])
The HandleApprove method accepts four parameters, as listed in Table 8-5.
Table 8-5. HandleApprove Function Parameters
The following code snippet provides the actual implementation of the HandleApprove() method:
public static void HandleApprove(string clientId,
string clientSecret,
string code,
string state,
Action onSuccess,
Action onCSRF = null,
Action<AuthenticationResponse> onErrorResponse = null,
Action<Exception> onException = null)
{
// we get the stored nonce from the Isolated Storage to verify it against the one we get back from Yammer
string nonce = StorageUtils.ReadStringFromIsolatedStorage(nonceFilePath);
if (state != nonce)
{
// might be a CSRF attack, so we discard the request
if (onCSRF != null)
{
onCSRF();
}
return;
}
string url = string.Format(Constants.ApiEndpoints.OAuthAppAuthentication, clientId, clientSecret, code);
var appAuthUri = new Uri(url, UriKind.Absolute);
var webclient = new WebClient();
OpenReadCompletedEventHandler handler = null;
handler = (s, e) =>
{
webclient.OpenReadCompleted -= handler;
if (e.Error == null)
{
// the token should have been sent back in json format, we use serialization to extract it
AuthenticationResponse oauthResponse = SerializationUtils.DeserializeJson<AuthenticationResponse>(e.Result);
AccessToken = oauthResponse.AccessToken.Token;
onSuccess();
}
else
{
HandleExceptions(e.Error, onErrorResponse, onException);
}
};
webclient.OpenReadCompleted += handler;
// make the actual call to the Yammer OAuth App Authentication endpoint to get our token back
webclient.OpenReadAsync(appAuthUri);
}
The GetJsonFromApi method calls the Yammer REST APIs asynchronously. Developers can use this method to call any REST APIs that do not require any additional parameters.
The syntax of GetJsonFromApi is as follows:
public static void GetJsonFromApi(Uri endpoint, Action<string> onSuccess, Action<AuthenticationResponse> onErrorResponse = null, Action<Exception> onException = null)
The GetJsonFromApi method accepts four parameters, as listed in Table 8-6.
Table 8-6. GetJsonFromApi Function Parameters
The following code snippet provides the actual implementation of the GetJsonFromApi() method:
public static void GetJsonFromApi(Uri endpoint,
Action<string> onSuccess,
Action<AuthenticationResponse> onErrorResponse = null,
Action<Exception> onException = null)
{
if (endpoint == null || onSuccess == null)
{
throw new ArgumentNullException();
}
var webclient = new WebClient();
// We shouldn't use the url query paramters to send the token, we should use the header to send it more securely instead
webclient.Headers[HttpRequestHeader.Authorization] = "Bearer " + AccessToken;
DownloadStringCompletedEventHandler handler = null;
handler = (s, e) =>
{
webclient.DownloadStringCompleted -= handler;
if (e.Error == null)
{
var result = e.Result;
// We just pass the raw text data response to the callback
onSuccess(result);
}
else
{
HandleExceptions(e.Error, onErrorResponse, onException);
}
};
webclient.DownloadStringCompleted += handler;
webclient.DownloadStringAsync(endpoint);
}
Now that we have explained all the important requirements and structure of the Windows Phone SDK for Yammer integration, let’s create a Windows phone app using this SDK.
Building a Windows Phone 8 App Using Yammer Windows Phone SDK
This section provides a step-by-step guide on creating a new Windows phone app. You will use the Yammer Windows Phone App SDK in your project and call Yammer REST APIs for groups, message, users, and so on. Finally, you’ll use Visual Studio’s emulator to test your app.
EXERCISE 8-1: BUILDING A WINDOWS 8 PHONE APP
Create New Project
Figure 8-3. The Visual Studio start page provides a quick way to get started
Figure 8-4. Visual Studio provides a number of templates to choose from; to get started, select the Windows phone app
Figure 8-6. Windows phone app project strucutre
Add Yammer.OAuthSDK to the Solution
Figure 8-7. To add an existing project to solution in Visual Studio
Figure 8-8. Browse to the Yammer.OAuthSDK project file on your development machine
Referencing the Yammer.OAuthSDK to Windows Phone App Project
Figure 8-10. Select the project from the list to be added as a reference
Understanding the Visual Studio Solution Structure
Figure 8-11. Windows phone solution structure
Table 8-7 lists the Windows Phone SDK’s Visual Studio projects available in SDK.
Table 8-7. Windows Phone SDK Projects
Name |
Description |
---|---|
Yammer.OAuthSDK |
This is class library project that contains helper functions that allow you to integrate OAuth login and functions to make APIs calls. |
YammerIntegrationWindowsApp |
A sample Windows Phone 8 application that demonstrates how to set up and use these helper classes in an app. |
Add an Extension: WMAppManifest.xml
We will start by adding an extension to the WMAppManifest.xml file. Since you’ll be using Visual Studio Emulator to build and test this Windows phone app, the redirect_uri parameter must be set so that the IE browser on your Windows phone redirects the users to the Windows phone app after successful authentication and app authorization. To set up the redirect_uri, you need to set up the extension in the WMAppManifest.xml file.
The configuration of URI association is done in the WMAppManifest.xml file, which is part of your Windows phone project.
<Extensions>
<Protocol Name="SPDSWP8App" NavUriFragment="encodedLaunchUri=%s" TaskID="_default" />
</Extensions>
Note The Protocol Name="SPDSWP8App" should match the App.xaml RedirectURI of the Yammer app redirect URI configuration.
<model:OAuthClientInfo xmlns:model="clr-namespace:Yammer.OAuthSDK.Model;assembly=Yammer.OAuthSDK" x:Key="MyOAuthClientInfo"
ClientId="Fmi5JYfF5jqMLCcydqkJWQ"
ClientSecret="GBE5vp3mOUZuRVKqFPsXOA6eOLro95DOFVP5PPgSII0"
RedirectUri="SPDSWP8App://WPSample" />
The redirectURI in this configuration should match your redirect_URI in the Yammer’s app configuration, as illustrated in Figure 8-12.
Figure 8-12. Ensure that your Yammer app's redirect URI matches OAuthClientInfo’s redirect URI
Note The clr-namespace refers to the Yammer.OAuthSDK.Model class in the SDK library project you added in previous steps.
using Yammer.OAuthSDK.Model;
using Yammer.OAuthSDK.Utils;
public OAuthClientInfo MyOAuthClientInfo
{
get
{
return Resources["MyOAuthClientInfo"] as OAuthClientInfo;
}
}
// Override the default URI-mapper class with our OAuth URI handler.
RootFrame.UriMapper = new OAuthResponseUriMapper(MyOAuthClientInfo.RedirectUri);
Note MainPage.xaml is the default page with some UI element. It is actually a startup UI for the Silverlight application in the Windows phone app. Here, you can use the Silverlight controls for developing user interface with different layouts.
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="SPDS University Windows Phone App" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
<TextBlock Text="SPDS University" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="0,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Button Name="btnSignInWithYammer" HorizontalAlignment="Center" VerticalAlignment="Top" Click="btnSignInWithYammer_Click">
<Image Source="Assetsyammer-signin.gif" Width="179" Height="28" Stretch="Fill" />
</Button>
</Grid>
Note Yammer-signin.gif: Use the image of your choice stored in the Asset folder of your Windows app solution. You can also download an image from https://www.filepicker.io/api/file/KYDbdovdQAG9ABZ0LLiT.
<TextBlock x:Name="txbIsTokenPresent" Text="Is Token Present: No." TextAlignment="Center" />
After you have defined all the markup in the MainPage.xaml page, you add the code to the code-behind class of MainPage.xaml.
using Yammer.OAuthSDK.Model;
using Yammer.OAuthSDK.Utils;
string clientId = default(string);
string clientSecret = default(string);
string redirectUri = default(string);
// we extract these values from the App's Resource Dictionary config
clientId = ((App)App.Current).MyOAuthClientInfo.ClientId;
clientSecret = ((App)App.Current).MyOAuthClientInfo.ClientSecret;
redirectUri = ((App)App.Current).MyOAuthClientInfo.RedirectUri;
private void btnSignInWithYammer_Click(object sender, RoutedEventArgs e)
{
OAuthUtils.LaunchSignIn(clientId, redirectUri);
}
private void UpdateTokenMessage(bool isTokenPresent)
{
Dispatcher.BeginInvoke(() => txbIsTokenPresent.Text = isTokenPresent ? txbIsTokenPresent.Text.Replace("No.", "Yes.") : txbIsTokenPresent.Text.Replace("Yes.", "No."));
}
The final method you’ll add to the MainPage.xaml.cs file handles the redirect call. This is required as the IE browser window will redirect users to the Windows app after a successful user authentication. This method
Once the login is successful, the IE browser redirects users to REDIRECT_URI, which is configured in the Windows Phone App and App.xaml.cs’s <Extension> tag.
The Windows Phone App provides an OnNavigatedTo() event, which is used to handle the request.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
// Check the arguments from the query string passed to the page.
IDictionary<string, string> uriParams = NavigationContext.QueryString;
// "Approve"
if (uriParams.ContainsKey(Constants.OAuthParameters.Code) && uriParams.ContainsKey(Constants.OAuthParameters.State) && e.NavigationMode != NavigationMode.Back)
{
OAuthUtils.HandleApprove(
clientId,
clientSecret,
uriParams[Constants.OAuthParameters.Code],
uriParams[Constants.OAuthParameters.State],
onSuccess: () =>
{
UpdateTokenMessage(true);
}, onCSRF: () =>
{
MessageBox.Show("Unknown 'state' parameter. Discarding the authentication attempt.", "Invalid redirect.", MessageBoxButton.OK);
}, onErrorResponse: errorResponse =>
{
Dispatcher.BeginInvoke(() => MessageBox.Show(errorResponse.OAuthError.ToString(), "Invalid operation", MessageBoxButton.OK));
}, onException: ex =>
{
Dispatcher.BeginInvoke(() => MessageBox.Show(ex.ToString(), "Unexpected exception!", MessageBoxButton.OK));
}
);
}
// "Deny"
else if (uriParams.ContainsKey(Constants.OAuthParameters.Error) && e.NavigationMode != NavigationMode.Back)
{
string error, errorDescription;
error = uriParams[Constants.OAuthParameters.Error];
uriParams.TryGetValue(Constants.OAuthParameters.ErrorDescription, out errorDescription);
string msg = string.Format("error: {0} error_description:{1}", error, errorDescription);
MessageBox.Show(msg, "Error response is received.", MessageBoxButton.OK);
OAuthUtils.DeleteStoredToken();
UpdateTokenMessage(false);
}
// if token already exist
if (!string.IsNullOrEmpty(OAuthUtils.AccessToken))
{
// UpdateTokenMessage(true);
}
}
Code flow:
Run the Application
Figure 8-13. Run the Windows Phone App using the emulator
Figure 8-14. Windows phone landing page
When the Login with Yammer button is clicked, the Windows app will redirect you to the IE browser, as illustrated in Figure 8-15.
Figure 8-15. The Yammer Login screen presented to the user in Internet Explorer
Messages Management: Post a Message to Yammer’s Group
Yammer Windows phone enables developers to post a message to Yammer on behalf of users from their Windows phone apps.
public const string Message = @"https://www.yammer.com/api/v1/messages.json";
public static void PostMessage(Uri endpoint, string method, string data,
Action<string> onSuccess,
Action<AuthenticationResponse> onErrorResponse = null,
Action<Exception> onException = null)
{
if (endpoint == null || onSuccess == null)
{
throw new ArgumentNullException();
}
var webclient = new WebClient();
// We shouldn't use the url query paramters to send the token, we should use the header to send it more securely instead
webclient.Headers[HttpRequestHeader.Authorization] = "Bearer " + AccessToken;
// webclient.Headers["Content-Type"] = "application/json";
UploadStringCompletedEventHandler handler = null;
handler = (s, e) =>
{
webclient.UploadStringCompleted -= handler;
if (e.Error == null)
{
var result = e.Result;
// We just pass the raw text data response to the callback
onSuccess(result);
}
else
{
HandleExceptions(e.Error, onErrorResponse, onException);
}
};
webclient.UploadStringCompleted += handler;
webclient.UploadStringAsync(endpoint, method, data);
}
<Button Name="btnPostMsg" Grid.Row="1" HorizontalAlignment="Center" Background="Black" VerticalAlignment="Top" Click="btnPostMsgYammer_Click">
Post a Message
</Button>
<TextBlock x:Name="txtResponses" Text="" TextAlignment="Center" Grid.Column="1" Grid.Row="12" />
private void btnPostMsgYammer_Click(object sender, RoutedEventArgs e)
{
// Call this API to test if the auth token works
var messageApiEndpoint = new Uri(Constants.ApiEndpoints.Message, UriKind.Absolute);
String data = "body=We are in process of launching more technical trainings this year. Check our training portal home page for more details ";
OAuthUtils.PostMessage(messageApiEndpoint, "POST", data, onSuccess: response =>
{
// we just dump the unformated json string response into a textbox
Dispatcher.BeginInvoke(() => txtResponses.Text = "Message Posted");
},
onErrorResponse: errorResponse =>
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(errorResponse.OAuthError.ToString(), "Invalid operation", MessageBoxButton.OK);
txtResponses.Text = string.Empty;
});
},
onException: ex =>
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(ex.ToString(), "Unexpected exception!", MessageBoxButton.OK);
txtResponses.Text = string.Empty;
});
}
);
Dispatcher.BeginInvoke(() => txtResponses.Text = "Posting…");
}
In this method, YOU define a string variable called "data" which will hold the actual message to post. To post this message on a particular group, use the group_id. If group_id is omitted then the message will be posted to "ALL Company", which is your default group to post a message.
Once the message is constructed, call the OAuthUtils.PostMessage method by passing arguments. In addition, you can modify the data string variable to do the following.
Table 8-8. Variable Available for Data String
Variable |
Example |
---|---|
Reply_to_Id |
String data = “replied_to_id=432948966” + “&body=” + “Great!!”; |
Add Topics |
String data = “group_id=4659506&body=A message with Topic” + “&topic1=” + “YammerBook!!”; |
Private Message |
String data = “direct_to_id=1522209393&body=A message”; Where direct_to_id is the user ID |
Share a Post |
String data = “shared_message_id=433483891” + “&body=” + “Sharing an useful blog!!”; |
Messages Management: Like a Message
You can use the Yammer Windows Phone SDK to mark a message as Liked by the current user. Yammer provides current.json to support this activity. You’ll need the message_id in order to mark a message as Liked. In the following example, the post message, which was used while posting a message, is used with method type set to "POST". To like a message, the data parameter that was used as the message string to post is not required; therefore, it is passed as an empty string. The full URL of the current.json endpoint is:
https://www.yammer.com/api/v1/messages/liked_by/current.json?message_id=[:id]
where the ID represents the target message ID and method is the POST for marking a message as liked.
public const string current = @"https://www.yammer.com/api/v1/messages/liked_by/current.json";
<Button Name="btnlikemsg" Grid.Row="2" HorizontalAlignment="Center" Background="Black" VerticalAlignment="Top" Click="btnLiketMsgYammer_Click">
Like a Message
</Button>
private void btnLiketMsgYammer_Click(object sender, RoutedEventArgs e)
{
// Call this API to test if the auth token works
var messageApiEndpoint = new Uri(Constants.ApiEndpoints.current + "?message_id=508413888", UriKind.Absolute);
String data = "";
OAuthUtils.PostMessage(messageApiEndpoint, "POST", data, onSuccess: response =>
{
// we just dump the unformated json string response into a textbox
Dispatcher.BeginInvoke(() => txtResponses.Text = "Message Liked");
},
onErrorResponse: errorResponse =>
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(errorResponse.OAuthError.ToString(), "Invalid operation", MessageBoxButton.OK);
txtResponses.Text = string.Empty;
});
},
onException: ex =>
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(ex.ToString(), "Unexpected exception!", MessageBoxButton.OK);
txtResponses.Text = string.Empty;
});
}
);
Dispatcher.BeginInvoke(() => txtResponses.Text = "Liking…");
}
Messages Management: Unlike a Liked Message
You can use the message endpoint method to unlike a message that was marked as Liked by the current users. You’ll need message_id to unlike a message. The “mutator” method to unlike a message is DELETE.
public static void PostMessage(Uri endpoint, string method, string data,
Action<string> onSuccess,
Action<AuthenticationResponse> onErrorResponse = null,
Action<Exception> onException = null)
{
if (endpoint == null || onSuccess == null)
{
throw new ArgumentNullException();
}
var webclient = new WebClient();
// We shouldn't use the url query paramters to send the token, we should use the header to send it more securely instead
webclient.Headers[HttpRequestHeader.Authorization] = "Bearer " + AccessToken;
// webclient.Headers["Content-Type"] = "application/json";
UploadStringCompletedEventHandler handler = null;
handler = (s, e) =>
{
webclient.UploadStringCompleted -= handler;
if (e.Error == null)
{
var result = e.Result;
// We just pass the raw text data response to the callback
onSuccess(result);
}
else
{
HandleExceptions(e.Error, onErrorResponse, onException);
}
};
webclient.UploadStringCompleted += handler;
webclient.UploadStringAsync(endpoint, method, data);
}
<Button Name="btnunlikemsg" HorizontalAlignment="Center" Background="Black" VerticalAlignment="Top" Click="btnUnLikeMsgYammer_Click">
Unlike a Message
</Button>
/// <summary>
/// UnLike a Message Button event handler to Like a message specified by message_Id
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnUnLikeMsgYammer_Click(object sender, RoutedEventArgs e)
{
// Call this API to test if the auth token works
var messageApiEndpoint = new Uri(Constants.ApiEndpoints.current + "?message_id=508402750", UriKind.Absolute);
String data = "";
OAuthUtils.PostMessage(messageApiEndpoint, "DELETE", data, onSuccess: response =>
{
// we just dump the unformated json string response into a textbox
Dispatcher.BeginInvoke(() => txtResponses.Text = "Message Unliked");
},
onErrorResponse: errorResponse =>
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(errorResponse.OAuthError.ToString(), "Invalid operation", MessageBoxButton.OK);
txtResponses.Text = string.Empty;
});
},
onException: ex =>
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(ex.ToString(), "Unexpected exception!", MessageBoxButton.OK);
txtResponses.Text = string.Empty;
});
}
);
Dispatcher.BeginInvoke(() => txtResponses.Text = "Unliking…");
}
The previous event handler calls the same method that was called to like a message and post a message. The only difference is that the method type is DELETE instead of POST.
Messages Management: Retrieve All Messages
The Yammer REST API https://www.yammer.com/api/v1/messages.json enables developers to retrieve all messages for the current user. The Windows Phone SDK provides a method called GetJsonFromApi from the OAuthUtil class to retrieve all messages from Yammer and serialize the JSON to a .NET object. The following code snippet explains step-by-step how to call the SDK’s method. It uses a separate phone application page that contains a list view object to display returned records.
Figure 8-17. Add a new page using Add New Item
Figure 8-18. Add a new windows page
<Style x:Key="MessagesList" TargetType="ListBox">
<Setter Property="Margin" Value="5"/>
<Setter Property="Grid.Row" Value="1"/>
<Setter Property="Background" Value="White"/>
</Style>
<Style x:Key="SimpleBlock" TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Foreground" Value="YellowGreen"/>
<Setter Property="TextAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style x:Key="TitleBlock" TargetType="TextBlock">
<Setter Property="FontSize" Value="18"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Foreground" Value="WhiteSmoke"/>
<Setter Property="TextAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
This example uses the Yammer REST APIs that return the JSON object. In order to convert JSON to a .NET object, define a class and all the serializable properties for the object.
Figure 8-19. Add a folder to the project
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using Yammer.OAuthSDK.Utils;
using SPDS UniversityWinPhoneApp.Common;
namespace SPDS UniversityWinPhoneApp.Common
{
[DataContract]
public class YammerMessage
{
[DataMember(Name = "id")]
public string ID { get; set; }
[DataMember(Name = "sender_id")]
public string SenderID { get; set; }
[DataMember(Name = "replied_to_id")]
public string RepliedToID { get; set; }
[DataMember(Name = "created_at")]
public string CreatedAt { get; set; }
[DataMember(Name = "network_id")]
public string NetworkID { get; set; }
[DataMember(Name = "message_type")]
public string MessageType { get; set; }
[DataMember(Name = "sender_type")]
public string SenderType { get; set; }
[DataMember(Name = "url")]
public string Url { get; set; }
[DataMember(Name = "web_url")]
public string WebUrl { get; set; }
[DataMember(Name = "group_id")]
public string GroupId { get; set; }
[DataMember(Name = "body")]
public YammerMessageContent MessageContent { get; set; }
[DataMember(Name = "rich")]
public YammerMessageContent MessageContent1 { get; set; }
[DataMember(Name = "thread_id")]
public string ThreadID { get; set; }
[DataMember(Name = "client_type")]
public string ClientType { get; set; }
[DataMember(Name = "client_url")]
public string ClientUrl { get; set; }
[DataMember(Name = "system_message")]
public bool SystemMessage { get; set; }
[DataMember(Name = "direct_message")]
public bool DirectMessage { get; set; }
[DataMember(Name = "chat_client_sequence")]
public string ChatClientSequence { get; set; }
[DataMember(Name = "content_excerpt")]
public string ContentExcerpt { get; set; }
[DataMember(Name = "language")]
public string Language { get; set; }
[DataMember(Name = "notified_user_ids")]
public string notified_user_ids { get; set; }
[DataMember(Name = "privacy")]
public string privacy { get; set; }
[DataMember(Name = "group_created_id")]
public string group_created_id { get; set; }
public YammerMessage()
{
this.MessageContent = new YammerMessageContent();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using Yammer.OAuthSDK.Utils;
using SPDS UniversityWinPhoneApp.Common;
namespace SPDS UniversityWinPhoneApp.Common
{
[DataContract]
public class YammerMessageContent
{
[DataMember(Name = "parsed")]
public string ParsedText { get; set; }
[DataMember(Name = "plain")]
public string PlainText { get; set; }
[DataMember(Name = "rich")]
public string RichText { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using Yammer.OAuthSDK.Utils;
using SPDS UniversityWinPhoneApp.Common;
[DataContract]
public class YammerMessages
{
[DataMember(Name = "messages")]
public List<YammerMessage> Messages { get; set; }
public YammerMessages()
{
this.Messages = new List<YammerMessage>();
}
}
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using Yammer.OAuthSDK.Utils;
<ListBox x:Name="ListBoxAllMessage" ItemsSource="{Binding}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Line Stroke="White" X1="0" Y1="25" X2="800" Y2="25" />
<TextBlock Text="{Binding ID}" Style="{StaticResource SimpleBlock}" />
<TextBlock Text="{Binding MessageContent.PlainText}" Margin="5" Style="{StaticResource TitleBlock}" />
<Line Stroke="White" X1="0" Y1="25" X2="800" Y2="25" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock x:Name="txtResponses" Text="" TextAlignment="Center" />
The previous code uses a ListBox control with an item template. The item template defines a StackPanel to display a line, a text block for the message ID, a text block for the MessageContent.PlainText, and another line as a row separator. Define the appropriate binding as per the YammerMessage class definition.
The code-behind file of ViewAllMessage.xaml implements the server-side code that calls the Yammer REST API using the SDK’s helper functions.
private void Loaddata()
{
// Call this API to test if the auth token works
var messageApiEndpoint = new Uri(Constants.ApiEndpoints.Message, UriKind.Absolute);
OAuthUtils.GetJsonFromApi(messageApiEndpoint, onSuccess: response =>
{
byte[] byteArray = System.Text.UTF8Encoding.UTF8.GetBytes(response);
MemoryStream res = new MemoryStream(byteArray);
YammerMessages msgs = SerializationUtils.DeserializeJson<YammerMessages>(res);
ListBoxAllMessage.DataContext = msgs.Messages;
ListBoxAllMessage.ItemsSource = msgs.Messages;
// we just dump the unformated json string response into a textbox
Dispatcher.BeginInvoke(() => txtResponses.Text = "Messages Retrieved");
},
onErrorResponse: errorResponse =>
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(errorResponse.OAuthError.ToString(), "Invalid operation", MessageBoxButton.OK);
txtResponses.Text = string.Empty;
});
},
onException: ex =>
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(ex.ToString(), "Unexpected exception!", MessageBoxButton.OK);
txtResponses.Text = string.Empty;
});
}
);
Dispatcher.BeginInvoke(() => txtResponses.Text = "Retrieving ...");
}
}
The Loaddata method calls the Windows Phone SDK’s GetJsonFromApi method, which returns the JSON stream, which is then deserialized into a .NET object. Finally, the collection object called msgs of the YammerMessages class is assigned to ListBox as an ItemsSource property.
using Yammer.OAuthSDK.Utils;
using Yammer.OAuthSDK.Model;
using Yammer.OAuthSDK.Utils;
using System.IO;
using System.Text;
public ViewAllMessages ()
{
InitializeComponent();
Loaddata();
}
<Button Name="ViewallMessage" Grid.Row="4" HorizontalAlignment="Center" VerticalAlignment="Top" Click="ViewallMessage_Click">
View All Messages
</Button>
private void ViewallMessage_Click(object sender, RoutedEventArgs e)
{
NavigationService.Navigate(new Uri("/ViewAllMessages.xaml", UriKind.Relative));
}
User Management: Retrieve all Users
In the previous section, you implemented code to retrieve all messages for the current user. Yammer is a social site and the most important actor on any social site are the users. We’ll see how to retrieve Yammer’s users using the REST APIs.
Figure 8-20. Adding a page using Visual Studio Solution Explorer
Figure 8-21. Adding new items using the Add New Item screen
public const string allUsersUrl = "https://www.yammer.com/api/v1/users.json";
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.IO;
using System.Diagnostics;
namespace SPDS UniversityWinPhoneApp.Common
{
[DataContract]
public class YammerUser
{
[DataMember(Name = "id")]
public string UserID { get; set; }
[DataMember(Name = "network_id")]
public string NetworkID { get; set; }
[DataMember(Name = "state")]
public string AccountStatus { get; set; }
[DataMember(Name = "job_title")]
public string JobTitle { get; set; }
[DataMember(Name = "expertise")]
public string Expertise { get; set; }
[DataMember(Name = "full_name")]
public string FullName { get; set; }
[DataMember(Name = "first_name")]
public string FirstName { get; set; }
[DataMember(Name = "last_name")]
public string LastName { get; set; }
[DataMember(Name = "url")]
public string ApiUrl { get; set; }
[DataMember(Name = "web_url")]
public string WebUrl { get; set; }
[DataMember(Name = "mugshot_url")]
public string PhotoUrl { get; set; }
[DataMember(Name = "mugshot_url_template")]
public string PhotoTemplateUrl { get; set; }
[DataMember(Name = "department")]
public string Department { get; set; }
[DataMember(Name = "contact")]
public YammerContactInfo ContactInfo { get; set; }
[DataMember(Name = "web_preferences")]
public YammerSettingsAndFeedsAndGroups SettingsAndFeedsAndGroups { get; set; }
[DataMember(Name = "previous_companies")]
public List<YammerEmployer> PreviousEmployers { get; set; }
[DataMember(Name = "schools")]
public List<YammerSchool> Schools { get; set; }
[DataMember(Name = "stats")]
public YammerUserStats UserStats { get; set; }
public YammerUser()
{
this.ContactInfo = new YammerContactInfo();
this.SettingsAndFeedsAndGroups = new YammerSettingsAndFeedsAndGroups();
this.PreviousEmployers = new List<YammerEmployer>();
this.Schools = new List<YammerSchool>();
this.UserStats = new YammerUserStats();
}
}
[DataContract]
public class YammerUserStats
{
[DataMember(Name = "followers")]
public int Followers { get; set; }
[DataMember(Name = "following")]
public int Following { get; set; }
[DataMember(Name = "updates")]
public int Updates { get; set; }
}
[DataContract]
public class YammerSchool
{
[DataMember(Name = "degree")]
public string Degree { get; set; }
[DataMember(Name = "description")]
public string Description { get; set; }
[DataMember(Name = "end_year")]
public string EndYear { get; set; }
[DataMember(Name = "start_year")]
public string StartYear { get; set; }
[DataMember(Name = "school")]
public string School { get; set; }
}
[DataContract]
public class YammerEmployer
{
[DataMember(Name = "description")]
public string Description { get; set; }
[DataMember(Name = "employer")]
public string Employer { get; set; }
[DataMember(Name = "end_year")]
public string EndYear { get; set; }
[DataMember(Name = "position")]
public string Position { get; set; }
[DataMember(Name = "start_year")]
public string StartYear { get; set; }
}
[DataContract]
public class YammerSettingsAndFeedsAndGroups
{
[DataMember(Name = "network_settings")]
public YammerNetworkSettings NetworkSettings { get; set; }
[DataMember(Name = "home_tabs")]
public List<YammerGroupsAndFeeds> GroupsAndFeeds { get; set; }
public YammerSettingsAndFeedsAndGroups()
{
this.NetworkSettings = new YammerNetworkSettings();
this.GroupsAndFeeds = new List<YammerGroupsAndFeeds>();
}
}
[DataContract]
public class YammerGroupsAndFeeds
{
[DataMember(Name = "name")]
public string Name { get; set; }
[DataMember(Name = "select_name")]
public string SelectName { get; set; }
[DataMember(Name = "type")]
public string Type { get; set; }
[DataMember(Name = "feed_description")]
public string Description { get; set; }
[DataMember(Name = "ordering_index")]
public int OrderingIndex { get; set; }
[DataMember(Name = "url")]
public string Url { get; set; }
[DataMember(Name = "group_id")]
public string GroupID { get; set; }
[DataMember(Name = "private")]
public bool IsPrivate { get; set; }
}
[DataContract]
public class YammerNetworkSettings
{
[DataMember(Name = "message_prompt")]
public string MessagePrompt { get; set; }
[DataMember(Name = "allow_attachments")]
public bool AllowAttachments { get; set; }
[DataMember(Name = "show_communities_directory")]
public bool ShowCommunitiesDirectory { get; set; }
[DataMember(Name = "enable_groups")]
public bool EnableGroups { get; set; }
[DataMember(Name = "allow_yammer_apps")]
public bool AllowYammerApps { get; set; }
[DataMember(Name = "admin_can_delete_messages")]
public bool AdminCanDeleteMessages { get; set; }
[DataMember(Name = "allow_inline_document_view")]
public bool AllowInlineDocumentView { get; set; }
[DataMember(Name = "allow_inline_video")]
public bool AllowInlineVideo { get; set; }
[DataMember(Name = "enable_private_messages")]
public bool EnablePrivateMessages { get; set; }
[DataMember(Name = "allow_external_sharing")]
public bool AllowExternalSharing { get; set; }
[DataMember(Name = "enable_chat")]
public bool EnableChat { get; set; }
}
[DataContract]
public class YammerContactInfo
{
[DataMember(Name = "has_fake_email")]
public bool HasFakeEmail { get; set; }
[DataMember(Name = "email_addresses")]
public List<YammerEmailAddresses> EmailAddresses { get; set; }
[DataMember(Name = "phone_numbers")]
public List<YammerPhoneNumbers> PhoneNumbers { get; set; }
[DataMember(Name = "im")]
public YammerIM IM { get; set; }
public YammerContactInfo()
{
this.EmailAddresses = new List<YammerEmailAddresses>();
this.PhoneNumbers = new List<YammerPhoneNumbers>();
this.IM = new YammerIM();
}
}
[DataContract]
public class YammerEmailAddresses
{
[DataMember(Name = "address")]
public string Address { get; set; }
[DataMember(Name = "type")]
public string Type { get; set; }
public YammerEmailAddresses() { }
public YammerEmailAddresses(string address, string type)
{
this.Address = address;
this.Type = type;
}
}
[DataContract]
public class YammerPhoneNumbers
{
[DataMember(Name = "number")]
public string PhoneNumber { get; set; }
[DataMember(Name = "type")]
public string Type { get; set; }
}
[DataContract]
public class YammerIM
{
[DataMember(Name = "provider")]
public string Provider { get; set; }
[DataMember(Name = "username")]
public string UserName { get; set; }
}
}
<Button Name="btnUsers" Grid.Row="5" HorizontalAlignment="Center" VerticalAlignment="Top" Click="btnAllUserYammer_Click">
Get all Users
</Button>
private void btnAllUserYammer_Click(object sender, RoutedEventArgs e)
{
NavigationService.Navigate(new Uri("/ViewAllUsers.xaml", UriKind.Relative));
}
In the <Grid x:Name=“ContentPanel”> section, define the user interface to display messages retrieved from Yammer. To do this, use the following code snippet. Use the style properties you defined in previous sections of this chapter to “Retrieve All Messages”.
<ListBox x:Name="ListBoxAllUsers" ItemsSource="{Binding}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Line Stroke="White" X1="0" Y1="25" X2="800" Y2="25" />
<TextBlock Text="{Binding ID}" Style="{StaticResource SimpleBlock}" />
<TextBlock Text="{Binding FullName}" Margin="5" Style="{StaticResource TitleBlock}" />
<Line Stroke="White" X1="0" Y1="25" X2="800" Y2="25" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock x:Name="txtResponses" Text="" TextAlignment="Center" />
The previous code snippet uses a ListBox control with an Item template. The Item template defines a StackPanel to display a line, a text block for the message ID, a text block for MessageContent.PlainText, and another line as a row separator. Define the appropriate binding as per the YammerUsers class definition.
The code-behind file of ViewAllUsers.xaml.cs implements the server-side code that calls the Yammer REST API using the SDK’s helper functions.
private void Loaddata()
{
// Call this API to test if the auth token works
var messageApiEndpoint = new Uri(Constants.ApiEndpoints.allUsersUrl, UriKind.Absolute);
OAuthUtils.GetJsonFromApi(messageApiEndpoint, onSuccess: response =>
{
byte[] byteArray = System.Text.UTF8Encoding.UTF8.GetBytes(response);
MemoryStream res = new MemoryStream(byteArray);
List<YammerUser> users = SerializationUtils.DeserializeJson<List<YammerUser>>(res);
ListBoxAllUsers.DataContext = users;
ListBoxAllUsers.ItemsSource = users;
// we just dump the unformated json string response into a textbox
Dispatcher.BeginInvoke(() => txtResponses.Text = "Messages Retrieved");
},
onErrorResponse: errorResponse =>
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(errorResponse.OAuthError.ToString(), "Invalid operation", MessageBoxButton.OK);
txtResponses.Text = string.Empty;
});
},
onException: ex =>
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(ex.ToString(), "Unexpected exception!", MessageBoxButton.OK);
txtResponses.Text = string.Empty;
});
}
);
Dispatcher.BeginInvoke(() => txtResponses.Text = "Retrieving ...");
}
The Loaddata method calls the Windows Phone SDK’s GetJsonFromApi method, which returns the JSON stream, which is then deserialized into a .NET object. The collection object messages of the YammerUsers class is then assigned to ListBox as an ItemsSource property.
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using SPDS UniversityWinPhoneApp.Common;
using Yammer.OAuthSDK.Utils;
using Yammer.OAuthSDK.Model;
using System.IO;
using System.Text;
public ViewAllUsers ()
{
InitializeComponent();
Loaddata();
}
User Management: View Data About the Current User
The Yammer REST API provides an endpoint https://www.yammer.com/api/v1/users/current.json to retrieve the current user’s information. It includes profile information like username, job title, department, and contact info (email address, phone number, IM, and so on). Once you have the right permissions or the user has authorized your Yammer app to use her data, you can retrieve any piece of information belonging to a user node.
public const string CurrentUserUrl = "https://www.yammer.com/api/v1/users/current.json";
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel Grid.Row="0" Margin="12,17,0,28">
<StackPanel Orientation="Horizontal">
<TextBlock Text="User Name:" Margin="9,0,2,5" Style="{StaticResource InputLabel}" />
<TextBlock x:Name="tbUserName" Text="" Margin="9,-7,2,5" Style="{StaticResource InputLabel}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="job_title:" Margin="9,-7,0,5" Style="{StaticResource InputLabel}" />
<TextBlock x:Name="tbjob_title" Text="" Margin="9,-7,0,5" Style="{StaticResource InputLabel}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Followers:" Margin="9,-7,0,2" Style="{StaticResource InputLabel}" />
<TextBlock x:Name="tbFollowers" Text="" Margin="9,-7,0,5" Style="{StaticResource InputLabel}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Location:" Margin="9,-7,0,5" Style="{StaticResource InputLabel}" />
<TextBlock x:Name="tbLocation" Text="" Margin="9,-7,0,5" Style="{StaticResource InputLabel}" />
</StackPanel>
<TextBlock x:Name="txtResponses" Text="" TextAlignment="Center" />
</StackPanel>
</Grid>
In the code-behind of the ViewUserInfo.xaml.cs file, you can use the same code that was used to retrieve the user list. The only difference is to replace the List<YammerUser> collection object with the YammerUser object as the returned JSON object will hold only one user’s information. I also added a separator function called RenderUI by passing the deserialize JSON YammerUser object.
private void Loaddata()
{
// Call this API to test if the auth token works
var messageApiEndpoint = new Uri(Constants.ApiEndpoints.CurrentUserUrl, UriKind.Absolute);
OAuthUtils.GetJsonFromApi(messageApiEndpoint, onSuccess: response =>
{
string s = response;
byte[] byteArray = System.Text.UTF8Encoding.UTF8.GetBytes(response);
MemoryStream res = new MemoryStream(byteArray);
YammerUser YammerUser = SerializationUtils.DeserializeJson<YammerUser>(res);
RenderUI(YammerUser);
// we just dump the unformated json string response into a textbox
Dispatcher.BeginInvoke(() => txtResponses.Text = "User Info Retrieved");
},
onErrorResponse: errorResponse =>
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(errorResponse.OAuthError.ToString(), "Invalid operation", MessageBoxButton.OK);
txtResponses.Text = string.Empty;
});
},
onException: ex =>
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(ex.ToString(), "Unexpected exception!", MessageBoxButton.OK);
txtResponses.Text = string.Empty;
});
}
);
Dispatcher.BeginInvoke(() => txtResponses.Text = "Retrieving …");
}
private void RenderUI(YammerUser yammeruser)
{
tbUserName.Text = yammeruser.FullName;
tbjob_title.Text = yammeruser.JobTitle;
tbFollowers.Text = yammeruser.UserStats.Following.ToString();
}
That’s it! You can view the current user’s information. You can extend the code to display the other pieces of user information like user stats (followers, following, and so on), group membership details, and more.
using Yammer.OAuthSDK.Model;
using Yammer.OAuthSDK.Utils;
using YammerBook_Sample.Common;
using System.IO;
using System.Text;
public ViewUserInfo ()
{
InitializeComponent();
Loaddata();
}
<Button Name="btnViewUser" HorizontalAlignment="Center" Style="{StaticResource TabItemFirst}" VerticalAlignment="Top" Click="btnViewUserYammer_Click">
View Current User Info
</Button>
private void btnViewUserYammer_Click(object sender, RoutedEventArgs e)
{
NavigationService.Navigate(new Uri("/ViewUserInfo.xaml", UriKind.Relative));
}
User Management Search by Email Address
The Yammer REST API provides an endpoint called https://www.yammer.com/api/v1/users/[:id].json to retrieve the current users’ information and it includes profile information like username, job title, department, and contact info (email addresses, phone number, IM, and so on). Once you have the right permission or the user has already authorized your Yammer app to use the user’s data, you can retrieve any piece of information belonging to a user node. This is very similar to the REST API to view the current user; the only difference is that this API needs the user ID to retrieve the other user’s data instead of the retrieving data for the logged-in user.
In the sample application we are building, we’ll add a new Windows phone page to display the user’s information. For that, you need to add a new Windows phone page to your Windows phone project as you have done in previous examples. You can also use the same page used in the previous example, called ViewUserInfo.xaml, to display the other user data by using passing parameters between pages to decide on calling REST API for the current user or for other users. In this book, we are going to keep it simple and use another page to display other user information.
public const string SearchUserByEmail= "https://www.yammer.com/api/v1/users/by_email.json?email=";
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel Grid.Row="0" Margin="12,17,0,28">
<StackPanel Orientation="Horizontal">
<TextBlock Text="User Name:" Margin="9,0,2,5" Style="{StaticResource InputLabel}" />
<TextBlock x:Name="tbUserName" Text="" Margin="9,-7,2,5" Style="{StaticResource InputLabel}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="job_title:" Margin="9,-7,0,5" Style="{StaticResource InputLabel}" />
<TextBlock x:Name="tbjob_title" Text="" Margin="9,-7,0,5" Style="{StaticResource InputLabel}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Followers:" Margin="9,-7,0,2" Style="{StaticResource InputLabel}" />
<TextBlock x:Name="tbFollowers" Text="" Margin="9,-7,0,5" Style="{StaticResource InputLabel}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Location:" Margin="9,-7,0,5" Style="{StaticResource InputLabel}" />
<TextBlock x:Name="tbLocation" Text="" Margin="9,-7,0,5" Style="{StaticResource InputLabel}" />
</StackPanel>
<TextBlock x:Name="txtResponses" Text="" TextAlignment="Center" />
</StackPanel>
</Grid>
In the code-behind of the SearchUserInfo.xaml.cs file, you can use the same code that was used to retrieve the user list. The only difference is to replace the List<YammerUser> collection object with the YammerUser object as the returned JSON object will hold only one user’s information. I also added a separator function called RenderUI by passing the deserialize JSON YammerUser object.
private void Loaddata()
{
// Call this API to test if the auth token works
var emailaddress = "[email protected]";
var messageApiEndpoint = new Uri(Constants.ApiEndpoints.SearchUserByEmail + emailaddress.ToString(), UriKind.Absolute);
OAuthUtils.GetJsonFromApi(messageApiEndpoint, onSuccess: response =>
{
string s = response;
byte[] byteArray = System.Text.UTF8Encoding.UTF8.GetBytes(response);
MemoryStream res = new MemoryStream(byteArray);
List<YammerUser> YammerUser = SerializationUtils.DeserializeJson<List<YammerUser>>(res);
RenderUI(YammerUser[0]);
// we just dump the unformated json string response into a textbox
Dispatcher.BeginInvoke(() => txtResponses.Text = "User Info Retrieved");
},
onErrorResponse: errorResponse =>
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(errorResponse.OAuthError.ToString(), "Invalid operation", MessageBoxButton.OK);
txtResponses.Text = string.Empty;
});
},
onException: ex =>
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(ex.ToString(), "Unexpected exception!", MessageBoxButton.OK);
txtResponses.Text = string.Empty;
});
}
);
Dispatcher.BeginInvoke(() => txtResponses.Text = "Retrieving …");
}
private void RenderUI(YammerUser yammeruser)
{
tbUserName.Text = yammeruser.FullName;
tbjob_title.Text = yammeruser.JobTitle;
tbFollowers.Text = yammeruser.UserStats.Following.ToString();
}
That’s it. You can view the current user’s information. You can extend the code to display the other piece of user information like user stats (followers, following, and so on), group members, ship details, and so on.
using Yammer.OAuthSDK.Model;
using Yammer.OAuthSDK.Utils;
using YammerBook_Sample.Common;
using System.IO;
using System.Text;
public SearchUserInfo ()
{
InitializeComponent();
Loaddata();
}
<Button Name="btnSearchUser" HorizontalAlignment="Center" Style="{StaticResource TabItemFirst}" VerticalAlignment="Top" Click="btnSearchUserYammer_Click">
Search User Info
</Button>
private void btnSearchUserYammer_Click(object sender, RoutedEventArgs e)
{
NavigationService.Navigate(new Uri("/SearchUserInfo.xaml", UriKind.Relative));
}
User Management” Retrieve All Users from a Group
The Yammer REST API provides an endpoint called https://www.yammer.com/api/v1/users/in_group/[:id].json to retrieve all users who are members of a Yammer group in your Yammer network.
In the sample application we are building, we’ll add a new Windows phone page to display users who are member of a Yammer group. To do that, add a new Windows phone page to your Windows Phone project as you did in previous examples. You can also use the same page used in the ViewAllUsers.xaml example to display the user’s list by using passing parameters between pages to decide on calling REST API for the current user or for other users. In this book, we going to keep it simple and use another page to display other user information.
public const string ViewUserinGroup = "https://www.yammer.com/api/v1/users/in_group/";
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox x:Name="ListBoxAllUsers" ItemsSource="{Binding}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Line Stroke="White" X1="0" Y1="25" X2="800" Y2="25" />
<TextBlock Text="{Binding Department}" Style="{StaticResource SimpleBlock}" />
<TextBlock Text="{Binding FullName}" Margin="5" Style="{StaticResource TitleBlock}" />
<Line Stroke="White" X1="0" Y1="25" X2="800" Y2="25" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock x:Name="txtResponses" Text="" TextAlignment="Center" />
</Grid>
In the code-behind of the ViewAllUserinaGroup.xaml.cs file, you can use the same code that was used to retrieve the user list. The only difference is the REST API endpoint.
private void Loaddata()
{
// Call this API to test if the auth token works
var GroupId = 4659506;
var messageApiEndpoint = new Uri(Constants.ApiEndpoints.ViewUserinGroup + GroupId + ".json", UriKind.Absolute);
OAuthUtils.GetJsonFromApi(messageApiEndpoint, onSuccess: response =>
{
byte[] byteArray = System.Text.UTF8Encoding.UTF8.GetBytes(response);
MemoryStream res = new MemoryStream(byteArray);
List<YammerUser> users = SerializationUtils.DeserializeJson<List<YammerUser>>(res);
ListBoxAllUsers.DataContext = users;
ListBoxAllUsers.ItemsSource = users;
// we just dump the unformated json string response into a textbox
Dispatcher.BeginInvoke(() => txtResponses.Text = "Users Retrieved");
},
onErrorResponse: errorResponse =>
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(errorResponse.OAuthError.ToString(), "Invalid operation", MessageBoxButton.OK);
txtResponses.Text = string.Empty;
});
},
onException: ex =>
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(ex.ToString(), "Unexpected exception!", MessageBoxButton.OK);
txtResponses.Text = string.Empty;
});
}
);
Dispatcher.BeginInvoke(() => txtResponses.Text = "Retrieving …");
}
using Yammer.OAuthSDK.Model;
using Yammer.OAuthSDK.Utils;
using YammerBook_Sample.Common;
using System.IO;
using System.Text;
public ViewAllUserinaGroup()
{
InitializeComponent();
Loaddata();
}
<Button Name="btnViewUserinGroup" HorizontalAlignment="Center" Style="{StaticResource TabItemFirst}" VerticalAlignment="Top" Click="btnViewUserinGroup_Click">
View Users in a Group
</Button>
Code Snippet: Use the MainPage.xaml.cs to handle the click event, OnClick users will be redirected to “ViewAllUsersinaGroup.xaml” page
private void btnViewUserinGroup_Click(object sender, RoutedEventArgs e)
{
NavigationService.Navigate(new Uri("/ViewAllUsersinaGroup.xaml", UriKind.Relative));
}
Figure 8-22. Run the Windows phone app using the emulator
Figure 8-23. Run the Windows phone app using the emulator
Figure 8-24. View All Message page displays the message’s ID and body
In this exercise, you have learned how to integrate the Windows phone app with Yammer using the Yammer Windows Phone SDK.
Summary
By now you are familiar with the Yammer SDKs released by Yammer. In this chapter, you explored how to implement the “Sign In with Yammer” button using Yammer’s SDKs for Windows Phone App and then learned how to implement Yammer features into the Windows Phone by using the Windows Phone SDK.
We hope this book has helped you understand the value of Yammer and develop integrations with Yammer using existing integration features. As the Yammer team keeps adding new features, we recommend that you follow https://developer.yammer.com to get the latest updates on new features that you can use to develop integration with Yammer.