@@ -150,15 +150,9 @@ The two new lines of code:
150150
151151### Add additional files to call Microsoft Graph
152152
153- Add the ` Services \ Microsoft - Graph - Rest \ * . cs ` files . This is an implementation of a custom service which encapsulates the call to the Microsoft Graph / me endpoint . Given an access token for Microsoft Graph , it 's capable of getting the user information and the photo of the user .
153+ Add ` Microsoft . Graph ` package , to use [ Microsoft Graph SDK ]( https : // github.com/microsoftgraph/msgraph-sdk-dotnet/blob/dev/docs/overview.md) .
154154
155- ```CSharp
156- public interface IGraphApiOperations
157- {
158- Task < dynamic > GetUserInformation (string accessToken );
159- Task < string > GetPhotoAsBase64Async (string accessToken );
160- }
161- ```
155+ Add the `Services \* .cs ` files . The `GraphServiceClientFactory .cs ` returns a `GraphServiceClient ` with an authentication provider , used for [Microsoft Graph SDK ](https :// github.com/microsoftgraph/msgraph-sdk-dotnet/blob/dev/docs/overview.md). Given an access token for Microsoft Graph, it's capable of making a request to Graph services sending that access token in the header.
162156
163157### Update the `Startup.cs` file to enable the Microsoft Graph custom service
164158
@@ -175,36 +169,55 @@ In the `Controllers\HomeController.cs`file:
175169
1761701 . Add a constructor to HomeController , making the ITokenAcquisition service available (used by the ASP .NET dependency injection mechanism )
177171
178- ```CSharp
179- public HomeController (ITokenAcquisition tokenAcquisition , IGraphApiOperations graphApiOperations )
180- {
181- this .tokenAcquisition = tokenAcquisition ;
182- this .graphApiOperations = graphApiOperations ;
172+ ```CSharp
173+ readonly ITokenAcquisition tokenAcquisition ;
174+ readonly WebOptions webOptions ;
183175
184- }
185- private ITokenAcquisition tokenAcquisition ;
186- private readonly IGraphApiOperations graphApiOperations ;
187- ```
176+ public HomeController (ITokenAcquisition tokenAcquisition , IOptions < WebOptions > webOptionValue )
177+ {
178+ this .tokenAcquisition = tokenAcquisition ;
179+ this .webOptions = webOptionValue .Value ;
180+ }
181+ ```
188182
1891831 . Add a `Profile ()` action so that it calls the Microsoft Graph * me * endpoint . In case a token cannot be acquired , a challenge is attempted to re -sign -in the user , and have them consent to the requested scopes . This is expressed declaratively by the `AuthorizeForScopes `attribute . This attribute is part of the `Microsoft .Identity .Web ` project and automatically manages incremental consent .
190184
191- ```CSharp
192- [AuthorizeForScopes (Scopes = new [] {Constants .ScopeUserRead })]
193- public async Task < IActionResult > Profile ()
194- {
195- var accessToken =
196- await tokenAcquisition .GetAccessTokenOnBehalfOfUser (HttpContext ,
197- new [] {Constants .ScopeUserRead });
198-
199- var me = await graphApiOperations .GetUserInformation (accessToken );
200- var photo = await graphApiOperations .GetPhotoAsBase64Async (accessToken );
185+ ```CSharp
186+ [AuthorizeForScopes (Scopes = new [] { Constants .ScopeUserRead })]
187+ public async Task < IActionResult > Profile ()
188+ {
189+ // Initialize the GraphServiceClient.
190+ Graph :: GraphServiceClient graphClient = GetGraphServiceClient (new [] { Constants .ScopeUserRead });
201191
192+ var me = await graphClient .Me .Request ().GetAsync ();
202193 ViewData [" Me" ] = me ;
203- ViewData [" Photo" ] = photo ;
194+
195+ try
196+ {
197+ // Get user photo
198+ using (var photoStream = await graphClient .Me .Photo .Content .Request ().GetAsync ())
199+ {
200+ byte [] photoByte = ((MemoryStream )photoStream ).ToArray ();
201+ ViewData [" Photo" ] = Convert .ToBase64String (photoByte );
202+ }
203+ }
204+ catch (System .Exception )
205+ {
206+ ViewData [" Photo" ] = null ;
207+ }
204208
205209 return View ();
206- }
207- ```
210+ }
211+
212+ private Graph :: GraphServiceClient GetGraphServiceClient (string [] scopes )
213+ {
214+ return GraphServiceClientFactory .GetAuthenticatedGraphClient (async () =>
215+ {
216+ string result = await tokenAcquisition .GetAccessTokenOnBehalfOfUserAsync (scopes );
217+ return result ;
218+ }, webOptions .GraphApiUrl );
219+ }
220+ ```
208221
209222### Add a Profile view to display the *me* object
210223
@@ -220,37 +233,50 @@ HTML table displaying the properties of the *me* object as returned by Microsoft
220233< h3 > @ViewData [" Message" ]< / h3 >
221234
222235< table class = " table table-striped table-condensed" style = " font-family: monospace" >
223- < tr >
224- < th > Property < / th >
225- < th > Value < / th >
226- < / tr >
227- < tr >
228- < td > photo < / td >
229- < td >
230- @{
231- if (ViewData [" photo" ] != null )
232- {
233- < img style = " margin: 5px 0; width: 150px" src = " data:image/jpeg;base64, @ViewData[" photo " ]" / >
234- }
235- else
236- {
237- < h3 > NO PHOTO < / h3 >
238- < p > Check user profile in Azure Active Directory to add a photo .< / p >
239- }
240- }
241- < / td >
242- < / tr >
243- @{
244- var me = ViewData [" me" ] as JObject ;
245- var children = me .Properties ();
246- foreach (var child in children )
247- {
248- < tr >
249- < td > @child .Name < / td >
250- < td > @child .Value < / td >
251- < / tr >
236+ < tr >
237+ < th > Property < / th >
238+ < th > Value < / th >
239+ < / tr >
240+ < tr >
241+ < td > photo < / td >
242+ < td >
243+ @{
244+ if (ViewData [" photo" ] != null )
245+ {
246+ < img style = " margin: 5px 0; width: 150px" src = " data:image/jpeg;base64, @ViewData[" photo " ]" / >
247+ }
248+ else
249+ {
250+ < h3 > NO PHOTO < / h3 >
251+ < p > Check user profile in Azure Active Directory to add a photo .< / p >
252+ }
253+ }
254+ < / td >
255+ < / tr >
256+ @{
257+ var me = ViewData [" me" ] as Microsoft .Graph .User ;
258+ var properties = me .GetType ().GetProperties ();
259+ foreach (var child in properties )
260+ {
261+ object value = child .GetValue (me );
262+ string stringRepresentation ;
263+ if (! (value is string ) && value is IEnumerable <string >)
264+ {
265+ stringRepresentation = " ["
266+ + string .Join (" , " , (value as IEnumerable <string >).OfType <object >().Select (c => c .ToString ()))
267+ + " ]" ;
268+ }
269+ else
270+ {
271+ stringRepresentation = value ? .ToString ();
272+ }
273+
274+ < tr >
275+ < td > @child .Name < / td >
276+ < td > @stringRepresentation < / td >
277+ < / tr >
278+ }
252279 }
253- }
254280< / table >
255281```
256282
0 commit comments