Discovery of JSON-based custom services in AX 7

If you download AX integration samples from GitHub, you’ll see (in JsonConsoleApplication project) that you can call JSON-based custom services by code like this:

var request = HttpWebRequest.Create(ClientConfiguration.Default.UriString + "api/services/UserSessionService/AifUserSessionService/GetUserSessionInfo");
request.Headers[OAuthHelper.OAuthHeader] = OAuthHelper.GetAuthenticationHeader();
request.Method = "POST";
request.GetResponse();

It will call the operation and return its return value as JSON:

{
    "$id":"1",
    "AOSLocaleName":"en-US",
    "AXLanguage":"EN-US",
    "Company":"DAT",
    "CompanyTimeZone":58,
    "CurrencyInfo": {
        "$id":"2",
        "CurrencyCode":"USD",
        "Description":"US Dollar",
        "ExchangeRate":100.0,
        "ISOCurrencyCode":"USD",
        "Prefix":"","Suffix":""
    },
    "IsSysAdmin":true,
    "UserId":"wintermute",
    "UserPreferredCalendar":0,
    "UserPreferredTimeZone":18
}

This is what happens when you use the POST method of HTTP; if you switch to GET, you’ll actually get some information about the service.

Therefore if you merely change the value of request.Method:

var request = HttpWebRequest.Create(ClientConfiguration.Default.UriString + "api/services/UserSessionService/AifUserSessionService/GetUserSessionInfo");
request.Headers[OAuthHelper.OAuthHeader] = OAuthHelper.GetAuthenticationHeader();
request.Method = "GET";
request.GetResponse();

you’ll get a very different response:

{
    "Parameters":[],
    "Return": {
        "Name":"return",
        "Type":"AifUserSessionInfo"
    }
}

You can see that the operation doesn’t expect any parameters and it returns a single object of AifUserSessionInfo type. This gives you some limited information about how to use this service.

You can also use GET requests to discover existing services and their operations.

/api/services gives you a list of all service groups:

{"ServiceGroups":[{"Name":"AxClient"},,{"Name":"UserSessionService"}]}

/api/services/UserSessionService provides a list of services in the service group:

{"Services":[{"Name":"AifUserSessionService"}]}

/api/services/UserSessionService/AifUserSessionService shows all operations of the individual service:

{
    "Operations": [
        {"Name":"ApplyTimeZone"},
        {"Name":"GetAccessRights"},
        {"Name":"GetPartitionKey"},
        {"Name":"GetPartitionKeysForUser"},
        {"Name":"GetUserSessionInfo"},
        {"Name":"IsSinglePartitionSystem"},
        {"Name":"RemoveTimeZone"}
    ]
}

Don’t forget than opening an URL in browser makes a GET request, therefore you don’t have to write any code to get this kind of information about custom services.

But maybe you would like something a bit more sophisticated, which is the topic of the next post: Open API for JSON-based custom services in AX 7.

15 Comments

  1. I have a custom service in D365 I have created that takes a class and returns a boolean. The request signature when I hit the URL of the service looks like this:

    {“Parameters”:[{“Name”:”response”,”Type”:”EmailApprovalResponse”}],”Return”:{“Name”:”return”,”Type”:”Boolean”}}

    For some reason, I cannot seem to figure out a way to have it properly parse my request. It always returns a 500 error, and my breakpoint in the service class never seems to get hit. In the debug output window, I’m seeing this:

    Exception thrown: ‘Microsoft.Dynamics.Platform.Integration.Services.Xpp.XppServicesParameterNotFoundDeserializationException’ in Microsoft.Dynamics.Platform.Integration.Services.Xpp.dll
    The thread 0x1d48 has exited with code 0 (0x0).
    The thread 0x79c has exited with code 0 (0x0).
    Exception thrown: ‘Microsoft.Dynamics.Platform.Integration.Services.Xpp.XppServicesDeserializationException’ in Microsoft.Dynamics.Platform.Integration.Services.Xpp.dll

    So, I’m apparently not calling it properly for it to know it got the proper JSON parameter data. Can you provide a simple example of how that should be done? Or some clues as to what I’m missing?

  2. How can u call like the service UserSessionService/AifUserSessionSevice/RemoveTimeZone?
    This service uses two parameters , how do use these parameters in your program who consumes the service?

  3. How do we send failure response from AX to the caller.
    The caller here is consuming D365 json based custom service.

  4. var request = HttpWebRequest.Create(ClientConfiguration.Default.UriString + “api/services/UserSessionService/AifUserSessionService/GetUserSessionInfo”);
    request.Headers[OAuthHelper.OAuthHeader] = OAuthHelper.GetAuthenticationHeader();
    request.Method = “POST”;

    I use this request but ı dont understand where we find company code in this main code.

      • Martin Dráb

        The Real Person!

        Author Martin Dráb acts as a real person and passed all tests against spambots. Anti-Spam by CleanTalk.

        There is nothing like that. If you want a parameter for the company, add it to your data contract and then use it (e.g. changeCompany()) inside the method.

  5. Hi Martin,

    Thanks for sharing this useful information. I am working on web services integration where the consumer of web services is BizTalk and when I am exposing my services for them they are having an issue consuming it because of the special character $ added to the response.

    {
    “$id”:”1″,

    Is there any way to remove this $ character from the response.

    • Martin Dráb

      The Real Person!

      Author Martin Dráb acts as a real person and passed all tests against spambots. Anti-Spam by CleanTalk.

      Assuming that you’re using a data contract class, decorate the class with [Newtonsoft.Json.JsonObjectAttribute(IsReference = false)].

  6. Hi Martin,

    I am struggling of find out access “api/services/UserSessionService/AifUserSessionService/GetUserSessionInfo/”. Always facing 401 unauthorized error message. I can get the token without error and have tried also in postman and it was success. But for C# code (using code from github), no luck. In C# code, i am using HttpClient, HttpWebRequest, WebRequest, all of them show same error. Can you please help me, what is the step i missed ?

Comments are closed.