├── Day29-OneDrive
├── Images
│ ├── aad-create-app-05.png
│ └── aad-grant-permissions-Files.png
├── FileUploadSample
│ ├── Assets
│ │ ├── StoreLogo.png
│ │ ├── SplashScreen.scale-200.png
│ │ ├── LockScreenLogo.scale-200.png
│ │ ├── Square44x44Logo.scale-200.png
│ │ ├── Wide310x150Logo.scale-200.png
│ │ ├── Square150x150Logo.scale-200.png
│ │ └── Square44x44Logo.targetsize-24_altform-unplated.png
│ ├── App.xaml
│ ├── Properties
│ │ ├── AssemblyInfo.cs
│ │ └── Default.rd.xml
│ ├── MainPage.xaml
│ ├── Package.appxmanifest
│ ├── App.xaml.cs
│ ├── FileUploadSample.csproj
│ └── MainPage.xaml.cs
├── FileUploadSample.sln
└── README.md
├── Day13-Postman.md
├── Day27-Teams.md
├── Day01-WhyMSGraph.md
├── Day02-OverviewMSGraph.md
├── Day29-OneDrive.md
├── Day28-Webhooks.md
├── Day10-AzureADAppV1.md
├── Day09-AzureADAppV2.md
├── Day23-SPAPart1.md
├── Day11-AppPermissions.md
├── Day17-AssignLicense.md
├── Day26-GraphAndFlow.md
├── Day25-OneNote.md
├── Day16-CreateUser.md
├── Day18-Mailbox.md
├── Day20-DeviceCode.md
├── Day21-Planner.md
├── Day19-O365GroupsPerm.md
├── Day15-DotnetCoreSample.md
├── Day05-QueryParamPt1.md
├── Day30-Conclusion.md
├── Day04-RequestSyntax.md
├── Day06-QueryParamPt2.md
├── Day24-SPAPart2.md
├── LICENSE
├── README.md
├── Day22-Intune.md
├── Day14-BatchProcessing.md
├── Day03-GraphExplorer.md
├── Day07-PagingNextLink.md
├── Day12-AuthScenarios.md
├── Day08-AccessTokens.md
└── .gitignore
/Day29-OneDrive/Images/aad-create-app-05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoftgraph/30DaysMSGraph-TryItOut/master/Day29-OneDrive/Images/aad-create-app-05.png
--------------------------------------------------------------------------------
/Day29-OneDrive/FileUploadSample/Assets/StoreLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoftgraph/30DaysMSGraph-TryItOut/master/Day29-OneDrive/FileUploadSample/Assets/StoreLogo.png
--------------------------------------------------------------------------------
/Day29-OneDrive/Images/aad-grant-permissions-Files.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoftgraph/30DaysMSGraph-TryItOut/master/Day29-OneDrive/Images/aad-grant-permissions-Files.png
--------------------------------------------------------------------------------
/Day29-OneDrive/FileUploadSample/Assets/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoftgraph/30DaysMSGraph-TryItOut/master/Day29-OneDrive/FileUploadSample/Assets/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/Day29-OneDrive/FileUploadSample/Assets/LockScreenLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoftgraph/30DaysMSGraph-TryItOut/master/Day29-OneDrive/FileUploadSample/Assets/LockScreenLogo.scale-200.png
--------------------------------------------------------------------------------
/Day29-OneDrive/FileUploadSample/Assets/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoftgraph/30DaysMSGraph-TryItOut/master/Day29-OneDrive/FileUploadSample/Assets/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/Day29-OneDrive/FileUploadSample/Assets/Wide310x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoftgraph/30DaysMSGraph-TryItOut/master/Day29-OneDrive/FileUploadSample/Assets/Wide310x150Logo.scale-200.png
--------------------------------------------------------------------------------
/Day29-OneDrive/FileUploadSample/Assets/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoftgraph/30DaysMSGraph-TryItOut/master/Day29-OneDrive/FileUploadSample/Assets/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/Day29-OneDrive/FileUploadSample/Assets/Square44x44Logo.targetsize-24_altform-unplated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoftgraph/30DaysMSGraph-TryItOut/master/Day29-OneDrive/FileUploadSample/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
--------------------------------------------------------------------------------
/Day29-OneDrive/FileUploadSample/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Day13-Postman.md:
--------------------------------------------------------------------------------
1 | # [Day 13 - Postman to make Microsoft Graph requests](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-13-postman-to-make-microsoft-graph-calls)
2 |
3 | Using Postman try below Microsoft Graph API calls:
4 |
5 | 1. Use Paging and NextLink discussed on Day 7 to get all users.
6 | 1. Use filter query parameters to filter the users by JobTitle.
--------------------------------------------------------------------------------
/Day27-Teams.md:
--------------------------------------------------------------------------------
1 | # [Day 27 - Use case: Create a Team](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-27-use-case-create-a-team)
2 |
3 | 1. Navigate to the [contoso-airlines-teams-sample repo](https://github.com/microsoftgraph/contoso-airlines-teams-sample).
4 | 1. Check out the [Teams overview](https://aka.ms/teamsgraph/v1) for more details on the Teams APIs in Microsoft Graph.
5 | 1. Watch the [video](https://aka.ms/teamsgraph/v1/video).
--------------------------------------------------------------------------------
/Day01-WhyMSGraph.md:
--------------------------------------------------------------------------------
1 | # [Day 1 - Why you should learn Microsoft Graph](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-1-why-you-should-learn-the-microsoft-graph)
2 |
3 | 1. What's new on Microsoft Graph (BUILD 2018): [https://channel9.msdn.com/events/Build/2018/THR5011](https://channel9.msdn.com/events/Build/2018/THR5011)
4 |
5 | 2. Microsoft Graph (BUILD 2019): [https://www.youtube.com/watch?v=XgkcCOvURaY](https://www.youtube.com/watch?v=XgkcCOvURaY)
6 |
--------------------------------------------------------------------------------
/Day02-OverviewMSGraph.md:
--------------------------------------------------------------------------------
1 | # [Day 2 - Overview Microsoft Graph](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-2-overview-microsoft-graph)
2 |
3 | 1. Microsoft Graph documentation: [https://developer.microsoft.com/en-us/graph](https://developer.microsoft.com/en-us/graph)
4 | - Also available at the short link [https://aka.ms/graph](https://aka.ms/graph)
5 | 1. Microsoft Graph blog: [https://developer.microsoft.com/en-us/graph/blogs](https://developer.microsoft.com/en-us/graph/blogs)
--------------------------------------------------------------------------------
/Day29-OneDrive.md:
--------------------------------------------------------------------------------
1 | # [Day 29 - Use case: Upload files to OneDrive](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-29-use-case-upload-files-to-onedrive)
2 |
3 | Navigate to the [30DaysMSGraph-TryItOut](https://github.com/microsoftgraph/30DaysMSGraph-TryItOut) repo. Clone the repo and configure the project in the Day 29 sub-folder using steps from the README or this post.
4 |
5 | If you run into any issues while building or configuring the project, please create a new Issue on the repo.
--------------------------------------------------------------------------------
/Day28-Webhooks.md:
--------------------------------------------------------------------------------
1 | # [Day 28 - Use case: Webhooks](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-28-use-case-webhooks)
2 |
3 | Navigate to the [dotnetcore-console-sample](https://github.com/microsoftgraph/dotnetcore-console-sample) repo. Clone the repo and configure the project in the Day 28 sub-folder.
4 |
5 | 1. Follow the instructions in Day 28 sub-folder to build the project from scratch yourself.
6 |
7 | If you run into any issues while building or configuring the project, please create a new Issue on the repo.
--------------------------------------------------------------------------------
/Day10-AzureADAppV1.md:
--------------------------------------------------------------------------------
1 | # [Day 10 - Azure AD application on V1 endpoint](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-10-azure-ad-applications-on-v1-endpoint)
2 |
3 | Navigate to the Azure AD Portal. Walk through these steps to create an app, assign it permissions, and grant admin consent.
4 |
5 | 1. Create a new Azure AD application.
6 | 1. Assign the delegated permission for Read user mail.
7 | 1. Assign the delegated permission for Read user calendars.
8 | 1. Assign the application permission for Read directory data.
9 | 1. Grant admin consent to the application.
--------------------------------------------------------------------------------
/Day09-AzureADAppV2.md:
--------------------------------------------------------------------------------
1 | # [Day 9 - Azure AD application on V2 endpoint](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-9-azure-ad-applications-on-v2-endpoint)
2 |
3 | Navigate to the [App registrations (Preview)](https://aka.ms/AppRegistrationsPreview). Walk through these steps to create an app, assign it permissions, and grant admin consent.
4 |
5 | 1. Create a new Azure AD application.
6 | 1. Assign the delegated permission for Mail.Read.
7 | 1. Assign the delegated permission for Calendars.ReadWrite.
8 | 1. Assign the application permission for User.Invite.All.
9 | 1. Grant admin consent to the application.
--------------------------------------------------------------------------------
/Day23-SPAPart1.md:
--------------------------------------------------------------------------------
1 | # [Day 23 - Use case: Calling Microsoft Graph from a single-page application Part 1](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-23-use-case-calling-microsoft-graph-from-a-single-page-application-part-1/)
2 |
3 | Navigate to [today's post](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-23-use-case-calling-microsoft-graph-from-a-single-page-application-part-1/).
4 |
5 | 1. Follow the instructions to update (or create new) the Azure AD V1 and V2 applications to support implicit authentication.
6 | 1. Use Postman to obtain an access token for the updated (newly created) Azure AD V1 and V2 applications.
--------------------------------------------------------------------------------
/Day11-AppPermissions.md:
--------------------------------------------------------------------------------
1 | # [Day 11 - Azure AD application permissions](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-11-azure-ad-application-permissions)
2 |
3 | Navigate to the [Microsoft Graph API reference](https://developer.microsoft.com/en-us/graph/docs/concepts/v1-overview).
4 |
5 | 1. Find 1 or more operations that you would like to complete and identify the permissions required for those operations.
6 | - Ex. Users – [Create User](https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/user_post_users)
7 | - Ex. Mail - [List Messages](https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/user_list_messages)
--------------------------------------------------------------------------------
/Day17-AssignLicense.md:
--------------------------------------------------------------------------------
1 | # [Day 17 - Use Case: Assign License](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-17-use-case-assign-license)
2 |
3 | Navigate to the [dotnetcore-console-sample](https://github.com/microsoftgraph/dotnetcore-console-sample) repo. Do one (or both) of the following:
4 |
5 | 1. Clone the repo and configure the project in the Day 17 sub-folder.
6 | 1. Follow the instructions in [Day 17 sub-folder](https://github.com/microsoftgraph/dotnetcore-console-sample/tree/master/day17-assign-license) to build the project from scratch yourself.
7 |
8 | If you run into any issues while building or configuring the project please create a new Issue on the repo.
--------------------------------------------------------------------------------
/Day26-GraphAndFlow.md:
--------------------------------------------------------------------------------
1 | # [Day 26 - Use case: Calling Microsoft Graph using Flow](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-26-use-case-calling-microsoft-graph-using-flow/)
2 |
3 | Create your own Microsoft Flow using Microsoft Graph. Then do one of the following:
4 |
5 | 1. Create Azure AD app registration (refer to [Day 9](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-9-azure-ad-applications-on-v2-endpoint) or [Day 10](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-10-azure-ad-applications-on-v1-endpoint) posts for more information)
6 | 1. Create the Flow using the above sample or download the flow package and update that.
--------------------------------------------------------------------------------
/Day25-OneNote.md:
--------------------------------------------------------------------------------
1 | # [Day 25 - Use case: Create a OneNote notebook](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-25-use-case-create-a-onenote-notebook)
2 |
3 | Navigate to the [dotnetcore-console-sample](https://github.com/microsoftgraph/dotnetcore-console-sample) repo. Do one (or both) of the following:
4 |
5 | 1. Clone the repo and configure the project in the Day 25 sub-folder.
6 | 1. Follow the instructions in [Day 25 sub-folder](https://github.com/microsoftgraph/dotnetcore-console-sample/tree/master/day25-onenote) to build the project from scratch yourself.
7 |
8 | If you run into any issues while building or configuring the project please create a new Issue on the repo.
--------------------------------------------------------------------------------
/Day16-CreateUser.md:
--------------------------------------------------------------------------------
1 | # [Day 16 - Use Case: Create user in Azure AD](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-16-use-case-create-user-in-azure-ad)
2 |
3 | Navigate to the [dotnetcore-console-sample](https://github.com/microsoftgraph/dotnetcore-console-sample) repo. Do one (or both) of the following:
4 |
5 | 1. Clone the repo and configure the project in the Day 16 subfolder.
6 | 1. Follow the instructions in [Day 16 subfolder](https://github.com/microsoftgraph/dotnetcore-console-sample/tree/master/day16-create-user) to build the project from scratch yourself.
7 |
8 | If you run into any issues while building or configuring the project please create a new Issue on the repo.
--------------------------------------------------------------------------------
/Day18-Mailbox.md:
--------------------------------------------------------------------------------
1 | # [Day 18 - Use Case: Update Exchange Online mailbox](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-18-use-case-update-user-mailbox-settings/)
2 |
3 | Navigate to the [dotnetcore-console-sample](https://github.com/microsoftgraph/dotnetcore-console-sample) repo. Do one (or both) of the following:
4 |
5 | 1. Clone the repo and configure the project in the Day 18 sub-folder.
6 | 1. Follow the instructions in [Day 18 sub-folder](https://github.com/microsoftgraph/dotnetcore-console-sample/tree/master/day18-mailbox) to build the project from scratch yourself.
7 |
8 | If you run into any issues while building or configuring the project please create a new Issue on the repo.
--------------------------------------------------------------------------------
/Day20-DeviceCode.md:
--------------------------------------------------------------------------------
1 | # [Day 20 - Use case: Device Code flow to authenticate users](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-20-use-case-device-code-flow-to-authenticate-users)
2 |
3 | Navigate to the [dotnetcore-console-sample](https://github.com/microsoftgraph/dotnetcore-console-sample) repo. Do one (or both) of the following:
4 |
5 | 1. Clone the repo and configure the project in the Day 20 sub-folder.
6 | 1. Follow the instructions in [Day 20 sub-folder](https://github.com/microsoftgraph/dotnetcore-console-sample/tree/master/day20-devicecode) to build the project from scratch yourself.
7 |
8 | If you run into any issues while building or configuring the project please create a new Issue on the repo.
--------------------------------------------------------------------------------
/Day21-Planner.md:
--------------------------------------------------------------------------------
1 | # [Day 21 - Use case: Create plans, buckets, and tasks in Planner](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-21-use-case-create-plans-buckets-and-tasks-in-planner)
2 |
3 | Navigate to the [dotnetcore-console-sample](https://github.com/microsoftgraph/dotnetcore-console-sample) repo. Do one (or both) of the following:
4 |
5 | 1. Clone the repo and configure the project in the Day 21 sub-folder.
6 | 1. Follow the instructions in [Day 21 sub-folder](https://github.com/microsoftgraph/dotnetcore-console-sample/tree/master/day21-planner) to build the project from scratch yourself.
7 |
8 | If you run into any issues while building or configuring the project please create a new Issue on the repo.
--------------------------------------------------------------------------------
/Day19-O365GroupsPerm.md:
--------------------------------------------------------------------------------
1 | # [Day 19 - Use Case: Assign Permissions using Unified Groups](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-19-use-case-assign-permissions-using-unified-groups/)
2 |
3 | Navigate to the [dotnetcore-console-sample](https://github.com/microsoftgraph/dotnetcore-console-sample) repo. Do one (or both) of the following:
4 |
5 | 1. Clone the repo and configure the project in the Day 19 sub-folder.
6 | 1. Follow the instructions in [Day 19 sub-folder](https://github.com/microsoftgraph/dotnetcore-console-sample/tree/master/day19-assign-permissions) to build the project from scratch yourself.
7 |
8 | If you run into any issues while building or configuring the project please create a new Issue on the repo.
--------------------------------------------------------------------------------
/Day15-DotnetCoreSample.md:
--------------------------------------------------------------------------------
1 | # [Day 15 - Microsoft Graph in .Net Core application](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-15-microsoft-graph-in-dotnet-core-application)
2 |
3 | Create your own Azure AD application from the instructions in [Day 15](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-15-microsoft-graph-in-dotnet-core-application) blog post. Then do one (or both if you are ambitious) of the following:
4 |
5 | 1. Build out the sample project from a blank .Net Core console application to use your Azure AD app registration.
6 | 1. Clone the [.Net Core console sample](https://github.com/microsoftgraph/dotnetcore-console-sample) from Microsoft Graph repo and configure it to use your Azure AD app registration.
--------------------------------------------------------------------------------
/Day05-QueryParamPt1.md:
--------------------------------------------------------------------------------
1 | # [Day 5 - Query Parameters Part 1](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-5-query-parameters-part-1)
2 |
3 | Use the query parameters covered today to filter, sort, and specify columns. Navigate to the [Graph Explorer](https://aka.ms/ge). Execute the following commands.
4 |
5 | 1. Get logged in user's high priority emails.
6 | - https://graph.microsoft.com/v1.0/me/messages?$filter=importance eq 'High'
7 | 1. Get name, size, and webUrl of logged in user's OneDrive site files.
8 | - https://graph.microsoft.com/v1.0/me/drive/root/children?$select=name,size,webUrl
9 | 1. Get logged in user's contacts sorted by birthday.
10 | - https://graph.microsoft.com/v1.0/me/contacts?$orderby=birthday
11 |
--------------------------------------------------------------------------------
/Day30-Conclusion.md:
--------------------------------------------------------------------------------
1 | # [Day 30 - Community resources and next steps](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-30-community-resources-and-next-steps)
2 |
3 | You may or may not know this but this project was almost entirely a labor of love and not the primary day job for many of our planners or contributors. This series wouldn't have been possible without all the planners, content contributors, and you as readers. A huge thank you to all for helping make this project a reality. As we reflect on lessons learned, what went well, and what we can improve on for future projects we especially appreciate your feedback. Please take a few minutes to share your feedback and suggestions on anything and everything related to this series as it helps make future projects like this possible.
4 |
5 | **30 Days of Microsoft Graph feedback and suggestions survey**
6 | [https://aka.ms/30DaysMSGraph-Survey](https://aka.ms/30DaysMSGraph-Survey)
--------------------------------------------------------------------------------
/Day04-RequestSyntax.md:
--------------------------------------------------------------------------------
1 | # [Day 4 - Request syntax](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-4-request-syntax)
2 |
3 | Explore additional resources related to the Me (logged in user) entity and also add query parameters to filter the base query. Navigate to the [Graph Explorer](https://aka.ms/ge) then execute the following commands:
4 |
5 | 1. Get logged in user's OneDrive site
6 | - [https://graph.microsoft.com/v1.0/me/drive](https://graph.microsoft.com/v1.0/me/drive)
7 | 1. Get users whose email address starts with "Adele"
8 | - [https://graph.microsoft.com/v1.0/users?\$filter=startswith(mail,'adele')](https://graph.microsoft.com/v1.0/users?$filter=startswith(mail,'adele'))
9 | 1. Get logged in user's user profile picture
10 | - [https://graph.microsoft.com/v1.0/me/photo/\$value](https://graph.microsoft.com/v1.0/me/photo/$value)
11 | 1. (Choose a new sample query by clicking show more samples from the left hand menu)
--------------------------------------------------------------------------------
/Day06-QueryParamPt2.md:
--------------------------------------------------------------------------------
1 | # [Day 6 - Query Parameters Part 2](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-6-query-parameters-part-2)
2 |
3 | Use query parameters we covered today to count, search, expand, and restrict results. Navigate to the [Graph Explorer](https://aka.ms/ge). Execute the following commands.
4 |
5 | 1. Get number of contacts for the logged in user
6 | - https://graph.microsoft.com/v1.0/me/contacts?$count=true
7 | 1. Get the logged in user's OneNote notebooks, 2 per page
8 | - https://graph.microsoft.com/v1.0/me/onenote/notebooks?$top=2
9 | 1. Get the logged in user's emails starting with the 11th email
10 | - https://graph.microsoft.com/v1.0/me/messages?$skip=10
11 | 1. Get the logged in user's emails that contain the word "Contoso" in the message body
12 | - https://graph.microsoft.com/v1.0/me/messages?$search="body:Contoso"
13 | 1. Get expanded information for logged in user's manager
14 | - https://graph.microsoft.com/beta/me?$expand=manager
15 |
--------------------------------------------------------------------------------
/Day24-SPAPart2.md:
--------------------------------------------------------------------------------
1 | # [Day 24 - Use case: Calling Microsoft Graph from a single-page application Part 2](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-24-use-case-calling-microsoft-graph-from-a-single-page-application-part-2/)
2 |
3 | Navigate to [today's post](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-24-use-case-calling-microsoft-graph-from-a-single-page-application-part-2/).
4 |
5 | 1. Complete the pre-requisites in [Day 23](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-23-use-case-calling-microsoft-graph-from-a-single-page-application-part-1/) to prepare an Azure AD app for V1 and V2.
6 | 1. Download or clone Bob German's [AADSamples repo](https://github.com/BobGerman/AADsamples) and navigate to the [implicitFlow sub-folder](https://github.com/BobGerman/AADsamples/tree/master/implicitFlow).
7 | 1. Follow the instructions in either Day 24 or the [README](https://github.com/BobGerman/AADsamples/blob/master/implicitFlow/readme.md) in repo (the latter will also contain Day 23's instructions, so skip to the [Sample Applications](https://github.com/BobGerman/AADsamples/tree/master/implicitFlow#sample-applications) section).
--------------------------------------------------------------------------------
/Day29-OneDrive/FileUploadSample/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("FileUploadSample")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("FileUploadSample")]
13 | [assembly: AssemblyCopyright("Copyright © 2018")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Version information for an assembly consists of the following four values:
18 | //
19 | // Major Version
20 | // Minor Version
21 | // Build Number
22 | // Revision
23 | //
24 | // You can specify all the values or you can default the Build and Revision Numbers
25 | // by using the '*' as shown below:
26 | // [assembly: AssemblyVersion("1.0.*")]
27 | [assembly: AssemblyVersion("1.0.0.0")]
28 | [assembly: AssemblyFileVersion("1.0.0.0")]
29 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation. All rights reserved.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 30 Days of Microsoft Graph - Try It Out
2 |
3 | The files in this repo correspond to the daily
4 | Try It Out exercises from the [30 Days of Microsoft Graph](https://aka.ms/30DaysMSGraph) blog series. Each day has a corresponding Markdown file consisting of resource links, hands-on exercises, or sample projects.
5 |
6 | ## Contributing
7 |
8 | This project welcomes contributions and suggestions. Most contributions require you to agree to a
9 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
10 | the rights to use your contribution. For details, visit https://cla.microsoft.com.
11 |
12 | When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
13 | a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
14 | provided by the bot. You will only need to do this once across all repos using our CLA.
15 |
16 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
17 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
18 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
19 |
--------------------------------------------------------------------------------
/Day29-OneDrive/FileUploadSample/Properties/Default.rd.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Day22-Intune.md:
--------------------------------------------------------------------------------
1 | # [Day 22 - Use case: Device and App Management with Intune](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-22-device-and-app-management-with-intune)
2 |
3 | Navigate to the [dotnetcore-console-sample](https://github.com/microsoftgraph/dotnetcore-console-sample) repo. Do one (or both) of the following:
4 |
5 | 1. Sign up for a free Intune trial at [https://docs.microsoft.com/en-us/intune/get-started-evaluation](https://docs.microsoft.com/en-us/intune/get-started-evaluation).
6 | 1. Clone the dotnetcore-console-sample repo and configure the project in the [Day 22 sub-folder](https://github.com/microsoftgraph/dotnetcore-console-sample/tree/master/day22-intune).
7 | 1. Follow the instructions in readme.md to add Intune functionality to the sample program. (This exercise requires delegated permissions so be sure to include device code authentication from [Day 20](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-20-use-case-device-code-flow-to-authenticate-users) if building from scratch).
8 | 1. Check out [https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/resources/intune_graph_overview](https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/resources/intune_graph_overview) for more details on the Intune APIs in Microsoft Graph.
9 |
10 | If you run into any issues while building or configuring the project please create a new Issue on the repo.
--------------------------------------------------------------------------------
/Day29-OneDrive/FileUploadSample/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 | Upload to SharePoint?
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Day14-BatchProcessing.md:
--------------------------------------------------------------------------------
1 | # [Day 14 - Batch processing](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-14-batch-processing)
2 |
3 | 1. Create a batch request to get user profile picture, list of direct reports, list of calendar reminders for today.
4 |
5 | ```json
6 | {
7 | "requests": [
8 | {
9 | "id": "1",
10 | "method": "GET",
11 | "url": "/me/photo/$value"
12 | },
13 | {
14 | "id": "2",
15 | "method": "GET",
16 | "url": "/me/directReports"
17 | },
18 | {
19 | "id": "3",
20 | "method": "GET",
21 | "url": "/me/reminderView(startDateTime='2018-11-134T08:00:00.0000000', endDateTime='2018-11-134T17:00:00.0000000')",
22 | "headers": {
23 | "Content-Type": "application/json"
24 | }
25 | }
26 | ]
27 | }
28 | ```
29 |
30 | 1. Assuming you got a list of your direct reports, now you can build another batch request to check track their out of office settings. Below is a sample batch request. Be sure to replace \, etc. with the actual user UPN values returned from above query Ex. john@contoso.com.
31 |
32 | ```json
33 | {
34 | "requests": [
35 | {
36 | "id": "1",
37 | "method": "GET",
38 | "url": "/users/john@contoso.com/mailboxSettings/automaticRepliesSetting"
39 | },
40 | {
41 | "id": "2",
42 | "method": "GET",
43 | "url": "/users/katie@contoso.com/mailboxSettings/automaticRepliesSetting"
44 | },
45 | …
46 | …
47 | ]
48 | }
49 | ```
--------------------------------------------------------------------------------
/Day29-OneDrive/FileUploadSample/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
13 |
14 |
15 |
16 |
17 | FileUploadSample
18 | jeremyke
19 | Assets\StoreLogo.png
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Day03-GraphExplorer.md:
--------------------------------------------------------------------------------
1 | # [Day 3 - Graph Explorer](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-3-graph-explorer)
2 |
3 | Navigate to the [Graph Explorer](https://aka.ms/ge). Try the following calls to the Microsoft Graph using the demo tenant or logging into your own tenant.
4 |
5 | 1. Get logged in user - https://graph.microsoft.com/v1.0/me
6 |
7 | Sample response:
8 |
9 | ```json
10 | {
11 | "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
12 | "id": "48d31887-5fad-4d73-a9f5-3c356e68a038",
13 | "businessPhones": [
14 | "+1 412 555 0109"
15 | ],
16 | "displayName": "Megan Bowen",
17 | "givenName": "Megan",
18 | "jobTitle": "Auditor",
19 | "mail": "MeganB@M365x214355.onmicrosoft.com",
20 | "mobilePhone": null,
21 | "officeLocation": "12/1110",
22 | "preferredLanguage": "en-US",
23 | "surname": "Bowen",
24 | "userPrincipalName": "MeganB@M365x214355.onmicrosoft.com"
25 | }
26 | ```
27 |
28 | 1. Get logged in user's manager - https://graph.microsoft.com/v1.0/me/manager
29 |
30 | Sample response:
31 |
32 | ```json
33 | {
34 | "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#directoryObjects/$entity",
35 | "@odata.type": "#microsoft.graph.user",
36 | "id": "24fcbca3-c3e2-48bf-9ffc-c7f81b81483d",
37 | "businessPhones": [
38 | "+1 205 555 0108"
39 | ],
40 | "displayName": "Diego Siciliani",
41 | "givenName": "Diego",
42 | "jobTitle": "CVP Finance",
43 | "mail": "DiegoS@M365x214355.onmicrosoft.com",
44 | "mobilePhone": null,
45 | "officeLocation": "14/1108",
46 | "preferredLanguage": "en-US",
47 | "surname": "Siciliani",
48 | "userPrincipalName": "DiegoS@M365x214355.onmicrosoft.com"
49 | }
50 | ```
--------------------------------------------------------------------------------
/Day07-PagingNextLink.md:
--------------------------------------------------------------------------------
1 | # [Day 7 - Paging and NextLink](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-7-paging-and-nextlink)
2 |
3 | Navigate to the [Graph Explorer](https://aka.ms/ge). Execute the following commands.
4 |
5 | 1. Get the users from your organization’s directory
6 | - https://graph.microsoft.com/v1.0/users?$top=10
7 | 1. Get all the items in your OneDrive for Business
8 | - https://graph.microsoft.com/v1.0/me/drive/root/children?$top=5
9 | 1. Get all the items from a SharePoint Online Site list
10 | - https://graph.microsoft.com/v1.0/sites/m365x214355.sharepoint.com:/sites/HR:/lists/ed70c81d-fedf-4a1b-a1f1-f44e39c5bb78/items?$top=5000
11 | - See appendix for details on how to build this Microsoft Graph query for SharePoint
12 |
13 | ## Appendix
14 |
15 | How to get SharePoint List Items using Microsoft Graph
16 |
17 | 1. If you are not logged into the Graph Explorer (i.e. using a demo tenant) find out the name of the tenant. Issue the following Microsoft Graph query:
18 | - https://graph.microsoft.com/v1.0/sites/root
19 | - Copy the **hostname** value from siteCollection entity, ex. "m365x214355.sharepoint.com"
20 | 1. Next you must use the site collection relative URL and find out the **id** of a list on that site. Issue below Microsoft Graph query to get those details:
21 | - https://graph.microsoft.com/v1.0/sites/:/\:/lists
22 | - Ex. https://graph.microsoft.com/v1.0/sites/m365x214355.sharepoint.com:/sites/HR:/lists
23 | - Copy the **{id}** value from the first list record shown.
24 | - Ex. "id": "ed70c81d-fedf-4a1b-a1f1-f44e39c5bb78"
25 | 1. Next create Microsoft Graph query to fetch the top 5000 items (max that SharePoint can return in one page) from the list
26 | - https://graph.microsoft.com/v1.0/sites/:/\:/lists//items?$top=5000
27 | - Ex. https://graph.microsoft.com/v1.0/sites/m365x214355.sharepoint.com:/sites/HR:/lists/ed70c81d-fedf-4a1b-a1f1-f44e39c5bb78/items?$top=5000
28 |
--------------------------------------------------------------------------------
/Day29-OneDrive/FileUploadSample.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27703.2042
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileUploadSample", "FileUploadSample\FileUploadSample.csproj", "{051BC360-AF62-4600-8AED-32172F4480A3}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|ARM = Debug|ARM
11 | Debug|x64 = Debug|x64
12 | Debug|x86 = Debug|x86
13 | Release|ARM = Release|ARM
14 | Release|x64 = Release|x64
15 | Release|x86 = Release|x86
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {051BC360-AF62-4600-8AED-32172F4480A3}.Debug|ARM.ActiveCfg = Debug|ARM
19 | {051BC360-AF62-4600-8AED-32172F4480A3}.Debug|ARM.Build.0 = Debug|ARM
20 | {051BC360-AF62-4600-8AED-32172F4480A3}.Debug|ARM.Deploy.0 = Debug|ARM
21 | {051BC360-AF62-4600-8AED-32172F4480A3}.Debug|x64.ActiveCfg = Debug|x64
22 | {051BC360-AF62-4600-8AED-32172F4480A3}.Debug|x64.Build.0 = Debug|x64
23 | {051BC360-AF62-4600-8AED-32172F4480A3}.Debug|x64.Deploy.0 = Debug|x64
24 | {051BC360-AF62-4600-8AED-32172F4480A3}.Debug|x86.ActiveCfg = Debug|x86
25 | {051BC360-AF62-4600-8AED-32172F4480A3}.Debug|x86.Build.0 = Debug|x86
26 | {051BC360-AF62-4600-8AED-32172F4480A3}.Debug|x86.Deploy.0 = Debug|x86
27 | {051BC360-AF62-4600-8AED-32172F4480A3}.Release|ARM.ActiveCfg = Release|ARM
28 | {051BC360-AF62-4600-8AED-32172F4480A3}.Release|ARM.Build.0 = Release|ARM
29 | {051BC360-AF62-4600-8AED-32172F4480A3}.Release|ARM.Deploy.0 = Release|ARM
30 | {051BC360-AF62-4600-8AED-32172F4480A3}.Release|x64.ActiveCfg = Release|x64
31 | {051BC360-AF62-4600-8AED-32172F4480A3}.Release|x64.Build.0 = Release|x64
32 | {051BC360-AF62-4600-8AED-32172F4480A3}.Release|x64.Deploy.0 = Release|x64
33 | {051BC360-AF62-4600-8AED-32172F4480A3}.Release|x86.ActiveCfg = Release|x86
34 | {051BC360-AF62-4600-8AED-32172F4480A3}.Release|x86.Build.0 = Release|x86
35 | {051BC360-AF62-4600-8AED-32172F4480A3}.Release|x86.Deploy.0 = Release|x86
36 | EndGlobalSection
37 | GlobalSection(SolutionProperties) = preSolution
38 | HideSolutionNode = FALSE
39 | EndGlobalSection
40 | GlobalSection(ExtensibilityGlobals) = postSolution
41 | SolutionGuid = {A5031674-7518-47EE-9373-CEC8ACA4F724}
42 | EndGlobalSection
43 | EndGlobal
44 |
--------------------------------------------------------------------------------
/Day12-AuthScenarios.md:
--------------------------------------------------------------------------------
1 | # [Day 12 - Authentication and authorization scenarios](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-12-authentication-and-authorization-scenarios)
2 |
3 | You can try the authorization code grant flow out using your browser and [Postman](https://www.getpostman.com/apps). If you are not familiar with Postman or similar REST endpoint development tools feel free to revisit these exercises after you've gone through tomorrow's post for Day 13.
4 |
5 | 1. Register an Azure AD V2 app following the directions from Day 9.
6 | - Ensure that the redirect URI is https://localhost:8080 to match the below steps.
7 | 1. Open Postman and create a new POST request to https://login.microsoftonline.com/YOUR_TENANT_ID/oauth2/v2.0/token, replacing ‘YOUR_TENANT_ID’ with your tenant ID from your app registration.
8 | 1. Configure the Body tab as follows:
9 | - Choose ‘x-www-form-urlencoded’
10 | - Add a ‘client_id’ key and put your application ID from your app registration in the value
11 | - Add a ‘client_secret’ key and put your application secret from your app registration in the value
12 | - Add a ‘redirect_uri’ key and put ‘https://localhost:8080’ in the value
13 | - Add a ‘grant_type’ key and put ‘authorization_code’ in the value.
14 | - Add a ‘scope’ key and put ‘openid profile offline_access User.Read’ in the value.
15 | - Add a ‘code’ key and leave the value blank.
16 | 1. Open your browser and go to https://login.microsoftonline.com/YOUR_TENANT_ID/oauth2/v2.0/authorize?client_id=YOUR_APP_ID&response_type=code&redirect_uri=https%3A%2F%2Flocalhost%3A8080&response_mode=query&scope=openid%20profile%20offline_access%20User.Read, replacing ‘YOUR_TENANT_ID’ with your tenant ID and ‘YOUR_APP_ID’ with your application ID from your app registration.
17 | 1. Login and authorize the app. Your browser redirects back to https://localhost:8080 and should show an error that the site cannot be reached.
18 | 1. Copy the URL in the address bar of your browser and paste it into Notepad. It should look like https://localhost:8080/?code=IAQABAAIAAAC...&session_state=.... Copy all of the characters after code= and before &session_state. This is the authorization code returned by Azure.
19 | 1. Paste the authorization code into the ‘code’ key in Postman, then send the request.
20 | 1. The response contains a JSON payload with the access token, refresh token, and ID token.
--------------------------------------------------------------------------------
/Day08-AccessTokens.md:
--------------------------------------------------------------------------------
1 | # [Day 8 - Authentication roadmap and access tokens](https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-8-authentication-roadmap-and-access-tokens)
2 |
3 | Navigate to the documentation for [Azure AD Access Tokens](https://docs.microsoft.com/en-us/azure/active-directory/develop/access-tokens). Decode the v1 and v2 sample tokens using [http://jwt.ms](http://jwt.ms).
4 |
5 | 1. V1 sample token
6 | - eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Imk2bEdrM0ZaenhSY1ViMkMzbkVRN3N5SEpsWSIsImtpZCI6Imk2bEdrM0ZaenhSY1ViMkMzbkVRN3N5SEpsWSJ9.eyJhdWQiOiJlZjFkYTlkNC1mZjc3LTRjM2UtYTAwNS04NDBjM2Y4MzA3NDUiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9mYTE1ZDY5Mi1lOWM3LTQ0NjAtYTc0My0yOWYyOTUyMjIyOS8iLCJpYXQiOjE1MzcyMzMxMDYsIm5iZiI6MTUzNzIzMzEwNiwiZXhwIjoxNTM3MjM3MDA2LCJhY3IiOiIxIiwiYWlvIjoiQVhRQWkvOElBQUFBRm0rRS9RVEcrZ0ZuVnhMaldkdzhLKzYxQUdyU091TU1GNmViYU1qN1hPM0libUQzZkdtck95RCtOdlp5R24yVmFUL2tES1h3NE1JaHJnR1ZxNkJuOHdMWG9UMUxrSVorRnpRVmtKUFBMUU9WNEtjWHFTbENWUERTL0RpQ0RnRTIyMlRJbU12V05hRU1hVU9Uc0lHdlRRPT0iLCJhbXIiOlsid2lhIl0sImFwcGlkIjoiNzVkYmU3N2YtMTBhMy00ZTU5LTg1ZmQtOGMxMjc1NDRmMTdjIiwiYXBwaWRhY3IiOiIwIiwiZW1haWwiOiJBYmVMaUBtaWNyb3NvZnQuY29tIiwiZmFtaWx5X25hbWUiOiJMaW5jb2xuIiwiZ2l2ZW5fbmFtZSI6IkFiZSAoTVNGVCkiLCJpZHAiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC83MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMjIyNDcvIiwiaXBhZGRyIjoiMjIyLjIyMi4yMjIuMjIiLCJuYW1lIjoiYWJlbGkiLCJvaWQiOiIwMjIyM2I2Yi1hYTFkLTQyZDQtOWVjMC0xYjJiYjkxOTQ0MzgiLCJyaCI6IkkiLCJzY3AiOiJ1c2VyX2ltcGVyc29uYXRpb24iLCJzdWIiOiJsM19yb0lTUVUyMjJiVUxTOXlpMmswWHBxcE9pTXo1SDNaQUNvMUdlWEEiLCJ0aWQiOiJmYTE1ZDY5Mi1lOWM3LTQ0NjAtYTc0My0yOWYyOTU2ZmQ0MjkiLCJ1bmlxdWVfbmFtZSI6ImFiZWxpQG1pY3Jvc29mdC5jb20iLCJ1dGkiOiJGVnNHeFlYSTMwLVR1aWt1dVVvRkFBIiwidmVyIjoiMS4wIn0=.D3H6pMUtQnoJAGq6AHd
7 |
8 | 1. V2 sample token
9 | - eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Imk2bEdrM0ZaenhSY1ViMkMzbkVRN3N5SEpsWSJ9.eyJhdWQiOiI2ZTc0MTcyYi1iZTU2LTQ4NDMtOWZmNC1lNjZhMzliYjEyZTMiLCJpc3MiOiJodHRwczovL2xvZ2luLm1pY3Jvc29mdG9ubGluZS5jb20vNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3L3YyLjAiLCJpYXQiOjE1MzcyMzEwNDgsIm5iZiI6MTUzNzIzMTA0OCwiZXhwIjoxNTM3MjM0OTQ4LCJhaW8iOiJBWFFBaS84SUFBQUF0QWFaTG8zQ2hNaWY2S09udHRSQjdlQnE0L0RjY1F6amNKR3hQWXkvQzNqRGFOR3hYZDZ3TklJVkdSZ2hOUm53SjFsT2NBbk5aY2p2a295ckZ4Q3R0djMzMTQwUmlvT0ZKNGJDQ0dWdW9DYWcxdU9UVDIyMjIyZ0h3TFBZUS91Zjc5UVgrMEtJaWpkcm1wNjlSY3R6bVE9PSIsImF6cCI6IjZlNzQxNzJiLWJlNTYtNDg0My05ZmY0LWU2NmEzOWJiMTJlMyIsImF6cGFjciI6IjAiLCJuYW1lIjoiQWJlIExpbmNvbG4iLCJvaWQiOiI2OTAyMjJiZS1mZjFhLTRkNTYtYWJkMS03ZTRmN2QzOGU0NzQiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhYmVsaUBtaWNyb3NvZnQuY29tIiwicmgiOiJJIiwic2NwIjoiYWNjZXNzX2FzX3VzZXIiLCJzdWIiOiJIS1pwZmFIeVdhZGVPb3VZbGl0anJJLUtmZlRtMjIyWDVyclYzeERxZktRIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiZnFpQnFYTFBqMGVRYTgyUy1JWUZBQSIsInZlciI6IjIuMCJ9.pj4N-w_3Us9DrBLfpCt
--------------------------------------------------------------------------------
/Day29-OneDrive/FileUploadSample/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.ApplicationModel;
7 | using Windows.ApplicationModel.Activation;
8 | using Windows.Foundation;
9 | using Windows.Foundation.Collections;
10 | using Windows.UI.Xaml;
11 | using Windows.UI.Xaml.Controls;
12 | using Windows.UI.Xaml.Controls.Primitives;
13 | using Windows.UI.Xaml.Data;
14 | using Windows.UI.Xaml.Input;
15 | using Windows.UI.Xaml.Media;
16 | using Windows.UI.Xaml.Navigation;
17 |
18 | namespace FileUploadSample
19 | {
20 | ///
21 | /// Provides application-specific behavior to supplement the default Application class.
22 | ///
23 | sealed partial class App : Application
24 | {
25 | ///
26 | /// Initializes the singleton application object. This is the first line of authored code
27 | /// executed, and as such is the logical equivalent of main() or WinMain().
28 | ///
29 | public App()
30 | {
31 | this.InitializeComponent();
32 | this.Suspending += OnSuspending;
33 | }
34 |
35 | ///
36 | /// Invoked when the application is launched normally by the end user. Other entry points
37 | /// will be used such as when the application is launched to open a specific file.
38 | ///
39 | /// Details about the launch request and process.
40 | protected override void OnLaunched(LaunchActivatedEventArgs e)
41 | {
42 | Frame rootFrame = Window.Current.Content as Frame;
43 |
44 | // Do not repeat app initialization when the Window already has content,
45 | // just ensure that the window is active
46 | if (rootFrame == null)
47 | {
48 | // Create a Frame to act as the navigation context and navigate to the first page
49 | rootFrame = new Frame();
50 |
51 | rootFrame.NavigationFailed += OnNavigationFailed;
52 |
53 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
54 | {
55 | //TODO: Load state from previously suspended application
56 | }
57 |
58 | // Place the frame in the current Window
59 | Window.Current.Content = rootFrame;
60 | }
61 |
62 | if (e.PrelaunchActivated == false)
63 | {
64 | if (rootFrame.Content == null)
65 | {
66 | // When the navigation stack isn't restored navigate to the first page,
67 | // configuring the new page by passing required information as a navigation
68 | // parameter
69 | rootFrame.Navigate(typeof(MainPage), e.Arguments);
70 | }
71 | // Ensure the current window is active
72 | Window.Current.Activate();
73 | }
74 | }
75 |
76 | ///
77 | /// Invoked when Navigation to a certain page fails
78 | ///
79 | /// The Frame which failed navigation
80 | /// Details about the navigation failure
81 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
82 | {
83 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
84 | }
85 |
86 | ///
87 | /// Invoked when application execution is being suspended. Application state is saved
88 | /// without knowing whether the application will be terminated or resumed with the contents
89 | /// of memory still intact.
90 | ///
91 | /// The source of the suspend request.
92 | /// Details about the suspend request.
93 | private void OnSuspending(object sender, SuspendingEventArgs e)
94 | {
95 | var deferral = e.SuspendingOperation.GetDeferral();
96 | //TODO: Save application state and stop any background activity
97 | deferral.Complete();
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015/2017 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # Visual Studio 2017 auto generated files
33 | Generated\ Files/
34 |
35 | # MSTest test Results
36 | [Tt]est[Rr]esult*/
37 | [Bb]uild[Ll]og.*
38 |
39 | # NUNIT
40 | *.VisualState.xml
41 | TestResult.xml
42 |
43 | # Build Results of an ATL Project
44 | [Dd]ebugPS/
45 | [Rr]eleasePS/
46 | dlldata.c
47 |
48 | # Benchmark Results
49 | BenchmarkDotNet.Artifacts/
50 |
51 | # .NET Core
52 | project.lock.json
53 | project.fragment.lock.json
54 | artifacts/
55 | **/Properties/launchSettings.json
56 |
57 | # StyleCop
58 | StyleCopReport.xml
59 |
60 | # Files built by Visual Studio
61 | *_i.c
62 | *_p.c
63 | *_i.h
64 | *.ilk
65 | *.meta
66 | *.obj
67 | *.iobj
68 | *.pch
69 | *.pdb
70 | *.ipdb
71 | *.pgc
72 | *.pgd
73 | *.rsp
74 | *.sbr
75 | *.tlb
76 | *.tli
77 | *.tlh
78 | *.tmp
79 | *.tmp_proj
80 | *.log
81 | *.vspscc
82 | *.vssscc
83 | .builds
84 | *.pidb
85 | *.svclog
86 | *.scc
87 |
88 | # Chutzpah Test files
89 | _Chutzpah*
90 |
91 | # Visual C++ cache files
92 | ipch/
93 | *.aps
94 | *.ncb
95 | *.opendb
96 | *.opensdf
97 | *.sdf
98 | *.cachefile
99 | *.VC.db
100 | *.VC.VC.opendb
101 |
102 | # Visual Studio profiler
103 | *.psess
104 | *.vsp
105 | *.vspx
106 | *.sap
107 |
108 | # Visual Studio Trace Files
109 | *.e2e
110 |
111 | # TFS 2012 Local Workspace
112 | $tf/
113 |
114 | # Guidance Automation Toolkit
115 | *.gpState
116 |
117 | # ReSharper is a .NET coding add-in
118 | _ReSharper*/
119 | *.[Rr]e[Ss]harper
120 | *.DotSettings.user
121 |
122 | # JustCode is a .NET coding add-in
123 | .JustCode
124 |
125 | # TeamCity is a build add-in
126 | _TeamCity*
127 |
128 | # DotCover is a Code Coverage Tool
129 | *.dotCover
130 |
131 | # AxoCover is a Code Coverage Tool
132 | .axoCover/*
133 | !.axoCover/settings.json
134 |
135 | # Visual Studio code coverage results
136 | *.coverage
137 | *.coveragexml
138 |
139 | # NCrunch
140 | _NCrunch_*
141 | .*crunch*.local.xml
142 | nCrunchTemp_*
143 |
144 | # MightyMoose
145 | *.mm.*
146 | AutoTest.Net/
147 |
148 | # Web workbench (sass)
149 | .sass-cache/
150 |
151 | # Installshield output folder
152 | [Ee]xpress/
153 |
154 | # DocProject is a documentation generator add-in
155 | DocProject/buildhelp/
156 | DocProject/Help/*.HxT
157 | DocProject/Help/*.HxC
158 | DocProject/Help/*.hhc
159 | DocProject/Help/*.hhk
160 | DocProject/Help/*.hhp
161 | DocProject/Help/Html2
162 | DocProject/Help/html
163 |
164 | # Click-Once directory
165 | publish/
166 |
167 | # Publish Web Output
168 | *.[Pp]ublish.xml
169 | *.azurePubxml
170 | # Note: Comment the next line if you want to checkin your web deploy settings,
171 | # but database connection strings (with potential passwords) will be unencrypted
172 | *.pubxml
173 | *.publishproj
174 |
175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
176 | # checkin your Azure Web App publish settings, but sensitive information contained
177 | # in these scripts will be unencrypted
178 | PublishScripts/
179 |
180 | # NuGet Packages
181 | *.nupkg
182 | # The packages folder can be ignored because of Package Restore
183 | **/[Pp]ackages/*
184 | # except build/, which is used as an MSBuild target.
185 | !**/[Pp]ackages/build/
186 | # Uncomment if necessary however generally it will be regenerated when needed
187 | #!**/[Pp]ackages/repositories.config
188 | # NuGet v3's project.json files produces more ignorable files
189 | *.nuget.props
190 | *.nuget.targets
191 |
192 | # Microsoft Azure Build Output
193 | csx/
194 | *.build.csdef
195 |
196 | # Microsoft Azure Emulator
197 | ecf/
198 | rcf/
199 |
200 | # Windows Store app package directories and files
201 | AppPackages/
202 | BundleArtifacts/
203 | Package.StoreAssociation.xml
204 | _pkginfo.txt
205 | *.appx
206 |
207 | # Visual Studio cache files
208 | # files ending in .cache can be ignored
209 | *.[Cc]ache
210 | # but keep track of directories ending in .cache
211 | !*.[Cc]ache/
212 |
213 | # Others
214 | ClientBin/
215 | ~$*
216 | *~
217 | *.dbmdl
218 | *.dbproj.schemaview
219 | *.jfm
220 | *.pfx
221 | *.publishsettings
222 | orleans.codegen.cs
223 |
224 | # Including strong name files can present a security risk
225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
226 | #*.snk
227 |
228 | # Since there are multiple workflows, uncomment next line to ignore bower_components
229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
230 | #bower_components/
231 |
232 | # RIA/Silverlight projects
233 | Generated_Code/
234 |
235 | # Backup & report files from converting an old project file
236 | # to a newer Visual Studio version. Backup files are not needed,
237 | # because we have git ;-)
238 | _UpgradeReport_Files/
239 | Backup*/
240 | UpgradeLog*.XML
241 | UpgradeLog*.htm
242 | ServiceFabricBackup/
243 | *.rptproj.bak
244 |
245 | # SQL Server files
246 | *.mdf
247 | *.ldf
248 | *.ndf
249 |
250 | # Business Intelligence projects
251 | *.rdl.data
252 | *.bim.layout
253 | *.bim_*.settings
254 | *.rptproj.rsuser
255 |
256 | # Microsoft Fakes
257 | FakesAssemblies/
258 |
259 | # GhostDoc plugin setting file
260 | *.GhostDoc.xml
261 |
262 | # Node.js Tools for Visual Studio
263 | .ntvs_analysis.dat
264 | node_modules/
265 |
266 | # Visual Studio 6 build log
267 | *.plg
268 |
269 | # Visual Studio 6 workspace options file
270 | *.opt
271 |
272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
273 | *.vbw
274 |
275 | # Visual Studio LightSwitch build output
276 | **/*.HTMLClient/GeneratedArtifacts
277 | **/*.DesktopClient/GeneratedArtifacts
278 | **/*.DesktopClient/ModelManifest.xml
279 | **/*.Server/GeneratedArtifacts
280 | **/*.Server/ModelManifest.xml
281 | _Pvt_Extensions
282 |
283 | # Paket dependency manager
284 | .paket/paket.exe
285 | paket-files/
286 |
287 | # FAKE - F# Make
288 | .fake/
289 |
290 | # JetBrains Rider
291 | .idea/
292 | *.sln.iml
293 |
294 | # CodeRush
295 | .cr/
296 |
297 | # Python Tools for Visual Studio (PTVS)
298 | __pycache__/
299 | *.pyc
300 |
301 | # Cake - Uncomment if you are using it
302 | # tools/**
303 | # !tools/packages.config
304 |
305 | # Tabs Studio
306 | *.tss
307 |
308 | # Telerik's JustMock configuration file
309 | *.jmconfig
310 |
311 | # BizTalk build output
312 | *.btp.cs
313 | *.btm.cs
314 | *.odx.cs
315 | *.xsd.cs
316 |
317 | # OpenCover UI analysis results
318 | OpenCover/
319 |
320 | # Azure Stream Analytics local run output
321 | ASALocalRun/
322 |
323 | # MSBuild Binary and Structured Log
324 | *.binlog
325 |
326 | # NVidia Nsight GPU debugger configuration file
327 | *.nvuser
328 |
329 | # MFractors (Xamarin productivity tool) working folder
330 | .mfractor/
331 |
--------------------------------------------------------------------------------
/Day29-OneDrive/FileUploadSample/FileUploadSample.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x86
7 | {051BC360-AF62-4600-8AED-32172F4480A3}
8 | AppContainerExe
9 | Properties
10 | FileUploadSample
11 | FileUploadSample
12 | en-US
13 | UAP
14 | 10.0.17134.0
15 | 10.0.15063.0
16 | 14
17 | 512
18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
19 | true
20 | FileUploadSample_TemporaryKey.pfx
21 |
22 |
23 | true
24 | bin\x86\Debug\
25 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
26 | ;2008
27 | full
28 | x86
29 | false
30 | prompt
31 | true
32 |
33 |
34 | bin\x86\Release\
35 | TRACE;NETFX_CORE;WINDOWS_UWP
36 | true
37 | ;2008
38 | pdbonly
39 | x86
40 | false
41 | prompt
42 | true
43 | true
44 |
45 |
46 | true
47 | bin\ARM\Debug\
48 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
49 | ;2008
50 | full
51 | ARM
52 | false
53 | prompt
54 | true
55 |
56 |
57 | bin\ARM\Release\
58 | TRACE;NETFX_CORE;WINDOWS_UWP
59 | true
60 | ;2008
61 | pdbonly
62 | ARM
63 | false
64 | prompt
65 | true
66 | true
67 |
68 |
69 | true
70 | bin\x64\Debug\
71 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
72 | ;2008
73 | full
74 | x64
75 | false
76 | prompt
77 | true
78 |
79 |
80 | bin\x64\Release\
81 | TRACE;NETFX_CORE;WINDOWS_UWP
82 | true
83 | ;2008
84 | pdbonly
85 | x64
86 | false
87 | prompt
88 | true
89 | true
90 |
91 |
92 | PackageReference
93 |
94 |
95 |
96 | App.xaml
97 |
98 |
99 | MainPage.xaml
100 |
101 |
102 |
103 |
104 |
105 | Designer
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 | MSBuild:Compile
122 | Designer
123 |
124 |
125 | MSBuild:Compile
126 | Designer
127 |
128 |
129 |
130 |
131 | 1.12.0
132 |
133 |
134 | 2.5.0-preview
135 |
136 |
137 | 6.1.5
138 |
139 |
140 |
141 | 14.0
142 |
143 |
144 |
151 |
--------------------------------------------------------------------------------
/Day29-OneDrive/FileUploadSample/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Graph;
2 | using Microsoft.Identity.Client;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Net.Http.Headers;
7 | using System.Threading.Tasks;
8 | using Windows.Storage;
9 | using Windows.Storage.Pickers;
10 | using Windows.UI.Xaml;
11 | using Windows.UI.Xaml.Controls;
12 |
13 | // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
14 |
15 | namespace FileUploadSample
16 | {
17 | ///
18 | /// An empty page that can be used on its own or navigated to within a Frame.
19 | ///
20 | public sealed partial class MainPage : Page
21 | {
22 | public MainPage()
23 | {
24 | this.InitializeComponent();
25 | }
26 |
27 | private const string AADClientId = "YOURAPPIDHERE";
28 | private const string GraphAPIEndpointPrefix = "https://graph.microsoft.com/v1.0/";
29 | private string[] AADScopes = new string[] { "files.readwrite.all" };
30 | private PublicClientApplication AADAppContext = null;
31 | private GraphServiceClient graphClient = null;
32 |
33 | private AuthenticationResult userCredentials;
34 |
35 | public AuthenticationResult UserCredentials
36 | {
37 | get { return userCredentials; }
38 | set { userCredentials = value; }
39 | }
40 |
41 | public void InitializeGraph()
42 | {
43 | if (userCredentials != null)
44 | {
45 | graphClient = new GraphServiceClient(
46 | GraphAPIEndpointPrefix,
47 | new DelegateAuthenticationProvider(
48 | async (requestMessage) =>
49 | {
50 | requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", userCredentials.AccessToken);
51 | }
52 | )
53 | );
54 | }
55 | }
56 |
57 |
58 | ///
59 | /// Log the user in to either O365 or OneDrive consumer
60 | ///
61 | /// A task to await on
62 | public async Task SignInUser()
63 | {
64 | string status = "Unknown";
65 |
66 | // Instantiate the app with AAD
67 | AADAppContext = new PublicClientApplication(AADClientId);
68 |
69 | // Get the token, if it fails print out an error message, if it succeeds print out the logged in User's identity as a verification
70 | try
71 | {
72 | UserCredentials = await AADAppContext.AcquireTokenAsync(AADScopes);
73 | if (UserCredentials != null)
74 | {
75 | status = "Signed in as " + UserCredentials.Account.Username;
76 | InitializeGraph();
77 | }
78 | }
79 | catch (MsalServiceException serviceEx)
80 | {
81 | status = $"Could not sign in, error code: " + serviceEx.ErrorCode;
82 | }
83 | catch (Exception ex)
84 | {
85 | status = $"Error Acquiring Token: {ex}";
86 | }
87 |
88 | return (status);
89 | }
90 |
91 | ///
92 | /// Take a file less than 4MB and upload it to the service
93 | ///
94 | /// The file that we want to upload
95 | /// Should we upload to SharePoint or OneDrive?
96 | public async Task UploadSmallFile(StorageFile fileToUpload)
97 | {
98 | Stream fileStream = (await fileToUpload.OpenReadAsync()).AsStreamForRead();
99 | DriveItem uploadedFile = null;
100 |
101 | // Do we want OneDrive for Business/Consumer or do we want a SharePoint Site?
102 | if (uploadToSharePointCheckBox.IsChecked == true)
103 | {
104 | uploadedFile = await graphClient.Sites["root"].Drive.Root.ItemWithPath(fileToUpload.Name).Content.Request().PutAsync(fileStream);
105 | }
106 | else
107 | {
108 | uploadedFile = await graphClient.Me.Drive.Root.ItemWithPath(fileToUpload.Name).Content.Request().PutAsync(fileStream);
109 | }
110 |
111 | return (uploadedFile);
112 | }
113 |
114 | ///
115 | /// Take a file greater than 4MB and upload it to the service
116 | ///
117 | /// The file that we want to upload
118 | /// Should we upload to SharePoint or OneDrive?
119 | public async Task UploadLargeFile(StorageFile fileToUpload)
120 | {
121 | Stream fileStream = (await fileToUpload.OpenReadAsync()).AsStreamForRead();
122 | DriveItem uploadedFile = null;
123 | UploadSession uploadSession = null;
124 |
125 | // Do we want OneDrive for Business/Consumer or do we want a SharePoint Site?
126 | if (uploadToSharePointCheckBox.IsChecked == true)
127 | {
128 | uploadSession = await graphClient.Sites["root"].Drive.Root.ItemWithPath(fileToUpload.Name).CreateUploadSession().Request().PostAsync();
129 | }
130 | else
131 | {
132 | uploadSession = await graphClient.Me.Drive.Root.ItemWithPath(fileToUpload.Name).CreateUploadSession().Request().PostAsync();
133 | }
134 |
135 | if(uploadSession != null)
136 | {
137 | // Chunk size must be divisible by 320KiB, our chunk size will be slightly more than 1MB
138 | int maxSizeChunk = (320 * 1024) * 4;
139 | ChunkedUploadProvider uploadProvider = new ChunkedUploadProvider(uploadSession, graphClient, fileStream, maxSizeChunk);
140 | var chunkRequests = uploadProvider.GetUploadChunkRequests();
141 | var exceptions = new List();
142 | var readBuffer = new byte[maxSizeChunk];
143 | foreach (var request in chunkRequests)
144 | {
145 | var result = await uploadProvider.GetChunkRequestResponseAsync(request, readBuffer, exceptions);
146 |
147 | if(result.UploadSucceeded)
148 | {
149 | uploadedFile = result.ItemResponse;
150 | }
151 | }
152 | }
153 |
154 | return (uploadedFile);
155 | }
156 |
157 | private async Task PickFile()
158 | {
159 | var picker = new FileOpenPicker();
160 | picker.ViewMode = PickerViewMode.Thumbnail;
161 | picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
162 | picker.FileTypeFilter.Add(".jpg");
163 | picker.FileTypeFilter.Add(".jpeg");
164 | picker.FileTypeFilter.Add(".png");
165 |
166 | StorageFile pickedFile = await picker.PickSingleFileAsync();
167 | return (pickedFile);
168 | }
169 |
170 | private async Task UploadFile(object whichButton)
171 | {
172 | if (this.UserCredentials == null)
173 | {
174 | await SignInUser();
175 | }
176 |
177 | StorageFile fileToUpload = await PickFile();
178 | DriveItem uploadedFile = null;
179 |
180 | if (whichButton == this.uploadSmallFileButton)
181 | {
182 | uploadedFile = await UploadSmallFile(fileToUpload);
183 | }
184 | else
185 | {
186 | uploadedFile = await UploadLargeFile(fileToUpload);
187 | }
188 |
189 | if (uploadedFile != null)
190 | {
191 | this.statusTextBlock.Text = "Uploaded file: " + uploadedFile.Name;
192 | }
193 | else
194 | {
195 | this.statusTextBlock.Text = "Upload failed";
196 | }
197 | }
198 |
199 | private async void uploadSmallFileButton_Click(object sender, RoutedEventArgs e)
200 | {
201 | await UploadFile(sender);
202 | }
203 |
204 | private async void uploadLargeFileButton_Click(object sender, RoutedEventArgs e)
205 | {
206 | await UploadFile(sender);
207 | }
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/Day29-OneDrive/README.md:
--------------------------------------------------------------------------------
1 | # Day 29 - Upload files to OneDrive and SharePoint
2 |
3 | - [Prerequisites](#prerequisites)
4 | - [Step 1: Update the App Registration permissions](#step-1-update-the-app-rgistration-permissions)
5 | - [Step 2: Extend the app to yyy](#step-2-extend-the-app-to-yyy)
6 | - [Create the MyHelper class](#create-the-myhelper-class)
7 | - [Extend program to yyy](#extend-program-to-yyy)
8 |
9 | ## Prerequisites
10 |
11 | To complete this sample you need the following:
12 |
13 | - Complete the [Base Console Application Setup](../base-console-app/)
14 | - [Visual Studio Community](https://visualstudio.microsoft.com/vs/community/) installed on your development machine. If you do not have Visual Studio Community edition (or another version of Visual Studio 2017), visit the previous link for download options.
15 | - Either a personal Microsoft account with a mailbox on Outlook.com, or a Microsoft work or school account.
16 |
17 | If you don't have a Microsoft account, there are a couple of options to get a free account:
18 |
19 | - You can [sign up for a new personal Microsoft account](https://signup.live.com/signup?wa=wsignin1.0&rpsnv=12&ct=1454618383&rver=6.4.6456.0&wp=MBI_SSL_SHARED&wreply=https://mail.live.com/default.aspx&id=64855&cbcxt=mai&bk=1454618383&uiflavor=web&uaid=b213a65b4fdc484382b6622b3ecaa547&mkt=E-US&lc=1033&lic=1).
20 | - You can [sign up for the Office 365 Developer Program](https://developer.microsoft.com/office/dev-program) to get a free Office 365 subscription.
21 |
22 | ## Step 1: Prepare a new client application
23 |
24 | 1. Create a new blank Universal Windows application
25 | 1. Add the following NuGet packages
26 | 1. Microsoft.Graph
27 | 1. Microsoft.Identity.Client
28 | 1. Add the following using declarations to your MainPage.xaml.cs file:
29 |
30 | ```cs
31 | using Microsoft.Graph;
32 | using Microsoft.Identity.Client;
33 | using System.Threading.Tasks;
34 | using System.Net.Http.Headers;
35 | using Windows.Storage;
36 | using Windows.Storage.Pickers;
37 | ```
38 |
39 | 1. Below the MainPage constructor add the following code:
40 |
41 | ```cs
42 | private const string AADClientId = "YOURAPPIDHERE";
43 | private const string GraphAPIEndpointPrefix = "https://graph.microsoft.com/v1.0/";
44 | private string[] AADScopes = new string[] { "files.readwrite.all" };
45 | private PublicClientApplication AADAppContext = null;
46 | private GraphServiceClient graphClient = null;
47 | private AuthenticationResult userCredentials;
48 | public AuthenticationResult UserCredentials
49 | {
50 | get { return userCredentials; }
51 | set { userCredentials = value; }
52 | }
53 | public void InitializeGraph()
54 | {
55 | if (userCredentials != null)
56 | {
57 | graphClient = new GraphServiceClient(
58 | GraphAPIEndpointPrefix,
59 | new DelegateAuthenticationProvider(
60 | async (requestMessage) =>
61 | {
62 | requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", userCredentials.AccessToken);
63 | }
64 | )
65 | );
66 | }
67 | }
68 |
69 | ///
70 | /// Log the user in to either Office 365 or OneDrive consumer
71 | ///
72 | /// A task to await on
73 | public async Task SignInUser()
74 | {
75 | string status = "Unknown";
76 |
77 | // Instantiate the app with AAD
78 | AADAppContext = new PublicClientApplication(AADClientId);
79 |
80 | try
81 | {
82 | UserCredentials = await AADAppContext.AcquireTokenAsync(AADScopes);
83 | if (UserCredentials != null)
84 | {
85 | status = "Signed in as " + UserCredentials.Account.Username;
86 | InitializeGraph();
87 | }
88 | }
89 | catch (MsalServiceException serviceEx)
90 | {
91 | status = $"Could not sign in, error code: " + serviceEx.ErrorCode;
92 | }
93 | catch (Exception ex)
94 | {
95 | status = $"Error Acquiring Token: {ex}";
96 | }
97 |
98 | return (status);
99 | }
100 | ```
101 | 1. Replace YOURAPPIDHERE with the id of your application created in the basic console application example
102 |
103 | ## Step 2: Update the App Registration permissions
104 |
105 | As this exercise requires new permissions the App Registration needs to be updated to include the **Files.ReadWrite.All** permission using the new Azure AD Portal App Registrations UI (in preview as of the time of publish Nov 2018).
106 |
107 | 1. Open a browser and navigate to the [Preview App Registration](https://aka.ms/AppRegistrationsPreview) within Azure AD Portal. Login using a **personal account** (aka: Microsoft Account) or **Work or School Account** with permissions to create app registrations.
108 |
109 | > **Note:** If you do not have permissions to create app registrations contact your Azure AD domain administrators.
110 |
111 | 1. Click on the **.NET Core Graph Tutorial** item in the list
112 |
113 | > **Note:** If you used a different name while completing the [Base Console Application Setup](../base-console-app/) select that instead.
114 |
115 | 1. Click **API permissions** from the current blade content.
116 |
117 | 1. Click **Add a permission** from the current blade content.
118 | 1. On the **Request API permissions** flyout select **Microsoft Graph**.
119 |
120 | 
121 |
122 | 1. Select **Delegated permissions**.
123 | 1. In the "Select permissions" search box type "Files.Read".
124 | 1. Select **Files.ReadWrite.All** from the filtered list.
125 |
126 | 
127 |
128 | 1. Click **Add permissions** at the bottom of flyout.
129 |
130 | ## Step 3: Add upload functionality
131 |
132 | In this step you will add methods to upload small and large files using two different techniques.
133 |
134 | ### Create the upload methods
135 |
136 | 1. Add the following code to your MainPage class for small file uploads:
137 |
138 | ```cs
139 | ///
140 | /// Take a file and upload it to the service
141 | ///
142 | /// The file that we want to upload
143 | /// Should we upload to SharePoint or OneDrive?
144 | public async Task UploadSmallFile(StorageFile fileToUpload, bool uploadToSharePoint)
145 | {
146 | Stream fileStream = (await fileToUpload.OpenReadAsync()).AsStreamForRead();
147 | DriveItem uploadedFile = null;
148 |
149 | // Do we want OneDrive for Business/Consumer or do we want a SharePoint Site?
150 | if (uploadToSharePoint)
151 | {
152 | uploadedFile = await graphClient.Sites["root"].Drive.Root.ItemWithPath(fileToUpload.Name).Content.Request().PutAsync(fileStream);
153 | }
154 | else
155 | {
156 | uploadedFile = await graphClient.Me.Drive.Root.ItemWithPath(fileToUpload.Name).Content.Request().PutAsync(fileStream);
157 | }
158 | }
159 | ```
160 |
161 | 1. Add the following code to your MainPage class for large file uploads:
162 |
163 | ```cs
164 | ///
165 | /// Take a file greater than 4MB and upload it to the service
166 | ///
167 | /// The file that we want to upload
168 | /// Should we upload to SharePoint or OneDrive?
169 | public async Task UploadLargeFile(StorageFile fileToUpload, bool uploadToSharePoint)
170 | {
171 | Stream fileStream = (await fileToUpload.OpenReadAsync()).AsStreamForRead();
172 | DriveItem uploadedFile = null;
173 | UploadSession uploadSession = null;
174 |
175 | // Do we want OneDrive for Business/Consumer or do we want a SharePoint Site?
176 | if (uploadToSharePoint)
177 | {
178 | uploadSession = await graphClient.Sites["root"].Drive.Root.ItemWithPath(fileToUpload.Name).CreateUploadSession().Request().PostAsync();
179 | }
180 | else
181 | {
182 | uploadSession = await graphClient.Me.Drive.Root.ItemWithPath(fileToUpload.Name).CreateUploadSession().Request().PostAsync();
183 | }
184 |
185 | if(uploadSession != null)
186 | {
187 | // Chunk size must be divisible by 320KiB, our chunk size will be slightly more than 1MB
188 | int maxSizeChunk = (320 * 1024) * 4;
189 | ChunkedUploadProvider uploadProvider = new ChunkedUploadProvider(uploadSession, graphClient, fileStream, maxSizeChunk);
190 | var chunkRequests = uploadProvider.GetUploadChunkRequests();
191 | var exceptions = new List();
192 | var readBuffer = new byte[maxSizeChunk];
193 | foreach (var request in chunkRequests)
194 | {
195 | var result = await uploadProvider.GetChunkRequestResponseAsync(request, readBuffer, exceptions);
196 |
197 | if(result.UploadSucceeded)
198 | {
199 | uploadedFile = result.ItemResponse;
200 | }
201 | }
202 | }
203 |
204 | return (uploadedFile);
205 | }
206 | ```
207 |
208 | ### Add UX elements
209 |
210 | 1. Replace the default Grid element in your MainPage.xaml file with the following:
211 |
212 | ```xaml
213 |
214 |
215 | Upload to SharePoint?
216 |
217 |
218 |
219 |
220 |
221 | ```
222 | 1. In the code behind file (MainPage.xaml.cs) add the following code to add button handlers and connect the file picker:
223 |
224 | ```cs
225 | private async Task PickFile()
226 | {
227 | var picker = new FileOpenPicker();
228 | picker.ViewMode = PickerViewMode.Thumbnail;
229 | picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
230 | picker.FileTypeFilter.Add(".jpg");
231 | picker.FileTypeFilter.Add(".jpeg");
232 | picker.FileTypeFilter.Add(".png");
233 |
234 | StorageFile pickedFile = await picker.PickSingleFileAsync();
235 | return (pickedFile);
236 | }
237 |
238 | private async Task UploadFile(object whichButton)
239 | {
240 | if (this.UserCredentials == null)
241 | {
242 | await SignInUser();
243 | }
244 |
245 | StorageFile fileToUpload = await PickFile();
246 | DriveItem uploadedFile = null;
247 |
248 | if (whichButton == this.uploadSmallFileButton)
249 | {
250 | uploadedFile = await UploadSmallFile(fileToUpload);
251 | }
252 | else
253 | {
254 | uploadedFile = await UploadLargeFile(fileToUpload);
255 | }
256 |
257 | if (uploadedFile != null)
258 | {
259 | this.statusTextBlock.Text = "Uploaded file: " + uploadedFile.Name;
260 | }
261 | else
262 | {
263 | this.statusTextBlock.Text = "Upload failed";
264 | }
265 | }
266 |
267 | private async void uploadSmallFileButton_Click(object sender, RoutedEventArgs e)
268 | {
269 | await UploadFile(sender);
270 | }
271 |
272 | private async void uploadLargeFileButton_Click(object sender, RoutedEventArgs e)
273 | {
274 | await UploadFile(sender);
275 | }
276 |
277 | ```
278 |
279 | The application is now able to upload small or large files to either OneDrive or SharePoint.
--------------------------------------------------------------------------------