Announcing Azure AD Graph API Client Library 2.0


The Graph API team is pleased to announce that Azure AD Graph has a new client library (version 2.0).  This was released recently at TechEd Europe 2014, as part of the exciting new Office 365 REST APIs and SDKs, which allows developers to easily build applications for .Net, Android and iOS.  You’ll find our new Graph libraries have the same consistent signature as the Office 365 client libraries, and are supported on the same platforms. Visual Studio developers can write applications that use Graph and Office 365 API using C# code, targeting Windows Phone, Windows Store, and MVC web apps. Additionally through Xamarin, that same code can now target Android and iOS. But wait there’s more! Through Microsoft Open Technologies we even have support for integrated development environments outside of Visual Studio!  Android developers, you can now preview connecting your applications to cloud services like Graph and Office 365, using IntelliJ or Android Studio, just like .Net developers do with Visual Studio.

Major benefits of the 2.0 library

Platform reach: With this release of the Graph and Office 365 API SDKs, we have:

  • NET SDK portable client library builds many types of apps using Visual Studio
    • .NET Windows Store (and Universal Store) Apps
    • Windows Forms Application
    • WPF Application
    • ASP.NET MVC Web Application
    • ASP.NET Web Forms Application
    • Xamarin Android and iOS Applications (build Android and iOS apps within VS)
    • Multi-device Hybrid Apps (Cordova)
    • Windows Phone 8.1 Apps (version 1.1.728 onwards)
  • Microsoft Office 365 API Tools for Visual Studio 2013 to easily create and connect apps to O365 and Graph cloud service APIs through the client libraries.
  • Native Android SDK (GA) & iOS SDK
    • Includes native Android and iOS Graph client libraries and samples
  • IntelliJ/Android Studio for Microsoft Services (preview)
    • Mobile developers can connect Android Apps to O365 and Azure Mobile Services through Android development environments

Consistent APIs:  Client libraries have a consistent signature across Graph and Office 365 client libraries

Async support:  Now call Graph asynchronously

Simplified query support:  Query Azure AD graph using LINQ constructs (rather than complex filter expressions)

A closer look at the .Net client library

For this post we will focus on the .Net client library.  If you’re more interested in the native Android and iOS client SDKs, please check out the Native Android SDK (GA) & iOS SDK blog, which link to the SDKs on github.

You can find the latest Graph client library 2.0  on nuget.org.  When you clone any of our samples from Github that use the new client library (using Visual Studio), and build the samples, this will automatically resolve references to our newest nuget package and pull it into your solution.  We have 2 samples available on github that use the new client library, and we’ll add more over time:

For the rest of this section we’ll walk you through some of the key calling patterns and scenarios.

Instantiating a graph client

Since Graph API is secured by Azure AD, you’ll also need to make sure that your solution contains the AD Authentication Library (or ADAL), which is also available as a nuget package.  NOTE: ADAL is also available natively for iOS and Android.

The following code snippet defines a helper function that returns an ActiveDirectoryClient.

