How to retrieve username, email and image with OneDrive/Graph APIs? - c#

I'm working on a UWP app and I was thinking about moving from the old LiveSDK (which is discontinued and was last updated around 2015) to the new OneDriveSDK (the Graph APIs), specifically using the UWP Community Toolkit Services package and its APIs.
The library seems pretty easy to use as far as login and files/folders management go, but so far I haven't been able to find a way to retrieve the user full name, the user email and the profile picture.
Here's the code I'm currently using to do so, using LiveSDK (code simplified here):
public static async Task<(String username, String email)> GetUserProfileNameAndEmailAsync(LiveConnectSession session)
{
LiveConnectClient connect = new LiveConnectClient(session);
LiveOperationResult operationResult = await connect.GetAsync("me");
IDictionary<String, object> results = operationResult.Result;
String username = results["name"] as String;
if (!(results["emails"] is IDictionary<string, object> emails)) return default;
String email = emails["preferred"] as String ?? emails["account"] as String;
return (username, email);
}
public static async Task<ImageSource> GetUserProfileImageAsync([NotNull] LiveConnectSession session)
{
LiveConnectClient liveClient = new LiveConnectClient(session);
LiveOperationResult operationResult = await liveClient.GetAsync("me/picture");
String url = operationResult.Result?["location"] as String;
// The URL points to the raw image data for the user profile picture, just download it
return default;
}
I've looked at the guide here and I see there seems to be a replacement for all of the above, but I haven't been able to integrate that with the UWP Toolkit service. For example, to retrieve the user info, here's what I've tried:
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "https://graph.microsoft.com/v1.0/me/");
await OneDriveService.Instance.Provider.AuthenticationProvider.AuthenticateRequestAsync(request);
using (HttpResponseMessage response = await OneDriveService.Instance.Provider.HttpProvider.SendAsync(request))
{
String content = await response.Content.ReadAsStringAsync();
}
But this fails with an exception at the SendAsync call.
NOTE: I know there are the Graph APIs too in the UWP Toolkit, with ready-to-use methods to retrieve the user info and profile picture, but apparently you need an office 365 subscription to use those APIs (both as a dev, and probably as a user too), so I guess that's not what I'm looking for here, since I've always been able to retrieve these info using a normal OneDrive client.
Is there a way to do this on UWP, either through some method within the UWP Toolkit, or with some other solution?
Thanks!
EDIT: I've reused the code from the sample app, registered my app to get a clientID and made a quick test, but it's not working as expected and I'm getting this exception:
Fixed, see below
EDIT #2: According to this question, I had to switch to https://graph.microsoft.com/beta to get the profile picture, as the 1.0 version of the APIs doesn't support it for normal MS accounts right now. All things considered, it seems to be working just fine now 👍

