skip to Main Content

I have made a page in Business Central, and i’m trying to access that page in an expo app.

I got authorization working, but I’m having troubles trying to access the page.

UPDATE

Here’s what’s up:

const getTimesheets = async () => {
    const timeSheetEndpoint = `https://api.businesscentral.dynamics.com/v2.0/${tenantId}/Sandbox/ODataV4/Company(${companyId})/${endpointName}`;
    var token = await fetch(
        `https://login.microsoftonline.com/${tenantId}/oauth2/token`,
        {
            method: "POST",
            headers: {
                ContentType: "application/x-www-form-urlencoded",
            },
            body:
                "grant_type=client_credentials" +
                "&scope=https://api.businesscentral.dynamics.com/.default" +
                "&client_id=" + clientId + "&client_secret=" + clientSecret,
        }
    )
        .then((result) => {
            const token = result.json();
            console.log(token);
            return token;
        })

    var json = await fetch(timeSheetEndpoint, {
        method: "Get",
        headers: {
            Authorization: "Bearer " + token,
        },
    })
        .then((response) => response.json())
        .then((json) => {
            const { value } = json;
            if (value == undefined || value == null) {
                return json;
            } else {
                return value;
            }
        })
        .catch((e) => alert("Error fetching user data", e));

    console.log(json);
    return json;
}

Here i get an unhandled promise rejection in the terminal.

[Unhandled promise rejection: TypeError: Network request failed] at node_moduleswhatwg-fetchdistfetch.umd.js:null in setTimeout$argument_0
at node_modulesreact-nativeLibrariesCoreTimersJSTimers.js:null in _allocateCallback$argument_0
at node_modulesreact-nativeLibrariesCoreTimersJSTimers.js:null in _callTimer
at node_modulesreact-nativeLibrariesCoreTimersJSTimers.js:null in callTimers
at node_modulesreact-nativeLibrariesBatchedBridgeMessageQueue.js:null in __callFunction
at node_modulesreact-nativeLibrariesBatchedBridgeMessageQueue.js:null in __guard$argument_0
at node_modulesreact-nativeLibrariesBatchedBridgeMessageQueue.js:null in __guard
at node_modulesreact-nativeLibrariesBatchedBridgeMessageQueue.js:null in callFunctionReturnFlushedQueue

Have any of you tried something similar? How did you do it?
I have tried using Postman, and it works, but I’m not quite sure how to implement it in js.

2

Answers


  1. Updated answer on 2023-03-03

    I think the unhandled promise rejection is could be caused by the then part of your token request.

    Calling result.json() returns a promise, not the actual JSON Object.

    In order to handle that promise you need an extra then:

    var token = await fetch(
        `https://login.microsoftonline.com/${tenantId}/oauth2/token`,
        {
            method: "POST",
            headers: {
                ContentType: "application/x-www-form-urlencoded",
            },
            body: body
        }
    )
    .then((result) => result.json())
    .then((token) => {
        console.log(token);
        return token;
    })
    

    Updated answer on 2023-03-02

    First of all you have a rouge commas after ContentType: "application/x-www-form-urlencoded", clientSecret, Authorization: "Bearer " + token and also after the headers object, which might make the object invalid.

    Another possible cause of the error is that the body of your token request is not url encoded.

    This can be done like this:

    var body = [];
    body.push(encodeURIComponent('grant_type') + "=" + encodeURIComponent('client_credentials'));
    body.push(encodeURIComponent('scope') + "=" + encodeURIComponent('https://api.businesscentral.dynamics.com/.default'));
    body.push(encodeURIComponent('client_id') + "=" + encodeURIComponent(clientId));
    body.push(encodeURIComponent('client_secret') + "=" + encodeURIComponent(clientSecret));
    body = body.join("&");
    

    And then you use the body variable within your fetch:

    var token = await fetch(
        `https://login.microsoftonline.com/${tenantId}/oauth2/token`,
        {
            method: "POST",
            headers: {
                ContentType: "application/x-www-form-urlencoded"
            },
            body: body
        }
    )
    

    Answer from 2023-03-01

    There are a few things that could be the cause, so you need to check each of them to see which one could solve your problem.

    Web Services

    In order for the page to be visible as an ODataV4 endpoint it needs to be created as a Web Service through the Business Central client. When you create the Web Service you give it a Service Name which will be a part of the URL.

    Make sure that the Web Service is marked as Published after creating it.

    URL

    Assuming you named your Web Service timeSheet then the final URL would look like this:

    https://api.businesscentral.dynamics.com/v2.0/{tenantId}/{environmentName}/ODataV4/Company('{companyName}')/timeSheet
    

    Note that the Company Name must be URL encoded if it contains any special characters (space, backslash etc.) and that the URL is case sensitive.

    You can copy the full URL from the Web Services page in the Business Central client.

    Login or Signup to reply.
  2. I had the same issue while trying to fetch data from NAV 2018 webservice (page type api).
    The error doesn’t say anything so at the beginning please check what is inside. You can do it as following:

    console.error(JSON.stringify(err.request?.response))

    or

    console.error(JSON.strigify(err.request))

    After that we can go further.

    In my scenario the issue was related to missing server certificate.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search