public static ActiveDirectoryClient GetActiveDirectoryClientAsApplication()
{
    Uri servicePointUri = new Uri(”https://graph.windows.net”);

    Uri serviceRoot = new Uri(servicePointUri, ”contoso.com”);

    ActiveDirectoryClient activeDirectoryClient = new ActiveDirectoryClient(serviceRoot, async () => await AcquireTokenAsyncForApplication());

    return activeDirectoryClient;

}

Client creation also requires a valid authorization token which in this case is accomplished through a helper function that makes use of ADAL methods. In this case the client is associated with a confidential_client flow token (application token).  Client creation can also be associated with a code flow token (“delegation” or “application + user” token).

Once the client is instantiated, the fun can begin and we can start calling the Graph!  The client object model now exposes all the entities, underlying complex types, properties, links, actions and custom service actions.

Async model

The new Graph Client Library also has support to make asynchronous calls to query Azure AD Graph. Async calls can help the overall responsiveness of your application and mitigate performance bottlenecks.

To retrieve an entity asynchronously:

AzureActiveDirectoryClient activeDirectoryClient;

Task<IPagedCollection<{Entity}>> getGraphObjectsTask = activeDirectoryClient.{Entity}.ExecuteAsync();

IPagedCollection<{Entity}> graphObjects = await getGraphObjectsTask;

For an example, to retrieve users asynchronously:

AzureActiveDirectoryClient activeDirectoryClient;

Task<IPagedCollection<IUser>> getGraphObjectsTask = activeDirectoryClient.Users.ExecuteAsync();

IPagedCollection<IUser> graphObjects = await getGraphObjectsTask;

Create, update and delete operations can also all be executed asynchronously, as well as in batch mode (but more about that later!).

Using LINQ to query users and paging results

Previously, creating filter queries, ordering and paging results was a challenging task requiring the construction of a filter expression.  With the new client library this is simplified through the use of the LINQ where clause.  Here are some examples:

Get users by UPN or objectId

Here’s how to search for a user by UPN (user principal name).  It returns a list, which will only have one member.

List<IUser> users = activeDirectoryClient.Users.Where(user =>

                    user.UserPrincipalName.Equals(“jon@contoso.com”)).

                    ExecuteAsync().Result.CurrentPage.ToList();

You can also search based on objectId.  ObjectId is the unique identifier for users, groups, devices, applications, and service principals – i.e. most Graph objects.  In general this unique identifier should be used for authorizing principals, so this kind of call should be relatively common in your applications:

IUser user = activeDirectoryClient.Users.GetByObjectId(uObjectId).ExecuteAsync().Result; 

Get a page of the top 4 users, ordered by display name:

List<IUser> users = activeDirectoryClient.Users.OrderBy(user =>

                   user.UserPrincipalName).Take(4).ExecuteAsync().

  result.CurrentPage.ToList();

Search for users through a people picker, and page through the results:

IUserCollection userCollection = activeDirectoryClient.Users;

IPagedCollection<IUser> searchResults = userCollection.Where(user =>

user.UserPrincipalName.StartsWith(searchString) ||

user.DisplayName.StartsWith(searchString) ||

user.GivenName.StartsWith(searchString) ||

user.Surname.StartsWith(searchString)).

ExecuteAsync().Result;

usersList = searchResults.CurrentPage.ToList();

if (usersList != null && usersList.Count > 0) {

do                
{

usersList = searchResults.CurrentPage.ToList();

foreach (IUser user in usersList)

{

Console.WriteLine(“User DisplayName: {0} UPN: {1}”,

user.DisplayName, user.UserPrincipalName);

}

searchResults = searchResults.GetNextPageAsync().Result;

} while (searchResults != null && searchResults.MorePagesAvailable);

}

Find groups starting with “US”, and page through the results:

Group retrievedGroup = new Group();

string searchString = “US”;

List<IGroup> foundGroups = null;

try

{

foundGroups = activeDirectoryClient.Groups.Where(group =>

group.DisplayName.StartsWith(searchString))

.ExecuteAsync().Result.CurrentPage.ToList();

}

catch (Exception e)

{

Console.WriteLine(“\nError getting Group {0} {1}”,

e.Message, e.InnerException != null ? e.InnerException.Message :””);

}

if (foundGroups != null && foundGroups.Count > 0)

{

retrievedGroup = foundGroups.First() as Group;

}

else

{

Console.WriteLine(“Group Not Found”);

}

Common Create, Update and Delete operations

Create:

{IEntity} entity = new {Entity}();

Then set entity properties and save it.

await activeDirectoryClient.{Entity}.Add{Entity}Async();

For example, to create a user:

IUser userToBeAdded = new User();

userToBeAdded.DisplayName = ” Demo User”;

userToBeAdded.UserPrincipalName = “demoUser@” + defaultDomain.Name;

userToBeAdded.AccountEnabled = true;

userToBeAdded.MailNickname = “DemoUser”;

userToBeAdded.PasswordProfile = new PasswordProfile

{

Password = “TempP@ssw0rd!”,

ForceChangePasswordNextLogin = true

};

userToBeAdded.UsageLocation = “US”;

await activeDirectoryClient.Users.AddUserAsync(userToBeAdded);

Update:

await {entityObject}.UpdateAsync();

To update an entity, change its properties you want to update and call UpdateAsync.

For example, to update a user:

user.City = “Updated City”;

user.Country = “New Country”;

await user.UpdateAsync();

Add a member to a group:

{groupObject}.Members.Add({entityObject} as DirectoryObject);

So for example, to update a group with a new user member:

myGroup.Members.Add(userToBeAdded as DirectoryObject);

await myGroup.UpdateAsync();

NOTE:  The same construct can be used to add users to a DirectoryRole object.  Groups and users may be added to a group, however, for now, only users can be added to a DirectoryRole. 

Delete:

await {EntityObject}.DeleteAsync();

For example, to delete a user:

await user.DeleteAsync();

Other operations

Take a look at the Graph samples on github (see links earlier in the blog) for more examples of calling the Azure AD Graph through the client library.  Below we have more details on groups, batch operations and schema extensions support. Currently differential query is not supported through the client library, and we’ll provide updates on this when it’s available.  For now you’ll need to do this by going directly to the Graph REST APIs.

Batch requests:

There are two ways batch requests can be performed: one where you “queue up” or “defer” the transactions and then execute them all at once by calling SaveChanges, and the other where you explicitly form the batch and execute. NOTE
Currently Graph API limits the number of requests to 5 in a batch.

  1. Queuing up requests:  This is good for creates, updates and deletes.  For example, if you create an entity as

activeDirectoryClient.{Entity}.Add{Entity}Async({entityObject}, true);

Then the transaction will be deferred. When you’re done creating entities, you can then execute all the deferred transactions in a single batch, by saving the changes. 

await activeDirectoryClient.Context.SaveChangesAsync(SaveChangesOptions.BatchWithIndependentOperations);

The same approach can be done for any asynchronous operations exposed by an entity (such as updates, deletes and service actions):

     2.   Form the batch and then execute: This approach is suited to querying objects in a single batch.

await activeDirectoryClient.Context.ExecuteBatchAsync(query1, query2, queryN);

For example, to get users (whose names start with “Dan”) and all groups in a batch request:

string searchString = “Dan”;

IReadOnlyQueryableSet<User> userQuery = activeDirectoryClient.DirectoryObjects.OfType<User>()

.Where(user =>

user.UserPrincipalName.StartsWith(searchString) ||

user.DisplayName.StartsWith(searchString) ||

user.GivenName.StartsWith(searchString) ||

user.Surname.StartsWith(searchString));

IReadOnlyQueryableSet<Group> groupsQuery = activeDirectoryClient.DirectoryObjects.OfType<Group>();

IBatchElementResult[] batchResult = await activeDirectoryClient.Context

.ExecuteBatchAsync(userQuery, groupsQuery).Result;            

The batch result can then be iterated through to the process response of each query.

Directory schema extensions:

Manipulating schema extensions is fully supported through the client library.  We’ll show you how to register an extension for your application.  Once registered, that extension attribute may be set and queried, just like any other entity attribute.  For more on schema extensions please see our MSDN topic on schema extensions.

Register an extension:

Firstly create the extension and then register it through your application entity.  For example, let’s register a LinkedInId extension on the user object.

ExtensionProperty linkedInUserId = new ExtensionProperty
{
     Name = “linkedInUserId”,
     DataType = “String”,
     TargetObjects = { “User” }
};

myApp.ExtensionProperties.Add(linkedInUserId);
await myApp.UpdateAsync(); 

Once updated, the extension property client side object will also be updated – the Name attribute will now contain the extension attribute’s reference name that will appear on the target object once a value is written.  We’ll use that next to set the attribute value on a user object.

Set an extension value

Here we’ll set the LinkedIn Id on a user object, using the linkedInIdUserId object from earlier:

myUser.SetExtendedProperty(linkedInUserId.Name, “dan@dan.com“);
await myUser.UpdateAsync();

Get an extension value 

You can get a object’s extension properties through a dictionary.  The general pattern is to retrieve the:

{entityObject}.GetExtendedProperties()[{keyValue}];

So for example:

string extensionValue = myUser.GetExtendedProperties()[linkedInUserId.Name]; 

Query for an object using an extension attribute value

Currently this is not supported through the client library.  We’ll update this blog with details when it’s available.

Find all registered extensions

The following query will allow you to get back all the schema extensions that have been registered in the tenant (when the tenant either consents to applications that have registered extensions) or when you instantiate service principals in your tenant from applications that register extensions.

IEnumerable<IExtensionProperty> availableExtensionProperties = activeDirectoryClient.GetAvailableExtensionPropertiesAsync(false).Result; 

Set the argument above to true if you want to get back extensions that were declared as syncing from on-premises.(through directory synchronization). You can inspect each extension property returned to find out its name, type and the target objects that it applies to.

 It’s also possible to retrieve the extensions registered by an application, by querying the application itself:

IEnumerable<IExtensionProperty> availableAppExtensions = <Application Entity>.ExtensionProperties;

So for our example:

IEnumerable<IExtensionProperty> availableAppProperties = myApp.ExtensionProperties;

Unregistering a directory extension

If you decide to unregister a registered extension, here’s how you can do it, using our example:

myApp.ExtensionProperties.Remove(linkedInUserId);

await myApp.UpdateAsync();

.Net Samples

Again, we currently have 2 samples available on github that use the new client library, and we’ll add more over time:

 

.Net Graph Client version 1.0

Graph client library version 1.0 is now deprecated, but will be supported for another 24 months from December 22nd, 2014.  We strongly encourage app developers to move to the newer v2 client library as soon as possible.

 

Graph API client library source code

We hope to make the Graph client library source code available very soon.  We’ll update this post with a link when it’s available

 

Feedback

We’d love to hear what you think about the new client library, any issues you see and any suggestions you might have for improvements or new features.

 

Thanks,

The Azure AD Graph team. 

Comments (37)

  1. Yvan Duhamel says:

    Hello, how can I search a user on properties that I don't know at compile time (so, for example, I cannot use "user.DisplayName" in Linq query)?

    I could do it in v2.0.0 using Microsoft.Azure.ActiveDirectory.GraphClient.ExpressionHelper but it doesn't work in latest versions.

    I really need this feature on my project

    Thanks!

  2. Mark Sztainbok says:

    How about some libraries for normal Java use? It shouldn't be hard to take the Android libraries and get them working with Java SE.

  3. Alessandro Alfano says:

    Hi! Please specify that the extension name after the saving becomes extension_GUID_name, so if you want to use {Entity}.GetExtendedProperties()[Name] this Name must be the complete one.

    You cannot query extension properties directly but you can get it from app.ExtensionProperties.Where(t=>t.Name.Contains("_"+Name)). Suggestion are welcome for better implementations.

    Regards,

    Alessandro

  4. Alessandro Alfano says:

    What does this mean?

    The expression (t.GetExtendedProperties().Count() > 0) is not supported

  5. Alessandro Alfano says:

    This is my code

    var myUser = client.Users.GetByObjectId(objectId).ExecuteAsync().Result;

    myUser.Members and myUser.MemberOf are always empty, should I query client as OData client (using expand)? Please provide more examples.

    Regards,

    Alessandro

  6. Dan Kershaw says:

    Hi Alessandro,

    I recommend that you take a look at our samples on github for many more scenarios that are not covered by the blog post.

    Extension attributes #1:  I'll update the blog with more explicit info on the format of the extended property.  Also please refer to the MSDN article on schema extensions.

    Extension attributes #2:  AFAIK Count is not supported by Graph API.

    Getting user members:  I'll get back to you on this.  The github console app sample does have examples of checking the user's group memberships and getting the user's group memberships.

    Cheers,

    Dan.

  7. Alessandro Alfano says:

    Hi Dan, thanks a lot!

    #1 OK, thankyou! In the post looks like you can use simple Name as a key..

    #2 My fault, did not check GraphAPI docs

    #3 If I want to get back to an IEntity from an Entity I have to cast it to IEntityFetcher and then I will be able to call GraphAPI again querying for example MemberOf/Members

    //here Members and MemberOf are empty

    var user = client.Users.GetByObjectId(objectId).ExecuteAsync().Result as User;

    //here I can get Members/MemberOf

    var groups = ((IUserFetcher)user).MemberOf.OfType<Group>().ExecuteAsync().Result.CurrentPage.ToList();

    Is it right? You can put my example in the post if you want.

    Regards,

    Alessandro

  8. Lexey says:

    Alessandro,

    Yes, your last code should work. The similar code works fine for me.

    Dan,

    Could you provide a sample how to remove a role -> user link. Initially DirectoryRole.Members collection is empty and I have found no way to populate it. So, Members.Remove(user) is useless.

  9. Alessandro Alfano says:

    Thankyou Lexey!

    Try this:

    var user = client.Users.GetByObjectId("objectId").ExecuteAsync().Result as User;

    var directoryRole = client.DirectoryRoles.GetByObjectId("objectId").Expand(t =>    t.Members).ExecuteAsync().Result as DirectoryRole;

    directoryRole.Members.Remove(user);

    directoryRole.UpdateAsync().RunSynchronously();

    With expand Members will be populated.

    Note that only one expand (lambda) is allowed but I think you can add more by string  .Expand("Property1&$expand=Property2");

    Let me know,

    Alessandro

  10. Lexey says:

    Well,

    I have invented a way to delete a link. But it looks really ugly:

    var context = adUser.GetContext();

    var entitites = context.Entities.Select(_ => _.Entity).ToList();

    var internalUser = entitites.OfType<Microsoft.Azure.ActiveDirectory.GraphClient.Internal.User>()

                            .Single(_ =&gt; _.userPrincipalName == adUser.UserPrincipalName);
    

    var internalRole = entitites.OfType<Microsoft.Azure.ActiveDirectory.GraphClient.Internal.DirectoryRole>()

                            .Single(_ =&gt; _.displayName == role.DisplayName);
    

    context.AttachLink(internalRole, "members", internalUser);

    context.DeleteLink(internalRole, "members", internalUser);

    context.SaveChanges();

    I do not think it the way it is supposed to work.

    Also, what a library user is supposed to do with the return of the context.SaveChanges()?

    And if I pass SaveChangesOptions.BatchWithIndependentOperations to the SaveChanges the web server accepts the changes but the library throws an error about an unexpected result.

  11. Lexey says:

    Alessandro,

    Thanks, but unfortunately Expand does not seem to work.

    I have tried it in the following way:

    var role = (DirectoryRole)((IDirectoryRoleFetcher)r).Expand(_ => _.Members).ExecuteAsync().ResultContextless();

    role.Members.Count is zero while the role really has member users.

    (r is the DirectoryRole,

    ResultContextless() is my own extension method doing almost the same as .Result but in the contextless await)

  12. Jason says:

    Apologies if this is covered elsewhere, but how do I get the value of a on-premise AD custom attribute that is being synced by AAD Sync? Do I need to register a extension property?

    I'm using the ActiveDirectoryClient, working with the User object.

    Thanks!

  13. Jamie says:

    I'm struggling to query appRoleAssignments for a user. It works when I call it using graphexplorer but the lirary returns an error. Any pointers ?

  14. Shalabh Mohan Shrivastava-MSFT says:

    How to retrieve the "Policy" Objects using graph client library? Please share the sample.

  15. Ah Cheng says:

    Hi, Thanks for sharing the post

    But I would like to highlight one logical error in Section

    "Search for users through a people picker, and page through the results:'

    Where the searchresult and userlist is not correctly updated.

    In your example, the LAST page is always not displayed out.

    do                

    {

     usersList = searchResults.CurrentPage.ToList();

     foreach (IUser user in usersList)

     {

      Console.WriteLine("User DisplayName: {0} UPN: {1}",

      user.DisplayName, user.UserPrincipalName);

     }

     searchResults = searchResults.GetNextPageAsync().Result;

    } while (searchResults != null && searchResults.MorePagesAvailable);

    We should swap the GetNextPageAsync().Result at the start of DO like below

    do                

    {

     searchResults = searchResults.GetNextPageAsync().Result;

     usersList = searchResults.CurrentPage.ToList();

     foreach (IUser user in usersList)

     {

      Console.WriteLine("User DisplayName: {0} UPN: {1}",

      user.DisplayName, user.UserPrincipalName);

     }

    } while (searchResults != null && searchResults.MorePagesAvailable);

    and of course before we do the DO loop, we will have to check

    if (usersList != null && usersList .Count > 0 && searchResults.MorePagesAvailable)

    {

     //DO LOOP here

    }

  16. Marco says:

    considering one of your examples about paging:

    IUserCollection userCollection = activeDirectoryClient.Users;

    IPagedCollection<IUser> searchResults = userCollection.Where(user =>

      user.UserPrincipalName.StartsWith(searchString) ||

      user.DisplayName.StartsWith(searchString) ||

      user.GivenName.StartsWith(searchString) ||

      user.Surname.StartsWith(searchString)).ExecuteAsync().Result;

    usersList = searchResults.CurrentPage.ToList();

    if (usersList != null && usersList.Count > 0) {

      do                

      {

         usersList = searchResults.CurrentPage.ToList();

      foreach (IUser user in usersList)

      {

         Console.WriteLine("User DisplayName: {0} UPN: {1}",

            user.DisplayName, user.UserPrincipalName);

      }

      searchResults = searchResults.GetNextPageAsync().Result;

      } while (searchResults != null && searchResults.MorePagesAvailable);

    }

    In these types of queries i run into a

    "Directory_ExpiredPageToken","message":{"lang":"en","value":"The specified page token value has expired and can no longer be included in your request."}

    when querying for eg. 4000 objects (groups in my case)

    • Which version of ADAL should I use in combination with this Graph Api library (v2.0.5) ?

    • And how to handle this exception properly?

  17. Hines 3 says:

    I just ran into the same error that Marco did using a very similar query… Any suggestions?

  18. John Garland says:

    Any ideas explanations why several people are getting exceptions when trying to instantiate the ActiveDirectoryClient with a token obtained from the latest ADAL library on Windows Phone platforms (8.1SL and 8.1 WinRT)?  The exception is indicating that "system.dll" can not be found.

  19. Rick Rainey says:

    The code for the Schema Extensions in this post doesn't work for me.  If I add an extension and then SetExtendedProperty for a user then the next time I run the application the extension is not there.  It's acting as if it is not persisted to Azure AD.  Yet, I don't get any errors and I have R/W permissions for the graph added to my application.  Any ideas?

  20. Rick Rainey says:

    I just realized the reason the changes are not persisting is that apparently you have to call activeDirectoryClient.Context.SaveChanges() at the end.  myApp.UpdateAsync() and user.UpdateAsync() are not sufficient.

  21. Rick Rainey says:

    I take back the last comment.  It worked one time for the User's Extended Properties but not the Application's Extended Properties.  Please update this section of the post.

  22. Austin Williams says:

    Hi guys,

    I started playing around with the ActiveDirectoryClient this week and I really like the direction this is heading. However I ran into an issue with the where clause that I am using to filter my results when using string.Contains() on the displayname of the collection of Groups. Are only .Equals, .StartsWith supported currently? Are there plans for others like .Contains, .EndsWith,  etc?

    Thanks!

  23. Alexey Korotaev says:

    Hello guys,

    I haven't found any information is Graph API Client library thread safe or not? For example, I know that it is unsafe to create one instance of ActiveDirectoryClient and call two asynchronous reads simultaneously on this instance: one call will fail with an error like "NullReferenceException". I get it with experiments. However, I cannot find a prof that I can create several instances of ActiveDirectoryClient in different threads and use them to call Graph API. Do I need to use some synchronization routines or it is safe?

  24. Dan Kershaw says:

    @Austin.  Unfortunately our filtering and search are a little limited right now.  Contains and EndsWith (and Count) are not supported.  We would like to add these capabilities in the future, but I can't give you a date right now.

  25. Josh says:

    Hey guys!

    Did y'all recently make a schema change?  Our AD client code completely broke as of this morning (3/13), and was only resolved by updating the Azure AD Client nuget package.  Thank goodness that worked, but I'm just curious to know what could have caused the break.

    Thanks!

  26. Sandeep Barre says:

    Hello, retrievedUser.UpdateAsync() runs fine, but is not working in 2.6 version of GraphClient dll meaning that If I tried to get the information I just updated on a particular user, i can't get it. I've tried several times in different ways. Can you please check if things are in place.

    Thanks much

  27. bElaie. says:

    How to remove the Role from a User?. I'm using Graph API 1.5. but I am unable to do  this in C# .NET. Anyone please??

    retrievedRole.Members.Add(retrievedUser)

    retrievedRole.Members.Remove(retrievedUser)

    retrievedRole.UpdateSync().Wait();

    Error:

    Attempt to delete a link between two objects failed because the identity of the target object of the link depends on the source object of the link.

  28. Alessandro Alfano says:

    Hi,

    var addGroup = ADClient.Groups.AddGroupAsync(group);

    …..

    …..

    addGroup.Wait();

    this brings me to endless waiting and time out, any suggestion?

  29. efonsecab says:

    I already tested it and it has been working great to list and create users, but how could I authenticate a specific user directly in code, let's say an "application user" which only the app will know about, which will be in charge of creating other users?

  30. Nandhini says:

    when I try to update the AAD user using graph client library it ended up with the following error:

    "{"odata.error":{"code":"Request_BadRequest","message":{"lang":"en","value":"Invalid value specified for property 'department' of resource 'User'."},"values":null}}"

    This is the below code which I used to update the user

    Microsoft.Azure.ActiveDirectory.GraphClient.User retrievedUser = new Microsoft.Azure.ActiveDirectory.GraphClient.User();

                  List<IUser> retrievedUsers = null;

                  retrievedUsers = ActiveDirectoryClientAttributes.activeDirectoryClient.Users

                      .Where(user => user.UserPrincipalName.Equals(userInfo.PrincipalName))

                      .ExecuteAsync().Result.CurrentPage.ToList();

                      IUser updateUser = retrievedUsers.First();

                      updateUser.DisplayName = userInfo.Description;

                      updateUser.GivenName = userInfo.GivenName;

                      updateUser.JobTitle = userInfo.JobTitle;

                      updateUser.Department = userInfo.Department == "UNSPECIFIED" ? string.Empty : userInfo.Department;

                      updateUser.PostalCode = string.Empty;

                      updateUser.State = string.Empty;

                      updateUser.City = string.Empty;

                      updateUser.Country = string.Empty;

                      updateUser.AccountEnabled = userInfo.AccountEnabled;

                      updateUser.Surname = userInfo.SurName;

                      updateUser.UpdateAsync().Wait();

    I get the same error even after i removed the below line

    updateUser.Department = userInfo.Department == "UNSPECIFIED" ? string.Empty : userInfo.Department;

    I would really appreciate if some one could help me to fix this.

    kind regards,

    Nandhini

  31. Vipin says:

    Hi

    This sample uses OPEN ID for authentication where user has to provide user and password. i am looking for an authentication solution in which user need not provide credentials and i am able to access Azure AD data based on a pre-defined account who has read-write access to AAD.

    Please provide some directions towards solution.

    Thanks.

  32. alertme says:

    Hi,

      Is it possible to Add member to a group via batch processing? If so could you please give me an example

  33. Vlad says:

    Give us a chance to get the source code, fix the issues and use the library.

  34. Robert says:

    The documentation is currently broken. You cannot add a user to an IGroup's Members collection. You must cast the group you retrieve via the API to GROUP, and you must cast the User to DirectoryObject, NOT IDirectoryObject.  

  35. Jenish zinzuvadiya says:

    When I use like following it goes into infinite execution it not returning result back.

    —————————————————————————————————————

    ActiveDirectoryClient adClient = new ActiveDirectoryClient(serviceRoot,

                         async () => await GetTokenForApplication());

                   IPagedCollection<IUser> pagedCollection = await adClient.Users.OrderBy(u=>u.UserPrincipalName).Take(5).ExecuteAsync();

                   if (pagedCollection != null)

                   {

                       do

                       {

                           List<IUser> usersList = pagedCollection.CurrentPage.ToList();

                           foreach (IUser user in usersList)

                           {

                               userList.Add((User)user);

                           }

                           pagedCollection = await pagedCollection.GetNextPageAsync();

                       } while (pagedCollection != null);

                   }

                   return userList;

  36. Efi says:

    not sure I understand correctly the LINQ async model implementation.

    when one query Azure AD graph using LINQ constructs, is the filtering done in the service side or in the client side?

    e.g

      retrievedUsers = activeDirectoryClient.Users

    .Where(user => user.OnPremisesSecurityIdentifier.Equals(searchString))

                                           .ExecuteAsync().Result.CurrentPage.ToList();      

    Will this result with retrieving the list of users in the client side and then filtering, or is it that only the relevant user will be returned to the client side.

  37. Om Shrivastava says:

    Hi

    I am using Graph API in mobile to get Thumbnai Photo of user from Azure AD but getting Error in download method  

    await user1.ThumbnailPhoto.DownloadAsync();

    like

    system.net.protocolviolationexception cannot send a content-body with this verb-type

    Invalidaoperation exception

    Please help

Skip to main content