I followed the MSDN document to register my app for Microsoft Graph. After that, I will get an application ID(in API, it's called as clientId).
Then, I used the Microsoft Graph Connect Sample for UWP to login in with my general MS account. It worked well. I could get the username, email etc.
Please note that if you want to run this sample successfully, you would need to use the application ID to initialize the PublicClientApplication object in AuthenticationHelper.cs.
public static PublicClientApplication IdentityClientApp = new PublicClientApplication("your client id");

Related

Instasharp in a Console Application

I have a .net console application that I want to use to pull Instagram posts via the Instasharp wrapper using a hashtag search.
I use C# .net web forms extensively and am not very familiar with MVC nor how to use the await keyword. The code sample below seems to run, but never provides any output.
This line:
var tagInfo = await tagApi.Get("soccer");
Returns me to the calling method with no indication of retrieved data.
Can anyone provide insights as to what I am doing wrong here?
public static async void GetInstagram(String tag, InstagramConfig config)
{
var instagramPosts = await LoadInstagramPosts(tag, config);
dynamic dyn = JsonConvert.DeserializeObject(instagramPosts.ToString());
foreach (var data in dyn.data)
{
Console.WriteLine("{0} - {1}", data.filter, data.images.standard_resolution.url);
}
}
public static async Task<TagResponse> LoadInstagramPosts(String hashTagTerm, InstagramConfig config)
{
var tagApi = new InstaSharp.Endpoints.Tags(config);
var tagInfo = await tagApi.Get("soccer");
}
EDITED code after first comment which solved my initial problem.
I feel like I'm close but something is still missing.
See specific questions below...
I've based the code on the documentation from InstaSharp GitHub (https://github.com/InstaSharp/InstaSharp). GitHubs example is based on an MVC application, mine is not an MVC project, but a console application.
I feel like I am very close and maybe others will benefit from helping me solve this.
My specific questions...
1) Not sure where the 'code' parameter in the OAuth method originate??
2) How to perform the needed call backs with Instagram??
var config = new InstaSharp.InstagramConfig(location.InstagramClientId, location.InstagramClientSecret, "http://localhost");
string instagramLoginLink = InstagramLogin(config);
GetInstagram("soccer", config, instagramLoginLink);
public static async void GetInstagram(String tag, InstagramConfig config, string code)
{
OAuthResponse oAuthResponse = await OAuth(code, config);
var instagramPosts = await LoadInstagramPosts(tag, config, oAuthResponse);
if(instagramPosts.Data != null)
{
dynamic dyn = JsonConvert.DeserializeObject(instagramPosts.Data.ToString());
foreach (var data in dyn.data)
{
Console.WriteLine("{0} - {1}", data.filter, data.images.standard_resolution.url);
}
}
}
public static string InstagramLogin(InstagramConfig config)
{
var scopes = new List<OAuth.Scope>();
scopes.Add(InstaSharp.OAuth.Scope.Likes);
scopes.Add(InstaSharp.OAuth.Scope.Comments);
string link = InstaSharp.OAuth.AuthLink(config.OAuthUri + "authorize", config.ClientId, config.RedirectUri, scopes, InstaSharp.OAuth.ResponseType.Code);
return link;
}
public static async Task<OAuthResponse> OAuth(string code, InstagramConfig config)
{
// add this code to the auth object
var auth = new OAuth(config);
// now we have to call back to instagram and include the code they gave us
// along with our client secret
return await auth.RequestToken(code);
}
public static async Task<TagResponse> LoadInstagramPosts(String hashTagTerm, InstagramConfig config, OAuthResponse OAuth)
{
var tagApi = new InstaSharp.Endpoints.Tags(config, OAuth);
return await tagApi.Get("soccer");
}
I'm a bit late to the show, yet probably my answer will help someone who find this question when googling, someone like me.
The main problem with your approach is that Instagram is using OAuth authentication. I suggest you to google on OAuth to understand the principles, but I will try to explain the practical points of it below.
OAuth approach means that the result of the InstagramLogin method in the snippet above is not the code. It's the link where you need to send you user (yes, using a browser or a web-view) so that they can sign into their Instagram account and then authorize your application to access their data (so-called user consent screen).
In the end, after user consent, Instagram will redirect browser to the URL of your choice (it should be previously added in the list of allowed redirect urls in Instagram API -> Manage Clients (top-right corner) -> Create/Select client to Manage -> Security tab)
You can try set a breakpoint and copy the value of instagramLoginLink into your browser's address box. You will be able to see the whole flow of authentication and consent - and finally the redirect url that will most probably produce 404 in your browser.
This final link will contain the code in a get parameter. It's the so-called grant code that allows you to get an access token. This code is to be extracted from url and then used in your call to OAuth.RequestToken).
PS: Yes, everything I say above means that you need either a web app running that will redirect user to Instagram or a client-side app that will show the user a web view and somehow handle the moment when Instagram sends the user back to your redirect url - to grab the code and proceed.

How to read inbox Outlook.com mails from WinForms?

