@@ -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
@@ -176,35 +170,55 @@ In the `Controllers\HomeController.cs`file:
1761701 . Add a constructor to HomeController , making the ITokenAcquisition service available (used by the ASP .NET dependency injection mechanism )
177171
178172 ```CSharp
179- public HomeController ( ITokenAcquisition tokenAcquisition , IGraphApiOperations graphApiOperations )
180- {
181- this . tokenAcquisition = tokenAcquisition ;
182- this . graphApiOperations = graphApiOperations ;
183-
184- }
185- private ITokenAcquisition tokenAcquisition ;
186- private readonly IGraphApiOperations graphApiOperations ;
173+ readonly ITokenAcquisition tokenAcquisition ;
174+ readonly WebOptions webOptions ;
175+
176+ public HomeController ( ITokenAcquisition tokenAcquisition , IOptions < WebOptions > webOptionValue )
177+ {
178+ this . tokenAcquisition = tokenAcquisition ;
179+ this . webOptions = webOptionValue . Value ;
180+ }
187181 ```
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 });
191+
192+ var me = await graphClient .Me .Request ().GetAsync ();
193+ ViewData [" Me" ] = me ;
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+ }
208+
209+ return View ();
210+ }
201211
202- ViewData [" Me" ] = me ;
203- ViewData [" Photo" ] = photo ;
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+ }
204220
205- return View ();
206- }
207- ```
221+ ```
208222
209223### Add a Profile view to display the *me* object
210224
@@ -220,37 +234,50 @@ HTML table displaying the properties of the *me* object as returned by Microsoft
220234< h3 > @ViewData [" Message" ]< / h3 >
221235
222236< table class = " table table-striped table-condensed" style = " font-family: monospace" >
223- < tr >
237+ < tr >
224238 < th > Property < / th >
225239 < 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- }
240+ < / tr >
241+ < tr >
242+ < td > photo < / td >
243+ < td >
244+ @{
245+ if (ViewData [" photo" ] != null )
246+ {
247+ < img style = " margin: 5px 0; width: 150px" src = " data:image/jpeg;base64, @ViewData[" photo " ]" / >
248+ }
249+ else
250+ {
251+ < h3 > NO PHOTO < / h3 >
252+ < p > Check user profile in Azure Active Directory to add a photo .< / p >
253+ }
254+ }
241255 < / td >
242256 < / tr >
243- @{
244- var me = ViewData [" me" ] as JObject ;
245- var children = me .Properties ();
246- foreach (var child in children )
257+ @{
258+ var me = ViewData [" me" ] as Microsoft . Graph . User ;
259+ var properties = me .GetType (). GetProperties ();
260+ foreach (var child in properties )
247261 {
248- < tr >
249- < td > @child .Name < / td >
250- < td > @child .Value < / td >
251- < / tr >
252- }
253- }
262+ object value = child .GetValue (me );
263+ string stringRepresentation ;
264+ if (! (value is string ) && value is IEnumerable <string >)
265+ {
266+ stringRepresentation = " ["
267+ + string .Join (" , " , (value as IEnumerable <string >).OfType <object >().Select (c => c .ToString ()))
268+ + " ]" ;
269+ }
270+ else
271+ {
272+ stringRepresentation = value ? .ToString ();
273+ }
274+
275+ < tr >
276+ < td > @child .Name < / td >
277+ < td > @stringRepresentation < / td >
278+ < / tr >
279+ }
280+ }
254281< / table >
255282```
256283
0 commit comments