Search code examples
javascriptodatadynamics-crm-2013dynamics-crm-2016

oData expand query not working on SystemUserRolesSet


I'm trying to get the current user's roles, and the data about said roles in one query (as opposed to using Xrm.Page.context.getUserRoles and then looping through all the results and querying the endpoint for each contained role using its ID).

I'm using Microsoft XRM tools (in CRM 2016) and the query it generates looks legit:

xrmservices/2011/OrganizationData.svc/SystemUserRolesSet?$select=systemuserroles_association/Name&$expand=systemuserroles_association&$filter=SystemUserId%20eq%20guid%27436CD5A4-FD15-E611-80C1-00155D7B5806%27

If I look at the class SystemUserRole generated by CrmSvcUtil, there seems to be such a property (systemuserroles_association) but it looks like the SVC endpoint isn't using the same class definition.

Type 'Microsoft.Crm.Sdk.Data.Services.SystemUserRoles' does not have a property named 'systemuserroles_association'.

Any ways of pulling this off ? I'd like for it to work so as to reduce client calls to the endpoint.


Solution

  • Two easy options here:

    Query for all role ids in one call

    Take the results of Xrm.Page.context.getUserRoles and generate an OR query like this: RoleSet?$select=Name,BusinessUnitId,RoleId&$orderby=Name&$filter=RoleId%20eq%20%28guid%27cb269f84-e19d-e011-b66c-00155db528b6%27%29%20or%20RoleId%20eq%20%28guid%27fcbd7757-bfa5-e511-80d4-6c3be5a8fa14%27%29

    Unencoded for easier reading: XRMServices/2011/OrganizationData.svc/RoleSet?$select=Name,BusinessUnitId,RoleId&$orderby=Name&$filter=RoleId eq (guid'cb269f84-e19d-e011-b66c-00155db528b6') or RoleId eq (guid'fcbd7757-bfa5-e511-80d4-6c3be5a8fa14')

    Pass Fetch

    You can pass this fetch query to the web api:

    <fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true">
      <entity name="role">
        <attribute name="name" />
        <attribute name="businessunitid" />
        <attribute name="roleid" />
        <order attribute="name" descending="false" />
        <link-entity name="systemuserroles" from="roleid" to="roleid" visible="false" intersect="true">
          <link-entity name="systemuser" from="systemuserid" to="systemuserid" alias="ac">
            <filter type="and">
              <condition attribute="systemuserid" operator="eq-userid" />
            </filter>
          </link-entity>
        </link-entity>
      </entity>
    </fetch>
    

    Here's what it looks like:

    var req = new XMLHttpRequest();
    req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v8.0/roles?fetchXml=%3Cfetch%20version%3D%221.0%22%20output-format%3D%22xml-platform%22%20mapping%3D%22logical%22%20distinct%3D%22true%22%3E%3Centity%20name%3D%22role%22%3E%3Cattribute%20name%3D%22name%22%20%2F%3E%3Cattribute%20name%3D%22businessunitid%22%20%2F%3E%3Cattribute%20name%3D%22roleid%22%20%2F%3E%3Corder%20attribute%3D%22name%22%20descending%3D%22false%22%20%2F%3E%3Clink-entity%20name%3D%22systemuserroles%22%20from%3D%22roleid%22%20to%3D%22roleid%22%20visible%3D%22false%22%20intersect%3D%22true%22%3E%3Clink-entity%20name%3D%22systemuser%22%20from%3D%22systemuserid%22%20to%3D%22systemuserid%22%20alias%3D%22ac%22%3E%3Cfilter%20type%3D%22and%22%3E%3Ccondition%20attribute%3D%22systemuserid%22%20operator%3D%22eq-userid%22%20%2F%3E%3C%2Ffilter%3E%3C%2Flink-entity%3E%3C%2Flink-entity%3E%3C%2Fentity%3E%3C%2Ffetch%3E", true);
    req.setRequestHeader("OData-MaxVersion", "4.0");
    req.setRequestHeader("OData-Version", "4.0");
    req.setRequestHeader("Accept", "application/json");
    req.setRequestHeader("Prefer", "odata.include-annotations=\"OData.Community.Display.V1.FormattedValue\"");
    req.onreadystatechange = function () {
        if (this.readyState === 4) {
            req.onreadystatechange = null;
            if (this.status === 200) {
                var results = JSON.parse(this.response);
            }
            else {
                alert(this.statusText);
            }
        }
    };
    req.send();
    

    I used the CRM Rest Builder to generate that JS.