SCENARIO
I would like to develop a very simple app written in C# or Vb.Net using WinForms tech., that will help me to automate a simple task that consist in access to my Outlook.com account to read my emails received from Youtube then extract the video urls.
PROBLEM
My networking related knowledges are not good, I'm stuck at the most important point trying to find the easiest way to acchieve that task (I mean official Microsoft APIs for .Net or 3rd party APIs or other way to be able do this), trying to apply the required OAuth2 autorizathion to access the email account.
I know that the following code is not focused in the right direction because the lack of authorization, but I don't know how to implement that neither how to read the emails, so this is what I tried:
string url = "https://outlook.office.com/api/v2.0/me/messages";
string result = "";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "GET";
try {
using (WebClient wc = new WebClient()) {
wc.Encoding = Encoding.UTF8;
result = wc.DownloadString(url);
}
} catch (Exception ex) {
MessageBox.Show(ex.Message);
}
QUESTION
How I could access to my Outlook.com account to read the title and the content of the inbox emails that I have?. And, additionally but optionally to respond (only if possible and is not too much ask), how I could delete a email?.
Note that this question reffers to Outlook.com online service, not to Outlook's desktop client neither the usage of their COM libraries or Office365.
ANSWER REQUISITES
I know that I'm no one to ask for help and put some requisites, all kind of help is appreciated for me, but this time I need to put a special requisite, because my head got crazy trying to understand, use and adapt OAuth2 solutions that were made from scratch, it generates very long codes that I don't understand at all, it's too much for me.
For that reason, I will accept an answer in this question only if the provided solution is based in the usage of a 3rd pary library that will facilitate all this task because it will serve as a complete abstraction of the OAuth2 implementation, like RestSharp, CodeScales or DotNetOpenAuth, or whichever other (free)lib that will handle the required things for me instead of the need to develop the OAuth2 algorithms by myself from scratch.
RESEARCH
My investigation started reading this Microsoft's Outlook dev. page, following to this Mail API reference, this REST API documentation, this Outlook.com API, this kind of getting started article, and ending in this fully illustrative example using ASP.Net.
What I have taken in clear from the Microsoft articles is just... nothing of nothing, I've registered the app and created the client id and the secret, but Microsoft does not provide any example for Winforms so I tried to translate their official ASP.NET example to WinForms without success.
After that waste of time, I found this OAuth documentation page which provides some libraries for .NET that I imagine will facilitate the OAuth2 authorization, then I discovered the DotNetOpenAuth library which seems very complete, and also I found this code sample for Outlook using DotNetOpenAuth but again it is for ASP.NET, and also these generic and official DotNetOpenAuth's code samples but I can't find any thing that could help me for what I want to do.
The general idea is to follow the tutorial here: Get Started with Mail, Calendar, and Contacts REST APIs but I will try to simplify it and demonstrate it with a Winforms sample.
Register App
First things first, you need to create and register an application to the Application Registration Portal (you should only have to do this once for a given application of course):
create an app
generate a new password
add a platform, and choose mobile ("mobile" here means "any device", or "not for a browser"...)
don't forget to click on save!
Authentication
Now, in your "any device" code (including winforms), you'll need to authenticate. The simplest way is to use ADAL ("Active Directory Authentication Library"). The source is available here https://github.com/AzureAD/azure-activedirectory-library-for-dotnet and the binary is available as a nuget.
Unfortunately, the latest version which you can get on nuget today named Microsoft.IdentityModel.Clients.ActiveDirectory does not work for me (It had a bug I've reported here https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/issues/412 that's already been fixed, but now the server complains about some app vs server incompatibility).
So you must use the old "Experimental" one (keep that in mind as someday in the future, we'll have to switch): Microsoft.Experimental.IdentityModel.Clients.ActiveDirectory
You want to make sure you use the proper scopes when you do acquire an auth token. Scopes are defined here: Outlook mail, calendar, and contacts scopes and represent an area of permission. Without specifying scope, you can do nothing else but authenticate.
So, if you want to read mails, use the "https://outlook.office.com/mail.read" scope.
When you try the application, after the authentication dialog, it should display to the user the consent screen (here we see we asked for mail scope: "Read Your Mail"):
Office/Outlook/OData API
Once authentication works, you can use the REST api directly which is not that easy, or be lazy and use another package: Microsoft.Office365.OutlookServices-V2.0 that will do all underlying REST/OData magic for you. The good news is this API is quite complete so it should allow you to do other things like, message creation, delete, etc.
There is an important remark for the outlook.com case: not all accounts are enabled for this whole REST API (check the "REST API availability" chapter here: Outlook Mail), so you might want to create a new one for testing.
Here is the winforms code for a sample app that will query 10 messages and add them to a listbox.
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Experimental.IdentityModel.Clients.ActiveDirectory;
using Microsoft.Office365.OutlookServices;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private const string authority = "https://login.microsoftonline.com/common";
private const string clientId = "blablabl-abla-blab-abla-blablablab"; // TODO: put your application id here
private const string redirectUri = "urn:ietf:wg:oauth:2.0:oob"; // put your redirect uri here (should be the same)
// we cache the token for the duration of this form
// you could/should use the FileCache class provided in the sample here https://dev.outlook.com/restapi/tutorial/dotnet
private TokenCache _cache = new TokenCache();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// since all packages force async,
// we have to avoid threading issues
BeginInvoke((Action)(() => GetMessages()));
}
private async void GetMessages()
{
// use the Microsoft.Experimental.IdentityModel.Clients.ActiveDirectory nuget package for auth
var authContext = new AuthenticationContext(authority, _cache);
var result = await authContext.AcquireTokenAsync(
new[] { "https://outlook.office.com/mail.read" },
null,
clientId,
new Uri(redirectUri),
new PlatformParameters(PromptBehavior.Always, this));
// use the Microsoft.Office365.OutlookServices-V2.0 nuget package from now on
var client = new OutlookServicesClient(new Uri("https://outlook.office.com/api/v2.0"), () => Task.FromResult(result.Token));
var messages = await client.Me.Messages
.Take(10) // get only 10 messages
.ExecuteAsync();
// fill some list box
// (beware, some messages have a null subject)
foreach (var msg in messages.CurrentPage)
{
listBox1.Items.Add(msg.Subject);
}
}
}
}
I just would like to share the (almost)final solution, I extended a little bit the solution provided by #Simon Mourier, to iterate all the emails of a specific folder and, if the email is from Youtube, scrap the urls inside, then recytle the email.
When to apply this?, well, just adapt it for any case on which you need to parse the emails, my case is very specific, I have around 500 channel subscriptions so I accumulate around 200 emais from Youtube in a month, most of the emails are from music channels that I just read the email to copy the url to download it with JDownloader, so this is usefull as a savetimer because it will do all the task for me.
Private Const Authority As String = "https://login.microsoftonline.com/common"
Private Const ClientId As String = "OUR API ID"
' Put your redirect uri here (should be the same).
Private Const RedirectUri As String = "urn:ietf:wg:oauth:2.0:oob"
' We cache the token for the duration of this Form.
' You could/should use the FileCache class provided in the sample here:
' https://dev.outlook.com/restapi/tutorial/dotnet
Private cache As New TokenCache()
Private Sub Form1_Shown() Handles MyBase.Shown
' Since all packages force async, we have to avoid threading issues.
Me.BeginInvoke(Sub() GetMessages())
End Sub
Private Async Sub GetMessages()
' Use the 'Microsoft.Experimental.IdentityModel.Clients.ActiveDirectory' Nuget package for auth.
Dim authContext As New AuthenticationContext(Authority, cache)
Dim result As AuthenticationResult =
Await authContext.AcquireTokenAsync({"https://outlook.office.com/mail.readwrite"},
Nothing, ClientId, New Uri(RedirectUri),
New PlatformParameters(PromptBehavior.Auto, Me))
' Use the 'Microsoft.Office365.OutlookServices-V2.0' Nuget package from now on.
Dim client As New OutlookServicesClient(New Uri("https://outlook.office.com/api/v2.0"),
Function() Task.FromResult(result.Token))
' I have a rule set to automatically move all emails received from Youtube to a folder with name "Youtube".
Dim folder As IMailFolder =
Await client.[Me].MailFolders.Where(Function(f As IMailFolder) f.DisplayName = "Youtube").ExecuteSingleAsync()
Dim messages As IPagedCollection(Of IMessage) =
Await client.[Me].MailFolders.GetById(folder.Id).Messages.ExecuteAsync()
Do While True
Me.ParseYoutubeMessages(messages.CurrentPage)
If messages.MorePagesAvailable Then
messages = Await messages.GetNextPageAsync
Else
Exit Do
End If
Loop
End Sub
Private Async Sub ParseYoutubeMessages(ByVal messageList As IReadOnlyList(Of IMessage))
Dim urlRegex As New Regex("""http://www.youtube.com/.+watch.+uploademail""", RegexOptions.IgnoreCase)
For Each msg As IMessage In messageList
If (msg.From.EmailAddress.Name.Equals("YouTube", StringComparison.OrdinalIgnoreCase)) Then
Dim body As String = msg.Body.Content
Dim isMatch As Boolean = urlRegex.IsMatch(body)
If Not (isMatch) Then
Throw New InvalidOperationException("Youtube url regex doesn't match.")
Else
Dim urlMatches As MatchCollection = urlRegex.Matches(body)
Dim urls As String() =
(From m As Match In urlMatches.Cast(Of Match)
Select Environment.NewLine & m.Value).Distinct().ToArray()
File.AppendAllText("C:\Youtube Urls.txt", String.Join("", urls))
msg.IsRead = True
Await msg.MoveAsync("DeletedItems")
End If
End If
Next msg
End Sub
Updating this for 2018 -- Microsoft Graph API now has control over granting access to objects in the 365 world, including email. See this link for the 4-step overview: https://developer.microsoft.com/en-us/graph/docs/concepts/auth_v2_user

