Hi% username%!
To be honest, I did not expect so many people to add to my favorites my previous
post . In fact, this is good news: the platform is actively developing and promoting, which attracts the attention of developers. Today I want to consecrate the theme of working with SkyDrive from the app. The article, like last time, will be based on a real case: I needed to enable the user to share the file in social networks.
Skydrive
For those who do not know - SkyDrive is an analogue of Microsoft's Dropbox: cloud storage with a capacity of 25 GB. SkyDrive is rather closely integrated with Windows Phone: in many marketing companies it is put in place of the lack of the possibility of using memory cards, a sort of "cloud flash drive." For example, if you want to share a photo on Twitter, the photo will be uploaded to skydrive and a link to it will be posted to Twitter. Let's implement the same functionality in our application.
Live SDK
To work with us, first of all, you need the Live SDK, which can be downloaded from the
link . With this SDK, we can do the following:
- Create / Open / Update / Delete folders
- Do the same with albums (a special kind of folder containing media files)
- Add / Delete Files
- Read / Change file / folder / album properties
- Move / Copy files / folders / albums
- Share files / folders / albums
Next, we need to get Client ID and Client Secret for our application. This can be done at the following
link .
Do not forget to specify in the API Settings tab that our application is a mobile client . Everything, now it is possible to begin to develop the application.
')
Authorization
First of all, we need to authorize our application to use SkyDrive. After installing the Live SDK, you will be able to use the new interface element: SignInButton.

<my:SignInButton Name="signInButton" Height="72" Margin="143,511,153,0" VerticalAlignment="Top" Branding="Skydrive" ClientId="_id" Content="Button" RedirectUri="http://oauth.live.com/desktop" Scopes="wl.basic wl.photos wl.skydrive wl.offline_access wl.signin wl.skydrive_update" SessionChanged="signInButton1_SessionChanged" TextType="SignIn" />
Let's look at the basic parameters:
Branding - the icon displayed on the button (it can also take the values "Windows", "Hotmail", "Messenger");
ClientId - ID of your application, obtained above;
RedirectUri - redirect address;
Scopes - permissions required by the application. Here we have indicated that we will log in, use SkyDrive, use the API for working with galleries and something else. Read more about the different types of Scopes, you can read the
link ;
SessionChanged - our authorization handler;
TextType - the text on the button. It can also be of several types: SignIn, Login, Connect and custom.
Now let's look at the handler:
private void signInButton1_SessionChanged(object sender, Microsoft.Live.Controls.LiveConnectSessionChangedEventArgs e) { if (e.Session != null && e.Status == LiveConnectSessionStatus.Connected) { App.Session = e.Session; } }
I prefer to store the session in App.xaml.cs: this will allow you to work with the API from any part of the application.
private static LiveConnectSession session = null; public static LiveConnectSession Session { get { return session; } set { session = value; } }
Do not forget to specify the namespace:
using Microsoft.Live;
Now, when you click on the
Sign In button, you will be prompted to log in with your Live ID and allow the application to use the functions that we have specified in
Scopes .

