API and OData bound actions

Completed

You've now learned how to read existing data and create or update data. You also have the possibility of running a procedure through OData. Because API is built on OData, you can use the same functionality in API and OData v4 web services.

However, you can't run any procedure on an API page. You can add an attribute [ServiceEnabled] to your procedure by using WebServiceActionContext and WebServiceActionResultCode in your procedure to set the result of the function.

To implement that function, add the function name to the URL. A small difference exists between API and OData v4 in the URL for bound actions. With OData, you would use NAV. as a prefix. With API, you would use Microsoft.NAV. as a prefix.

The URL for OData v4 would be as follows:

POST /ODataV4/Company(<companyName>)/Customers(<code>)/NAV.<functionName>

The URL for API would be as follows:

POST /api/v2.0/Company(<companyid>)/customers(<id>)/Microsoft.NAV.<functionName>

In the following example, you want to apply a template on a customer when the customer is created by using the API. The templates depend on the region that is provided as a parameter. Some logic exists in a codeunit that will retrieve the correct template and apply that template on the customer record.

[ServiceEnabled]
procedure ApplyTemplate(var actionCnxt: WebServiceActionContext; region: Text[20])
var
    CustomLogicMngt: Codeunit "Custom Logic Management";
begin
    if region = '' then
        Error('You must provide a valid region code for this function.');

    CustomLogicMngt.ApplyCustomerTemplate(Rec, region);
    actionCnxt.SetObjectType(ObjectType::Page);
    actionCnxt.SetObjectId(Page::"My Custom Customer API");
    actionCnxt.AddEntityKey(Rec.FieldNo(SystemId), Rec.SystemId);

    actionCnxt.SetResultCode(WebServiceActionResultCode::Updated);
end;

The WebServiceActionResultCode enumerator is where you can specify if a record is created or updated or the function completed with success and should return an HTTP status code of 200.

Unbound actions

The OData web services also support Unbound actions. These unbound actions are created in Codeunits and aren't linked to specific entity (therefore Unbound). Unbound actions aren't available for the API services, only for OData web services. A procedure in a codeunit published as an unbound action doesn’t need a ServiceEnabled attribute. You only need to create a public procedure and publish the codeunit as a web service.

The URL for OData v4 Unbound action would be as follows:

POST /ODataV4/{serviceName}_{procedureName}?company={companyName}

codeunit 50100 "MiscOperations"
{
    procedure Ping(input: Integer): Integer
    begin
        exit(-input);
    end;
 
    procedure Delay(delayMilliseconds: Integer)
    begin
        Sleep(delayMilliseconds);
    end;
 
    procedure GetLengthOfStringWithConfirmation(inputJson: Text): Integer
    var
        c: JsonToken;
        input: JsonObject;
    begin
        input.ReadFrom(inputJson);
        if input.Get('confirm', c) and c.AsValue().AsBoolean() = true and input.Get('str', c) then
            exit(StrLen(c.AsValue().AsText()))
        else
            exit(-1);
    end;
}

If you publish the codeunit with a service name MiscOperations, then the procedures are available with following URLs:

POST /ODataV4/MiscOperations_Ping?company=CRONUS%20USA%20Inc.

POST /ODataV4/MiscOperations_Delay?company=CRONUS%20USA%20Inc.

POST /ODataV4/MiscOperations_GetLengthOfStringWithConfirmation?company=CRONUS%20USA%20Inc.