Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Appelez Microsoft Graph à partir de vos applications ASP.NET Core et OWIN à l’aide de Microsoft. Identity.Web et le Kit de développement logiciel (SDK) Microsoft Graph pour accéder à Microsoft 365 données et services.
Comprendre l’intégration de Microsoft Graph
Microsoft Graph fournit un point de terminaison d’API unifié pour accéder aux données entre Microsoft 365, Windows et Enterprise Mobility + Security. Microsoft.Identity.Web simplifie l’authentification et l’acquisition de jetons pour Microsoft Graph, tandis que le SDK Microsoft Graph fournit une API fluide et typée pour appeler des points de terminaison du Graph.
Choisissez Microsoft. Identity.Web.GraphServiceClient
Les avantages suivants rendent Microsoft. Identity.Web.GraphServiceClient l’approche recommandée pour appeler Microsoft Graph.
- Acquisition automatique de jetons : gère en toute transparence les jetons d’utilisateur et d’application
- Mise en cache des jetons : mise en cache intégrée pour les performances
- API Fluent : Appels Graph permettant la sécurité de type et le soutien d'IntelliSense
- Consentement incrémentiel : demander des étendues supplémentaires à la demande
- Schémas d’authentification multiples : prise en charge des applications web et des API web
- V1.0 et Bêta : Utiliser ensemble des points de connexion stables et en préversion
Installer les packages requis
Installez le package d’intégration Microsoft Graph SDK :
dotnet add package Microsoft.Identity.Web.GraphServiceClient
Pour les API bêta Microsoft Graph :
dotnet add package Microsoft.Identity.Web.GraphServiceClientBeta
Configurer ASP.NET Core
1. Configurer les services
Ajoutez la prise en charge de Microsoft Graph à votre application.
using Microsoft.Identity.Web;
var builder = WebApplication.CreateBuilder(args);
// Add authentication (web app or web API)
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
// Add Microsoft Graph support
builder.Services.AddMicrosoftGraph();
builder.Services.AddControllersWithViews();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
2. Configurer appsettings.json
Configurez les options Graph dans votre fichier de configuration :
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "your-tenant-id",
"ClientId": "your-client-id",
"ClientSecret": "your-client-secret",
"CallbackPath": "/signin-oidc"
},
"DownstreamApis": {
"MicrosoftGraph": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"Scopes": ["User.Read", "User.ReadBasic.All"]
}
}
}
Configuration avec du code :
builder.Services.AddMicrosoftGraph(options =>
{
builder.Configuration.GetSection("DownstreamApis:MicrosoftGraph").Bind(options);
});
Ou configurez directement dans le code :
builder.Services.AddMicrosoftGraph();
builder.Services.Configure<MicrosoftGraphOptions>(options =>
{
options.BaseUrl = "https://graph.microsoft.com/v1.0";
options.Scopes = new[] { "User.Read", "Mail.Read" };
});
3. Configurer la prise en charge du cloud national
Pour utiliser Microsoft Graph dans les clouds nationaux, spécifiez la baseUrl dans votre configuration :
{
"DownstreamApis": {
"MicrosoftGraph": {
"BaseUrl": "https://graph.microsoft.us/v1.0",
"Scopes": ["User.Read"]
}
}
}
Consultez Microsoft Graph déploiements pour les URL de point de terminaison.
Utiliser GraphServiceClient
Injecter GraphServiceClient
Injectez GraphServiceClient depuis le constructeur :
using Microsoft.Graph;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
[Authorize]
public class ProfileController : Controller
{
private readonly GraphServiceClient _graphClient;
public ProfileController(GraphServiceClient graphClient)
{
_graphClient = graphClient;
}
public async Task<IActionResult> Index()
{
// Call Microsoft Graph
var user = await _graphClient.Me.GetAsync();
return View(user);
}
}
Utiliser des autorisations déléguées (jetons utilisateur)
Appelez Graph pour le compte de l’utilisateur connecté avec des autorisations déléguées.
Récupérer le profil utilisateur de base
Récupérez les informations de profil de l'utilisateur actuel à partir de Microsoft Graph.
[Authorize]
public class ProfileController : Controller
{
private readonly GraphServiceClient _graphClient;
public ProfileController(GraphServiceClient graphClient)
{
_graphClient = graphClient;
}
public async Task<IActionResult> Me()
{
// Get current user's profile
var user = await _graphClient.Me.GetAsync();
return View(new UserViewModel
{
DisplayName = user.DisplayName,
Mail = user.Mail,
JobTitle = user.JobTitle
});
}
}
Demander un consentement incrémentiel
Demandez des étendues supplémentaires dynamiquement lorsque votre application en a besoin :
[Authorize]
[AuthorizeForScopes("Mail.Read")]
public class MailController : Controller
{
private readonly GraphServiceClient _graphClient;
public MailController(GraphServiceClient graphClient)
{
_graphClient = graphClient;
}
public async Task<IActionResult> Inbox()
{
try
{
// Request Mail.Read scope dynamically
var messages = await _graphClient.Me.Messages
.GetAsync(r => r.Options.WithScopes("Mail.Read"));
return View(messages);
}
catch (MicrosoftIdentityWebChallengeUserException)
{
// ASP.NET Core will redirect user to consent
// thansk to the AuthorizeForScopes attribute.
throw;
}
}
}
Appliquer des options de requête
Utilisez les options de requête du Kit de développement logiciel (SDK) Graph pour filtrer, sélectionner et classer les résultats :
public async Task<IActionResult> UnreadMessages()
{
var messages = await _graphClient.Me.Messages
.GetAsync(requestConfiguration =>
{
requestConfiguration.QueryParameters.Filter = "isRead eq false";
requestConfiguration.QueryParameters.Select = new[] { "subject", "from", "receivedDateTime" };
requestConfiguration.QueryParameters.Orderby = new[] { "receivedDateTime desc" };
requestConfiguration.QueryParameters.Top = 10;
// Request specific scope
requestConfiguration.Options.WithScopes("Mail.Read");
});
return View(messages);
}
Feuilleter les résultats
Gérez les résultats paginés de Microsoft Graph en itérant à travers chaque page :
public async Task<IActionResult> AllUsers()
{
var allUsers = new List<User>();
// Get first page
var users = await _graphClient.Users
.GetAsync(r => r.Options.WithScopes("User.ReadBasic.All"));
// Add first page
allUsers.AddRange(users.Value);
// Iterate through remaining pages
var pageIterator = PageIterator<User, UserCollectionResponse>
.CreatePageIterator(
_graphClient,
users,
user =>
{
allUsers.Add(user);
return true; // Continue iteration
});
await pageIterator.IterateAsync();
return View(allUsers);
}
Utiliser des autorisations d’application (jetons d’application uniquement)
Appelez Graph avec des autorisations d’application quand aucun contexte utilisateur n’est requis.
Appeler Graph avec WithAppOnly()
Utilisez la WithAppOnly() méthode pour effectuer des appels Graph avec des autorisations d’application.
[Authorize]
[ApiController]
[Route("api/[controller]")]
public class AdminController : ControllerBase
{
private readonly GraphServiceClient _graphClient;
public AdminController(GraphServiceClient graphClient)
{
_graphClient = graphClient;
}
[HttpGet("users/count")]
public async Task<ActionResult<int>> GetUserCount()
{
// Get count using app permissions
var count = await _graphClient.Users.Count
.GetAsync(r => r.Options.WithAppOnly());
return Ok(count);
}
[HttpGet("applications")]
public async Task<ActionResult> GetApplications()
{
// List applications using app permissions
var apps = await _graphClient.Applications
.GetAsync(r => r.Options.WithAppOnly());
return Ok(apps.Value);
}
}
Configuration des autorisations d'application
Spécifiez une demande de jeton d’application dans appsettings.json:
{
"DownstreamApis": {
"MicrosoftGraph": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"RequestAppToken": true
}
}
}
Les étendues sont automatiquement définies sur ["https://graph.microsoft.com/.default"].
Configurer des options détaillées d’application uniquement
Définissez des options d’authentification explicites d’application uniquement dans le code.
public async Task<IActionResult> GetApplicationsDetailed()
{
var apps = await _graphClient.Applications
.GetAsync(r =>
{
r.Options.WithAuthenticationOptions(options =>
{
// Request app token explicitly
options.RequestAppToken = true;
// Scopes automatically become [.default]
// No need to specify: options.Scopes = new[] { "https://graph.microsoft.com/.default" };
});
});
return Ok(apps);
}
Gérer plusieurs schémas d’authentification
Si votre application utilise plusieurs schémas d’authentification (par exemple, application web + API), spécifiez le schéma à utiliser :
using Microsoft.AspNetCore.Authentication.JwtBearer;
[Authorize]
public class ApiDataController : ControllerBase
{
private readonly GraphServiceClient _graphClient;
public ApiDataController(GraphServiceClient graphClient)
{
_graphClient = graphClient;
}
[HttpGet("profile")]
public async Task<ActionResult> GetProfile()
{
// Specify JWT Bearer scheme
var user = await _graphClient.Me
.GetAsync(r => r.Options
.WithAuthenticationScheme(JwtBearerDefaults.AuthenticationScheme));
return Ok(user);
}
}
Configurer des options de schéma détaillées
Définissez explicitement le schéma d’authentification et les étendues dans le code.
public async Task<ActionResult> GetMailWithScheme()
{
var messages = await _graphClient.Me.Messages
.GetAsync(r =>
{
r.Options.WithAuthenticationOptions(options =>
{
// Specify authentication scheme
options.AcquireTokenOptions.AuthenticationOptionsName =
JwtBearerDefaults.AuthenticationScheme;
// Specify scopes
options.Scopes = new[] { "Mail.Read" };
});
});
return Ok(messages);
}
Utiliser les points de terminaison v1.0 et Bêta
Inscrivez et appelez Microsoft Graph version 1.0 et bêta dans la même application.
1. Installer les deux packages
dotnet add package Microsoft.Identity.Web.GraphServiceClient
dotnet add package Microsoft.Identity.Web.GraphServiceClientBeta
2. Inscrire les deux services
using Microsoft.Identity.Web;
builder.Services.AddMicrosoftGraph();
builder.Services.AddMicrosoftGraphBeta();
3. Utiliser les deux clients
using GraphServiceClient = Microsoft.Graph.GraphServiceClient;
using GraphBetaServiceClient = Microsoft.Graph.Beta.GraphServiceClient;
public class MyController : Controller
{
private readonly GraphServiceClient _graphClient;
private readonly GraphBetaServiceClient _graphBetaClient;
public MyController(
GraphServiceClient graphClient,
GraphBetaServiceClient graphBetaClient)
{
_graphClient = graphClient;
_graphBetaClient = graphBetaClient;
}
public async Task<IActionResult> GetData()
{
// Use stable v1.0 endpoint
var user = await _graphClient.Me.GetAsync();
// Use beta endpoint for preview features
var profile = await _graphBetaClient.Me.Profile.GetAsync();
return View(new { user, profile });
}
}
Envoyer des requêtes par lots
Combinez plusieurs appels Graph dans une seule requête HTTP pour améliorer les performances :
using Microsoft.Graph.Models;
public async Task<IActionResult> GetDashboard()
{
var batchRequestContent = new BatchRequestContentCollection(_graphClient);
// Add multiple requests to batch
var userRequest = _graphClient.Me.ToGetRequestInformation();
var messagesRequest = _graphClient.Me.Messages.ToGetRequestInformation();
var eventsRequest = _graphClient.Me.Events.ToGetRequestInformation();
var userRequestId = await batchRequestContent.AddBatchRequestStepAsync(userRequest);
var messagesRequestId = await batchRequestContent.AddBatchRequestStepAsync(messagesRequest);
var eventsRequestId = await batchRequestContent.AddBatchRequestStepAsync(eventsRequest);
// Send batch request
var batchResponse = await _graphClient.Batch.PostAsync(batchRequestContent);
// Extract responses
var user = await batchResponse.GetResponseByIdAsync<User>(userRequestId);
var messages = await batchResponse.GetResponseByIdAsync<MessageCollectionResponse>(messagesRequestId);
var events = await batchResponse.GetResponseByIdAsync<EventCollectionResponse>(eventsRequestId);
return View(new DashboardViewModel
{
User = user,
Messages = messages.Value,
Events = events.Value
});
}
Appliquer des modèles Graph courants
Utilisez ces modèles pour effectuer des opérations de Microsoft Graph fréquentes dans votre application.
Obtenir le responsable de l’utilisateur
Récupérez le gestionnaire de l’utilisateur connecté à partir du répertoire.
public async Task<IActionResult> GetManager()
{
var manager = await _graphClient.Me.Manager.GetAsync();
// Cast to User (manager is DirectoryObject)
if (manager is User managerUser)
{
return View(managerUser);
}
return NotFound("Manager not found");
}
Obtenir la photo de l’utilisateur
Téléchargez la photo de profil de l'utilisateur connecté sous forme de flux de données.
public async Task<IActionResult> GetPhoto()
{
try
{
var photoStream = await _graphClient.Me.Photo.Content.GetAsync();
return File(photoStream, "image/jpeg");
}
catch (ServiceException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
{
return NotFound("Photo not available");
}
}
Envoyer un e-mail
Envoyez un e-mail pour le compte de l’utilisateur connecté.
public async Task<IActionResult> SendEmail([FromBody] EmailRequest request)
{
var message = new Message
{
Subject = request.Subject,
Body = new ItemBody
{
ContentType = BodyType.Html,
Content = request.Body
},
ToRecipients = new List<Recipient>
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = request.ToEmail
}
}
}
};
await _graphClient.Me.SendMail
.PostAsync(new SendMailPostRequestBody
{
Message = message,
SaveToSentItems = true
},
requestConfiguration =>
{
requestConfiguration.Options.WithScopes("Mail.Send");
});
return Ok("Email sent");
}
Créer un événement de calendrier
Créez un événement de calendrier avec les participants pour l’utilisateur connecté.
public async Task<IActionResult> CreateEvent([FromBody] EventRequest request)
{
var newEvent = new Event
{
Subject = request.Subject,
Start = new DateTimeTimeZone
{
DateTime = request.StartTime.ToString("yyyy-MM-ddTHH:mm:ss"),
TimeZone = "UTC"
},
End = new DateTimeTimeZone
{
DateTime = request.EndTime.ToString("yyyy-MM-ddTHH:mm:ss"),
TimeZone = "UTC"
},
Attendees = request.Attendees.Select(email => new Attendee
{
EmailAddress = new EmailAddress { Address = email },
Type = AttendeeType.Required
}).ToList()
};
var createdEvent = await _graphClient.Me.Events
.PostAsync(newEvent, r => r.Options.WithScopes("Calendars.ReadWrite"));
return Ok(createdEvent);
}
Rechercher des utilisateurs
Recherchez les utilisateurs dans le répertoire par nom complet ou adresse e-mail.
public async Task<IActionResult> SearchUsers(string searchTerm)
{
var users = await _graphClient.Users
.GetAsync(requestConfiguration =>
{
requestConfiguration.QueryParameters.Filter =
$"startswith(displayName,'{searchTerm}') or startswith(mail,'{searchTerm}')";
requestConfiguration.QueryParameters.Select =
new[] { "displayName", "mail", "jobTitle" };
requestConfiguration.QueryParameters.Top = 10;
requestConfiguration.Options.WithScopes("User.ReadBasic.All");
});
return Ok(users.Value);
}
Implémenter le support technique OWIN
Pour les applications ASP.NET qui utilisent OWIN, configurez la fabrique d’acquisition de jetons et inscrivez les services Microsoft Graph.
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.OWIN;
using Owin;
public class Startup
{
public void Configuration(IAppBuilder app)
{
OwinTokenAcquirerFactory factory = TokenAcquirerFactory.GetDefaultInstance<OwinTokenAcquirerFactory>();
app.AddMicrosoftIdentityWebApi(factory);
factory.Services
.AddMicrosoftGraph();
factory.Build();
}
}
2. Appeler l’API à partir de contrôleurs
Récupérez une instance GraphServiceClient dans votre contrôleur et appelez Microsoft Graph.
using Microsoft.Identity.Abstractions;
using Microsoft.Identity.Web;
using System.Web.Http;
[Authorize]
public class DataController : ApiController
{
public DataController()
{
}
public async Task<IHttpActionResult> GetMyProfile()
{
GraphServiceClient graphServiceClient = this.GetGraphServiceClient();
var me = await graphServiceClient.Me.GetAsync();
return Ok(me);
}
}
Migrez à partir de Microsoft. Identity.Web.MicrosoftGraph 2.x
Si vous effectuez une migration à partir de la version plus ancienne du package Microsoft.Identity.Web.MicrosoftGraph (SDK 4.x), examinez les modifications clés suivantes :
1. Supprimer l’ancien package et ajouter nouveau
dotnet remove package Microsoft.Identity.Web.MicrosoftGraph
dotnet add package Microsoft.Identity.Web.GraphServiceClient
2. Mettre à jour les appels de méthode
La .Request() méthode a été supprimée dans le Kit de développement logiciel (SDK) 5.x :
Avant (SDK 4.x) :
var user = await _graphClient.Me.Request().GetAsync();
var messages = await _graphClient.Me.Messages
.Request()
.WithScopes("Mail.Read")
.GetAsync();
Après (SDK 5.x) :
var user = await _graphClient.Me.GetAsync();
var messages = await _graphClient.Me.Messages
.GetAsync(r => r.Options.WithScopes("Mail.Read"));
3. Mettre à jour l’emplacement WithScopes()
Before:
var users = await _graphClient.Users
.Request()
.WithScopes("User.Read.All")
.GetAsync();
After:
var users = await _graphClient.Users
.GetAsync(r => r.Options.WithScopes("User.Read.All"));
4. Mettre à jour l’emplacement WithAppOnly()
Before:
var apps = await _graphClient.Applications
.Request()
.WithAppOnly()
.GetAsync();
After:
var apps = await _graphClient.Applications
.GetAsync(r => r.Options.WithAppOnly());
5. Mettre à jour l’emplacement WithAuthenticationScheme()
Before:
var user = await _graphClient.Me
.Request()
.WithAuthenticationScheme(JwtBearerDefaults.AuthenticationScheme)
.GetAsync();
After:
var user = await _graphClient.Me
.GetAsync(r => r.Options
.WithAuthenticationScheme(JwtBearerDefaults.AuthenticationScheme));
Pour plus d’informations sur la migration, consultez Microsoft Graph .NET sdk v5 changelog.
Gérer les erreurs
Gérer l'exception ServiceException
Interceptez ODataError et MicrosoftIdentityWebChallengeUserException pour gérer avec élégance les défaillances de l'API Graph.
using Microsoft.Graph.Models.ODataErrors;
public async Task<IActionResult> GetData()
{
try
{
var user = await _graphClient.Me.GetAsync();
return Ok(user);
}
catch (ODataError ex) when (ex.ResponseStatusCode == 404)
{
return NotFound("Resource not found");
}
catch (ODataError ex) when (ex.ResponseStatusCode == 403)
{
return Forbid("Insufficient permissions");
}
catch (MicrosoftIdentityWebChallengeUserException)
{
// User needs to consent
throw;
}
catch (Exception ex)
{
_logger.LogError(ex, "Graph API call failed");
return StatusCode(500, "An error occurred");
}
}
Suivre les bonnes pratiques
1. Demander des étendues minimales
Demandez uniquement les périmètres dont vous avez besoin :
// Bad: Requesting too many scopes
options.Scopes = new[] { "User.Read", "Mail.ReadWrite", "Calendars.ReadWrite", "Files.ReadWrite.All" };
// Good: Request only what you need
options.Scopes = new[] { "User.Read" };
2. Utiliser le consentement incrémentiel
Demandez des étendues supplémentaires uniquement si nécessaire :
// Sign-in: Only User.Read
// Later, when accessing mail:
var messages = await _graphClient.Me.Messages
.GetAsync(r => r.Options.WithScopes("Mail.Read"));
3. Cache le GraphServiceClient
GraphServiceClient est sûr à réutiliser. Inscrivez-vous en tant que singleton ou injectez à partir de DI.
4. Utiliser la sélection pour réduire la taille de réponse
// Bad: Getting all properties
var users = await _graphClient.Users.GetAsync();
// Good: Select only needed properties
var users = await _graphClient.Users
.GetAsync(r => r.QueryParameters.Select =
new[] { "displayName", "mail", "id" });
Résoudre les problèmes courants
Résolvez « Privilèges insuffisants pour terminer l’opération »
Cause : l’application n’a pas d’autorisations Graph requises.
Solution:
- Ajouter des autorisations d’API requises dans l’inscription d’application
- Consentement administrateur requis pour les autorisations d’application
- Consentement de l’utilisateur requis pour les autorisations déléguées
Résolvez « AADSTS65001 : l’utilisateur ou l’administrateur n’a pas consenti »
Cause : l’utilisateur n’a pas consenti aux étendues demandées.
Solution : utilisez le consentement incrémentiel avec .WithScopes() pour déclencher le flux de consentement.
Résoudre les erreurs photo 404
Cause : l’utilisateur n’a pas de photo de profil.
Solution : gérez correctement 404 et fournissez un avatar par défaut.
Résoudre les défaillances de requêtes par lots
Cause : les requêtes individuelles par lots peuvent échouer indépendamment.
Solution : vérifiez chaque réponse par lot pour les erreurs :
var userResponse = await batchResponse.GetResponseByIdAsync<User>(userRequestId);
if (userResponse == null)
{
// Handle individual request failure
}
Contenu connexe
- Documentation de Microsoft Graph
- Guide de migration du Kit de développement logiciel (SDK) Graph v5
- Présentation générale de l'appel des API descendantes
- Appels depuis des applications Web
- Appel à partir d’API web
Next Steps : En savoir plus sur calling SDK Azure ou custom API.