SOLVED

How to get user photo in C# using Graph API?

Brass Contributor

I am building a bot which shows user the searched user photo and other information. Rest of the information is being fetched properly other than user's photo.

 

I am trying to get user photo by using below URL. Graph explorer shows the user's photo using this URL.

https://graph.microsoft.com/v1.0/users/{userid}/photo/$value

 

I am using below code to get the image and assign it as URL to image card in my bot.

        private async Task<string> GetPhoto(HttpClient client, string id)
        {
           
            var resp = await client.GetAsync("https://graph.microsoft.com/v1.0/users/{id}/photo/$value");
            var buffer = await resp.Content.ReadAsByteArrayAsync();
            var byteArray = buffer.ToArray();

            string base64String = Convert.ToBase64String(byteArray);

            Trace.WriteLine($"converted base 64 string! =>=>=>=> {base64String}");
            return base64String;

        }

is it the right way to fetch and show the user photo in C#?

3 Replies
best response confirmed by GraemeB (Microsoft)
Solution

I found the solution to this issue in one of the Richard diZerega's sample bots. Following is the way you display the user's photo in bot.

 

Get the byte array of the user's photo by using Graph API.

 

// Extension method
public static async Task<byte[]> GetStreamWithAuthAsync(this HttpClient client, string accessToken, string endpoint)
        {
            client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
            client.DefaultRequestHeaders.Add("Accept", "application/json");
            using (var response = await client.GetAsync(endpoint))
            {
                if (response.IsSuccessStatusCode)
                {
                    var stream = await response.Content.ReadAsStreamAsync();
                    byte[] bytes = new byte[stream.Length];
                    stream.Read(bytes, 0, (int)stream.Length);
                    return bytes;
                }
                else
                    return null;
            }
        }

Assign the above byte array with the prefix "data&colon;image/png;base64," and assign it to image URL property.

 

 

// Get the users profile photo from the Microsoft Graph
var bytes = await new HttpClient().GetStreamWithAuthAsync(token, "https://graph.microsoft.com/v1.0/me/photo/$value");
var pic = "data&colon;image/png;base64," + Convert.ToBase64String(bytes);

ThumbnailCard card = new ThumbnailCard()
 {
    Title = $"{((JValue)jItem["Subject"]).Value}",
    Subtitle = jItem.SelectToken("sender.emailAdress.name").ToString(),
    Text = jItem.SelectToken("body.content").ToString(),
    Images = new List<CardImage>()
    {
          new CardImage()
          {
                Url= pic
          }
    }
 };
 return card;

 

 

 

@Atul Moghe

 

How would you do this for a single page web app using PHP or MSAL.js

I can get the details data, but not the actual photo 

@Atul Moghe 

 

WIth recent updates to Microsoft.Graph api (summer 2020), this approach is pretty clean:

public static async Task<System.Drawing.Image> GetMePhotoAsync()
        {
            try
            {
                // GET /me
                Stream photoresponse = await graphClient.Me.Photo.Content.Request().GetAsync();

                if (photoresponse != null)
                {
                    MemoryStream ms = new MemoryStream();
                    photoresponse.CopyTo(ms);
                    System.Drawing.Image i = System.Drawing.Image.FromStream(ms);

                    return i;
                }
                else
                { return null; }
            }
            catch (ServiceException ex)
            {
                Console.WriteLine($"Error getting signed-in user profilephoto: {ex.Message}");
                return null;
            }
        }
1 best response

Accepted Solutions
best response confirmed by GraemeB (Microsoft)
Solution

I found the solution to this issue in one of the Richard diZerega's sample bots. Following is the way you display the user's photo in bot.

 

Get the byte array of the user's photo by using Graph API.

 

// Extension method
public static async Task<byte[]> GetStreamWithAuthAsync(this HttpClient client, string accessToken, string endpoint)
        {
            client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
            client.DefaultRequestHeaders.Add("Accept", "application/json");
            using (var response = await client.GetAsync(endpoint))
            {
                if (response.IsSuccessStatusCode)
                {
                    var stream = await response.Content.ReadAsStreamAsync();
                    byte[] bytes = new byte[stream.Length];
                    stream.Read(bytes, 0, (int)stream.Length);
                    return bytes;
                }
                else
                    return null;
            }
        }

Assign the above byte array with the prefix "data&colon;image/png;base64," and assign it to image URL property.

 

 

// Get the users profile photo from the Microsoft Graph
var bytes = await new HttpClient().GetStreamWithAuthAsync(token, "https://graph.microsoft.com/v1.0/me/photo/$value");
var pic = "data&colon;image/png;base64," + Convert.ToBase64String(bytes);

ThumbnailCard card = new ThumbnailCard()
 {
    Title = $"{((JValue)jItem["Subject"]).Value}",
    Subtitle = jItem.SelectToken("sender.emailAdress.name").ToString(),
    Text = jItem.SelectToken("body.content").ToString(),
    Images = new List<CardImage>()
    {
          new CardImage()
          {
                Url= pic
          }
    }
 };
 return card;

 

 

 

View solution in original post