how to use box api in asp.net web application

I am trying to use box api in an asp.net web application.
Based on the search there are two options to access box account;
By downloading the Box.V2 package using below link containing the required dlls and use that in our application
By using Box SDK containing code and reference that inside our application. Using this approach we can debug the Box.V2 code by adding the project to our solution.
Correct me if I am wrong.
So, I am trying to implement the second approach. Can someone help me move forward by specifying the steps to be taken, minimum .net framework requirement, etc.
Good question, GitHub samples does not mention about the Web (Asp.Net).
It's possible and it looks pretty easy to do once you figure out the the way,
I have seen some answers for Windows apps trying to manually build the authorization URLs etc, but there is an easier way to do it.
Here's how to do it with OAuth,
Install nuget
PM> Install-Package Box.V2
Get the Authcode (this is what's been missing in most examples)
public async Task<ActionResult> Connect()
{
var clientId = "xxxxx";
var clientSecret = "xxxxxx";
var redirectUri = new Uri("http://localhost:xxxx/Home/AuthCallBackAsync");//Your call back URL
var config = new BoxConfig(clientId, clientSecret, redirectUri);
return Redirect(config.AuthCodeUri.ToString());
}
Interesting thing is that the "config" object generates the AuthCodeUri.
This will redirect the user to Consent screen and ask the user to sign in. Once the user "Grants Access" you will get the "Authcode" for your call back URL which can be used to generate accesstoken.
Handle the Auth Callback response
public async Task<ActionResult> AuthCallbackAsync()
{
NameValueCollection parms = Request.QueryString;
var authCode = parms["code"]
//Get "config" - you can store this in session or in a cache.
var config = new BoxConfig(clientId, clientSecret, redirectUri);
var client = new BoxClient(config);
await client.Auth.AuthenticateAsync(authCode);
//Now you will get the accesstoken and refresh token
var accessToken = client.Auth.Session.AccessToken;
var refreshToken = client.Auth.Session.RefreshToken;
//Ready to consume the API
var user = await client.UsersManager.GetCurrentUserInformationAsync();
-------More Api Calls---
}

Facebook Retrive Data using Graph API using c#

i have created desktop Facebook application using c# .net. i want to retrieve users message,post and chat history. which is convenient way to retrieve users all information.i have started with Facebook Graph API but i am not getting any example.
can any one help me ?
A bit late to the party but anyway:
Add a reference to System.Net.Http and Newtonsoft.Json
string userToken = "theusertokentogiveyoumagicalpowers";
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://graph.facebook.com");
HttpResponseMessage response = client.GetAsync($"me?fields=name,email&access_token={userToken}").Result;
response.EnsureSuccessStatusCode();
string result = response.Content.ReadAsStringAsync().Result;
var jsonRes = JsonConvert.DeserializeObject<dynamic>(result);
var email = jsonRes["email"].ToString();
}
Go to developer.facebook.com -> Tools & Support -> Select Graph API Explorer
Here U get FQL Query, Access Token
Then write code in C#.....
var client = new FacebookClient();
client.AccessToken = Your Access Token;
//show user's profile picture
dynamic me = client.Get("me?fields=picture");
pictureBoxProfile.Load(me.picture.data.url);
//show user's birthday
me = client.Get("me/?fields=birthday");
labelBirthday.Text = Convert.ToString(me.birthday);
http://www.codeproject.com/Articles/380635/Csharp-Application-Integration-with-Facebook-Twitt
I hope this will help you.!!!
you can check the Graph explorer tool on Developer.facebook.com , go to Tools and select graph explorer, its a nice tool which gives you exact idea about what you can fetch by sending "GET" and "POST" method on FB Graph APis
From what i see the app now only uses webhooks to post data to a data endpoint (in your app) at which point you can parse and use this. (FQL is deprecated). This is used for things like messaging.
A get request can be send to the API to get info - like the amt. of likes on your page.
The docs of FB explain the string you have to send pretty nicely. Sending requests can be done with the webclient, or your own webrequests.
https://msdn.microsoft.com/en-us/library/bay1b5dh(v=vs.110).aspx
Then once you have a string of the JSON formatted page you can parse this using JSON.NET library. It's available as a NUGEt package.

