locked
The graph.Windows.Net service - changed this afternoon - does AAL need to be upgraded on NUGET ? RRS feed

  • Question

  • So Using the AAL library

    The property 'ObjectId' does not exist on type 'MyClass.ServiceReference1.Microsoft.WindowsAzure.ActiveDirectory.User'. Make sure to only use property names that are defined by the type.  

    So Until today - ObjectId with a Capital O - was a Guid

    now it has a lowercase o - and is a String

    I changed all my code....

    t System.Data.Services.Client.Materialization.FeedAndEntryMaterializerAdapter.TryRead()
       at System.Data.Services.Client.Materialization.FeedAndEntryMaterializerAdapter.AssertRead()
       at System.Data.Services.Client.Materialization.FeedAndEntryMaterializerAdapter.ReadEntryCore()
       at System.Data.Services.Client.Materialization.FeedAndEntryMaterializerAdapter.TryReadEntry(MaterializerEntry& entry)
       at System.Data.Services.Client.Materialization.FeedAndEntryMaterializerAdapter.<LazyReadEntries>d__0.MoveNext()
       at System.Data.Services.Client.Materialization.FeedAndEntryMaterializerAdapter.Read()
       at System.Data.Services.Client.Materialization.ODataReaderEntityMaterializer.ReadNextFeedOrEntry()
       at System.Data.Services.Client.Materialization.ODataEntityMaterializer.ReadImplementation()
       at System.Data.Services.Client.Materialization.ODataMaterializer.Read()
       at System.Data.Services.Client.MaterializeAtom.MoveNextInternal()
       at System.Data.Services.Client.MaterializeAtom.MoveNext()
       at System.Linq.Enumerable.<CastIterator>d__b1`1.MoveNext()
       at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
       at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)

    Note that I saw no mention of changes to this service

    e.g.

    http://msdn.microsoft.com/en-us/library/windowsazure/jj649347.aspx

    In the Add Service Reference dialog box, specify the address of Windows Azure AD Graph REST service (https://graph.windows.net/<your tenant domain>/$metadata), and then click Go. After the service information is downloaded, Click OK to add the service reference to the project.


    Mark Jones - Envision IT http://www.envisionit.com/

    Thursday, February 28, 2013 9:20 PM

All replies

  • Hi Mark,

    AAL only helps you to obtain an access token, which in turn allows you to call the Graph.

    When you are actually calling the Graph to query the directory AAL is no longer in the picture, what you are using there is the OData proxy. I would suggest refreshing the proxy, as you mentioned there. In the meanwhile I'll ask if what you are experiencing is an actual update or if you stumbled in an issue.

    thanks

    V.


    Vittorio [MSFT]

    Friday, March 1, 2013 8:21 AM
  • Thanks Vittorio

    I figured I would get called on blaming AAL when it wasn't at fault - but it got me a response !

    On the OData Proxy side though - it is even more confusing....

    I have a Console App in VS2012 on Windows 8 it can create a user in WAAD and retrieve them
    it was generated and working on Feb 25

    I then Switched to a different project on a different machine in VS2010 and tried to duplicate the results
    but in a dll instead of a console app.

    I was getting close, I had unit tests working for some methods, I could read ALL users, and specific users by ID, I was working on the query methods. Then all of a sudden everything started returning EndPoint Errors

    and other strange errors about types and such that It didn't recognize.

    I "Figured" that something had changed as per the breaking pending changes - and refreshed the Proxy.

    This stopped the Endpoint errors, but the user object was significantly different

    It seemed to get a lot more properties - The ObjectId changed to objectId and .Password went away

    but it doesn't work

     

    So I thought that the Console app should also be broken, and I would reproduce there

    but I was able to recompile it - without regenerating the proxy -  and it still works, no Endpoint Error.

     

    I regenerated the "New" proxy again this morning - but no significant change

    So If I Diff the Two Reference.vb files (yes VB !)

    This is the first thing I notice that wasn't in the old one
     Me.Format.LoadServiceModel = AddressOf GeneratedEdmModel.GetInstance

    I didn't see EdmModel in the Old one - in both cases we are including Microsoft.Data.Edm in the package

    and there is a service.edmx involved

    Also In the Old one

        Public ReadOnly Property Users() As Global.System.Data.Services.Client.DataServiceQuery(Of User)
                Get
                    If (Me._Users Is Nothing) Then
                        Me._Users = MyBase.CreateQuery(Of User)("Users")
                    End If
                    Return Me._Users
                End Get
            End Property

    This Users property is no longer there in the new one !

    Replaced  I suppose by <edmx:Edmx Version=""1.0"">  edm Xml (a lot of it) in the new one

     

    Now the Old Working Console app is .NET 4.5
    And the New dll is .Net 4.0 since it is in VS2010 - I am trying to integrate into an existing project, and didn't want to upgrade

     

    ??

    I would blame the difference on the .net runtimes and Visual studio Versions

    but I had it sort of working - then it stopped.

    I guess I can start again and read the packages and proxies and see what happens

     

     

     

     

     


    Mark Jones - Envision IT http://www.envisionit.com/

    Friday, March 1, 2013 3:33 PM
  • I  Tried Regenerating the Service Reference

    1) Ran Windows update to ensure all patches for .Net etc.

    2) deleted the old service reference and files

    3) add service reference

    But the Reference.vb - was not generated

    The custom tool 'DataServiceClientGenerator' failed. Data service client code-generation failed: The element 'DataService' has an attribute 'DataServiceVersion' with an unrecognized Version '3.0'..

    If I try and delete it

    The .svcmap file cannot be found. It may have been moved or deleted. To Generate a new .svcmap file, delete the service reference and add it again.

    (which is what I was trying to do !!)

    I recall seeing this before... but I can't recall what I had to do to get past it.???

    Normally there is a .datasvcmap (not a .svcmap)  a service.edmx  and Reference.vb

    In this case it is only the Reference.vb that is missing


    Mark Jones - Envision IT http://www.envisionit.com/

    Friday, March 1, 2013 7:31 PM
  • http://www.microsoft.com/en-us/download/details.aspx?id=35840

    WCF Data Services 5.3.0 RTM Tools Installer

    In VS2010 - delete the files on the disk, and then you can delete the service reference for the project


    After Reapplying the WCF Tools - the Service Reference could be regenerated successfully


    Mark Jones - Envision IT http://www.envisionit.com/

    Friday, March 1, 2013 7:46 PM
  • After all that I end up back at the same issue

    The 5.3 NuGets for net40 and the 5.3 Tools for  VS2010 - everything seems bleeding edge

     Trying to Query all users - I get the ObjectId Error - with capital "O"

    On the DirectoryDataService call

    .CreateQuery(OfUser)("Users").ToList()

     The property 'ObjectId' does not exist on type 'EIT_WAADProviders.ServiceReference1.Microsoft.WindowsAzure.ActiveDirectory.User'. Make sure to only use property names that are defined by the type.  

       at System.Data.Services.Client.Materialization.FeedAndEntryMaterializerAdapter.TryRead()
       at System.Data.Services.Client.Materialization.FeedAndEntryMaterializerAdapter.AssertRead()
       at System.Data.Services.Client.Materialization.FeedAndEntryMaterializerAdapter.ReadEntryCore()
       at System.Data.Services.Client.Materialization.FeedAndEntryMaterializerAdapter.TryReadEntry(MaterializerEntry& entry)
       at System.Data.Services.Client.Materialization.FeedAndEntryMaterializerAdapter.<LazyReadEntries>d__0.MoveNext()
       at System.Data.Services.Client.Materialization.FeedAndEntryMaterializerAdapter.Read()
       at System.Data.Services.Client.Materialization.ODataReaderEntityMaterializer.ReadNextFeedOrEntry()
       at System.Data.Services.Client.Materialization.ODataEntityMaterializer.ReadImplementation()
       at System.Data.Services.Client.Materialization.ODataMaterializer.Read()
       at System.Data.Services.Client.MaterializeAtom.MoveNextInternal()
       at System.Data.Services.Client.MaterializeAtom.MoveNext()
       at System.Linq.Enumerable.<CastIterator>d__b1`1.MoveNext()
       at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
       at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)

    Should I give up on VS2010 and .NET4  and Go VS2012 and .NET 4.5 ?   :(


    Mark Jones - Envision IT http://www.envisionit.com/

    Friday, March 1, 2013 8:56 PM
  • Shorter Stack Dump - to query for user by Email

    .CreateQuery(Of User)("Users").AddQueryOption("Mail", "'"& email.ToLower & "'").ToList()

    An error occurred while processing this request.  

    at System.Data.Services.Client.DataServiceRequest.Execute[TElement](DataServiceContext context, QueryComponents queryComponents)
       at System.Data.Services.Client.DataServiceQuery`1.Execute()
       at System.Data.Services.Client.DataServiceQuery`1.GetEnumerator()
       at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
       at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)


    Mark Jones - Envision IT http://www.envisionit.com/

    Friday, March 1, 2013 9:03 PM
  • I  Regenerated my WORKING .net 4.5 console app

    - as on .net4 - the attributes, changed case,  the .Password went away (replaced by PasswordProfile ?)

    so there are breaking changes in the graph.windows.net API

    once it compiles there is still more changes to make

    <m:code>Request_BadRequest</m:code><m:message xml:lang="en">The property 'accountEnabled' does not exist on type 'Microsoft.WindowsAzure.ActiveDirectory.User'. Make sure to only use property names that are defined by the type.</m:message></m:error>

    ctrl-kd will reformat all the case changes (.accountEnabled, .displayName etc)

    This message is coming back from the SERVER - so now the Server does not like the lowercase properties ?


    Mark Jones - Envision IT http://www.envisionit.com/

    Friday, March 1, 2013 10:20 PM
  • It seems like some changes or updates are being made.

    I'm assuming that https://graphexplorer.cloudapp.net/ is up to date, but when I try it out with demo company, all the normal query operations are missing (like "Users", "Groups", etc).

    This also means that now when I refreshed our service reference, I cannot call "Users" from DirectoryDataService anymore.

    Sunday, March 3, 2013 12:46 AM
  • Sorry to hear that you have run into these problems. We have published blog post which covers the changes that have been included in the 0.9 version here: http://blogs.msdn.com/b/aadgraphteam/archive/2013/03/03/0-9-version-of-azure-active-directory-graph-now-available.aspx . The MVC sample application has also been updated to work with 0.9. Regarding the specific questions, all property names have been changed to use Camel Casing and Password has been moved under a complex property - passwordProfile. There are a number of other changes covered in the blog post. Let us know if you are still running into problems and need help with any questions.

    Thanks,

    Srikanth


    This posting is provided "AS IS" with no warranties, and confers no rights.

    Sunday, March 3, 2013 11:04 AM
  • Sorry to hear that you have run into these problems. We have published blog post which covers the changes that have been included in the 0.9 version here: http://blogs.msdn.com/b/aadgraphteam/archive/2013/03/03/0-9-version-of-azure-active-directory-graph-now-available.aspx . The MVC sample application has also been updated to work with 0.9. Copy-Paste from the blog post for your question:

    Collections for Subtypes( users, groups etc.) missing in .Net generated proxy class and $metadata: OData does not have good support for exposing different top level collections for types belonging to the same inheritance hierarchy like directoryObjects, users, contacts etc. We tried to work around this in the service layer but this was leading to various classes of bugs. In order to have a clean service implementation, we have removed these collections from the $metadata and thus you won’t see them in the generated proxy. If you want to access the users collection, you can access them by using code like the following: return this.directoryObjects.OfType<User>() as DataServiceQuery<User>; . While we don’t support these collections( users, groups etc.) in $metadata, we do support hitting the Service with the specific collections without any problem. So the following HTTP request is still supported: https://graph.windows.net/graphdir1.onmicrosoft.com/users/Adam@GraphDir1.onmicrosoft.com. On the Service side, we rewrite the request to https://graph.windows.net/GraphDir1.onmicrosoft.com/directoryObjects/$/Microsoft.WindowsAzure.ActiveDirectory.User/ Adam@GraphDir1.onmicrosoft.com which is the same as the HTTP request produced by the OfType Linq query.

    Thanks,

    Srikanth


    This posting is provided "AS IS" with no warranties, and confers no rights.

    Sunday, March 3, 2013 11:06 AM
  • Srikanth,

    Thank you!

    The blog post is illuminating. 

    I rewrote some parts of our code, and it is gratifying to notice that all I needed to do (after updating service reference) was to update queries themselves and change data contract version so that it is part of the request uri instead of in a header. Didn't need to use your new thin helper library either, it all fit well with the existing AAL implementation.

    Everything seems to work again.

    Best regards,

    Sakari

    Sunday, March 3, 2013 8:35 PM
  • I am not having such good luck

    I am not able to get the api-version parameter to work with AAL

    e.g. if I want to query user with a given upn - using the / format insead of ('')

    notice I have the lower case user now instead of "Users"

    userQuery = String.Format("{0}/{1}", "users", user.userPrincipalName)

    .CreateQuery(Of User)(userQuery) _
      .AddQueryOption("api-version", dataContractVersion) _
      .ToList().First()

    Results in this URL

    https://graph.windows.net/pcarsontest1.onmicrosoft.com/users/adam@graphdir1.onmicrosoft.com()?api-version=0.9 

    Notice the extra () appended - by AAL ?

    An error occurred while processing this request.

     

     at System.Data.Services.Client.DataServiceRequest.Execute[TElement](DataServiceContext context, QueryComponents queryComponents)
       at System.Data.Services.Client.DataServiceQuery`1.Execute()
       at System.Data.Services.Client.DataServiceQuery`1.GetEnumerator()
       at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
       at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)

     

     Also - when Creating a NEW user, it is not clear where to put the AddQueryOption for the api-version, because I don't have a DataServiceQuery -  

    it calls .AddObject and then .SaveChanges

     

     

     

     

     


    Mark Jones - Envision IT http://www.envisionit.com/

    Monday, March 4, 2013 3:23 PM
  • I now have GetAllUsers working - I swear it magically fixed itself

    userQuery is "users" lowercase u - s on the end

    .CreateQuery(OfUser)(userQuery) _

      .AddQueryOption("api-version", dataContractVersion) _

      .ToList()

    However this is because - the () at the end works /users()?api-version=0.9

    other queries on specific items, don't like the extra () getting in there just before the ?

    e.g. /users('mjones@Domain1.onmicrosoft.com')()?api-version=0.9

    or using the new syntax also fails  /users/mjones@Domain1.onmicrosoft.com()?api-version=0.9


    Mark Jones - Envision IT http://www.envisionit.com/


    Monday, March 4, 2013 6:10 PM
  • Mark,

    I had posted a response on the Graph team blog which I have copied below. An additional thing to note is that AAL only deals with getting the Authorization token to talk to Graph. All the Linq magic happens through WCF Data Services client library. Below is the response that I posted on the team blog:

    The best way to add the api-version parameter to all your requests would be to add it in the new event called OnBuildingRequest. You do need to regenerate your proxy using WCF 5.2 toolset or later( as mentioned in this blog post). Below I have copied and pasted code from the DirectoryDataService_partial.cs file in the helper library from Sample Application. Since the sample does not use AAL, the way the token is fetched will change a little. Other than that you should be able to use this code.

          public DirectoryDataService(string tenantName, AADGraphServiceAuthenticationToken token)

               : this(new Uri("graph.windows.net/" + tenantName))

           {

               this.authenticationToken = token;

               // Register the event handler that adds the headers for HTTP requests including the Authorization header.

               this.BuildingRequest += new EventHandler<BuildingRequestEventArgs>(OnBuildingRequest);

           }

    internal void OnBuildingRequest(object sender, BuildingRequestEventArgs args)

           {

               // Add the data contract version as a query argument

               args.RequestUri = GetRequestUriWithDataContractVersion(args.RequestUri, "0.9");

               // Add an Authorization header that contains an OAuth WRAP access token to the request.

               string authzHeader = String.Format(CultureInfo.InvariantCulture, "{0}{1}{2}", authenticationToken.TokenType, " ", authenticationToken.AccessToken);

               args.Headers.Add("Authorization", authzHeader);

           }

           private static Uri GetRequestUriWithDataContractVersion(Uri origRequestUri, string apiVersion)

           {

               // Handle the api-version query argument to specify the data contract version

               NameValueCollection queryArguments = HttpUtility.ParseQueryString(origRequestUri.Query);

               if (String.IsNullOrEmpty(queryArguments["api-version"]))

               {

                   queryArguments["api-version"] = apiVersion;

               }

               UriBuilder uriBuilder = new UriBuilder(origRequestUri);

               uriBuilder.Query = queryArguments.ToString();

               return uriBuilder.Uri;

           }

    Thanks,

    Srikanth.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    Monday, March 4, 2013 6:16 PM
  • Thanks

    that helped - I refactored the SEND REQUEST headers to BUILDING REQUEST

     

    Private Sub MyBuildingRequest(sender As Object, args As BuildingRequestEventArgs)
        args.RequestUri = GetRequestUriWithDataContractVersion(args.RequestUri, dataContractVersion)

        args.RequestUri = New Uri(args.RequestUri.ToString.Replace(")()?", ")?"))

        args.Headers.Add("Authorization", GetAuthorizationHeader())

        If Not [String].IsNullOrEmpty(m_ReplicaSessionKeyHeader) Then
          args.Headers.Add("ocp-aad-session-key", m_ReplicaSessionKeyHeader)
        End If

        Dim clientRequestId As Guid = Guid.NewGuid()
        args.Headers.Add("client-request-id", clientRequestId.ToString())
    End Sub

    Notice if I find )()? in the url, I replace the extra () - this helps in the ByUsername and ByObjectID queries for sure

    and also my 0.9 contract version is now back inside the code, instead of being added to every request

    GetAuthorizationHeader is the AAL integration


    Mark Jones - Envision IT http://www.envisionit.com/

    Monday, March 4, 2013 9:20 PM