Create / check for a folder
In order to post a photo in a folder or album, you need to know its ID. Accordingly, when you create a folder, you are returned, including its ID. You can create an album, get its ID, record it in
IsolatedStorageSettings, and then upload photos using it. But if the user deletes the folder, or the folder with the specified name will already exist, then upload the photo in a similar way will not work. Therefore, I prefer to always first get a list of folders, check for the presence of the desired folder. And, if it is present, we upload files; if it is absent, we first create a folder, and then we load the file.
Getting the list of files and checking:
public class SkyDriveContent { public string Name { get; set; } public string ID { get; set; } } List<SkyDriveContent> ContentList = new List<SkyDriveContent>(); private void CheckAlbum() { if (App.Session == null) { MessageBox.Show("You must sign in first."); Waiting.Visibility = Visibility.Collapsed; } else { txtStatus.Text = "Checking album"; LiveConnectClient client = new LiveConnectClient(App.Session); client.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(clientDataFetch_GetCompleted); client.GetAsync("/me/skydrive/files"); } } void clientDataFetch_GetCompleted(object sender, LiveOperationCompletedEventArgs e) { if (e.Error == null) { List<object> data = (List<object>)e.Result["data"]; foreach (IDictionary<string, object> content in data) { SkyDriveContent skyContent = new SkyDriveContent(); skyContent.Name = (string)content["name"]; if (skyContent.Name == "SkyDriveTest") { albumID = (string)content["id"]; } ContentList.Add(skyContent); } if (albumID == "") CreateAlbum(); else UploadPhoto(); } else { MessageBox.Show("Error calling API: " + e.Error.ToString()); Waiting.Visibility = Visibility.Collapsed; } }
For parsing, I use the intermediate class SkyDriveContent, which stores folder names and their IDs. We check the names of all folders that are in the root of our SkyDrive. If the folder name “SkyDriveTest is found, then we take its ID, if we don’t find such a folder, we create it using a POST request:
private void CreateAlbum() { txtStatus.Text = "Creating album"; Dictionary<string, object> fileData = new Dictionary<string, object>(); fileData.Add("name", "SkyDriveTest"); LiveConnectClient client = new LiveConnectClient(App.Session); client.PostCompleted += new EventHandler<LiveOperationCompletedEventArgs>(CreateAlbum_Completed); client.PostAsync("me/albums", fileData); } void CreateAlbum_Completed(object sender, LiveOperationCompletedEventArgs e) { if (e.Error == null) { JObject jObject = JObject.Parse(e.RawResult); albumID = (string)jObject["id"]; UploadPhoto(); } else { MessageBox.Show("Error calling API: " + e.Error.ToString()); Waiting.Visibility = Visibility.Collapsed; } }
When we create a folder, the server in response sends us its properties in JSON format, including the ID. For deserialization, I use Json.NET, which is available in NuGet.
Upload and Share Photos
Now that we have a folder ID, we can upload a photo. The photo in the example we get from the camera:
void cameraCapture_Completed(object sender, PhotoResult e) { if (e.TaskResult == TaskResult.OK) { bitImage.SetSource(e.ChosenPhoto); image1.Source = bitImage; stream = new IsolatedStorageFileStream("/image.jpg", System.IO.FileMode.OpenOrCreate, iso); WriteableBitmap wb = new WriteableBitmap(bitImage); System.Windows.Media.Imaging.Extensions.SaveJpeg(wb, stream, wb.PixelWidth, wb.PixelHeight, 0, 80); stream.Close(); } }
Directly loading:
public void UploadPhoto() { txtStatus.Text = "Uploading photo"; LiveConnectClient uploadClient = new LiveConnectClient(App.Session); uploadClient.UploadCompleted += new EventHandler<LiveOperationCompletedEventArgs>(uploadClient_UploadCompleted); stream = iso.OpenFile("/image.jpg", System.IO.FileMode.Open, System.IO.FileAccess.Read); uploadClient.UploadAsync(albumID, "Image " + DateTime.Now.Millisecond + ".jpg", stream); } void uploadClient_UploadCompleted(object sender, LiveOperationCompletedEventArgs e) { stream.Close(); if (e.Error == null) { txtStatus.Text = "Sharing photo"; JObject jObject = JObject.Parse(e.RawResult); string name = (string)jObject["id"]; Share(name); } else { MessageBox.Show("Error calling API: " + e.Error.ToString()); Waiting.Visibility = Visibility.Collapsed; } }
As you can see, uploading a photo is almost the same. We, like in the past case, receive in response the ID of the downloaded image, which we will need to share it. By default, all files uploaded to the non-shared folder have the Private access modifier. Now let's share our image. This is done by adding the parameter "/ shared_read_link" to the ID of our image.
private void Share(string filename) { LiveConnectClient client = new LiveConnectClient(App.Session); client.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(GetSharedLink_Completed); client.GetAsync(filename + "/shared_read_link"); } void GetSharedLink_Completed(object sender, LiveOperationCompletedEventArgs e) { if (e.Error == null) { ShareLinkTask shareLinkTask = new ShareLinkTask(); shareLinkTask.Title = "Holiday Photo"; shareLinkTask.LinkUri = new Uri(e.Result["link"].ToString(), UriKind.Absolute); shareLinkTask.Message = "My super holiday photo via #HolidayPhoto!"; shareLinkTask.Show(); txtStatus.Text = "Done!"; Waiting.Visibility = Visibility.Collapsed; } else { MessageBox.Show("Error calling API: " + e.Error.ToString()); Waiting.Visibility = Visibility.Collapsed; } }

Here we get a link from our server to our file and transfer it to
ShareLinkTask . Everything, on this work is finished!
Conclusion
Of course, the capabilities of both the REST API for SkyDrive and the Live SDK as a whole are not limited to what I told you about. You can get additional information from the following sources:
Download an example from the article .
In this example, the image from the camera is taken and uploaded to SkyDrive. During the download, the status of the application is displayed.
Do not forget to specify your ClientID in the MainPage.xaml file! Without this, the application will not work!All creative exploits and successful certification! For those who do not know - the other day a new
contest for Windows Phone applications began.
UPD: With Habrastorage a little trouble, the pictures will soon return to their places.