@@ -150,15 +150,9 @@ The two new lines of code:
150
150
151
151
### Add additional files to call Microsoft Graph
152
152
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) .
154
154
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.
162
156
163
157
### Update the `Startup.cs` file to enable the Microsoft Graph custom service
164
158
@@ -175,36 +169,55 @@ In the `Controllers\HomeController.cs`file:
175
169
176
170
1 . Add a constructor to HomeController , making the ITokenAcquisition service available (used by the ASP .NET dependency injection mechanism )
177
171
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 ;
183
175
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
+ ```
188
182
189
183
1 . 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 .
190
184
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 });
201
191
192
+ var me = await graphClient .Me .Request ().GetAsync ();
202
193
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
+ }
204
208
205
209
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
+ ```
208
221
209
222
### Add a Profile view to display the *me* object
210
223
@@ -220,37 +233,50 @@ HTML table displaying the properties of the *me* object as returned by Microsoft
220
233
< h3 > @ViewData [" Message" ]< / h3 >
221
234
222
235
< 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
+ }
252
279
}
253
- }
254
280
< / table >
255
281
```
256
282
0 commit comments