Fetch Twitter Timeline as XML/JSON, show in Windows 8 app

I'm currently following a tutorial on how to show Twitter feeds with LINQ to XML in C#. However, seeing as Microsoft has replaced WebClient with HTTPClient, I'm unsure how to proceed on my quest of integrating this into my Windows 8 application.
The tutorial: http://www.codeproject.com/Articles/117614/How-to-query-twitter-public-status-using-LINQ-to-X
The thing is that I'm "halfway" used to DownloadStringCompleted, which I believe is not in the HTTPClient api. So after searching for a while on the async/await functionality, I mixed some of my knowledge together with some tutorials and snippets I found, but what I ended up with would not work:
public async Task<XElement> GetXmlAsync()
{
var client = new HttpClient();
var response = await client.GetAsync("http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=VladimirPutin");
var text = response.Content.ReadAsStringAsync();
return XElement.Parse(text.Result);
XElement xmlTweets = XElement.Parse(text.Result);
listboxTweetsSecond.ItemsSource = from tweet in xmlTweets.Descendants("status")
select new UserTweet
{
UserImageSrc = tweet.Element("user").Element("profile_image_url").Value,
UserMessage = tweet.Element("text").Value,
UserName = tweet.Element("user").Element("screen_name").Value
};
}
(Yeah, the Twitter username is just a placeholder)
I do not need an entire code as an answer, but I'd love it if someone could point out where I should go from here, as well as what I should do in general, as this (of course) does not work (as in, it does not show anything when I run it/debug mode).
Comment out the line
return XElement.Parse(text.Result);
and it should probably work.
Having done that (i.e. you are no longer returning an XElement) you can probably change the method signature top return just a task.
public async Task GetXmlAsync()
{
// method body
}

Categories

Resources