Monday, November 2, 2026

Custom services in d365fo

 In this blog we see how to develop custom services in d365fo

Mainly we need to develop

1) Request class

2) Response class 

3) service class 

4) service object

5) servicegroup object

Note:-Its not mandatory to have every time request class or response class it depends on the requirement, Sometimes we create multiple Request classes and multiple Response class if we have line to loop then we pass in a list with class attribute.

Here we see a scenario with Request class , Response class

I  am here considering Purchase order information when we pass a purchid and dataareaid

classes:-

PurchaseorderHeaderResponseContract

PurchaseorderLineResponseContract

PurchaseorderRequestContract

PurchaseorderService

Objects

1) Service

2) service group

Code:-

1) PurchaseorderRequestContract

[DataContractAttribute]

 class PurchaseorderRequestContract

{

    public str purchid;

    public str dataAreaId;


    [DataMember("PurchId")]

    public str parmPurchId(str _purchid = purchid)

    { 

        purchid = _purchid;

        return purchid;

    }


    [DataMember("DataAreaId")]

    public str parmDataAreaId(str _dataAreaId = dataAreaId)

    {

        dataAreaId = _dataAreaId;

        return dataAreaId;

    }


}

2) PurchaseorderHeaderResponseContract


[DataContractAttribute]

class PurchaseorderHeaderResponseContract

{

    public str purchid;

    public str vendoraccount;

    public str vendorname;

    List purchlines;


    [DataMember("PurchId")]

    public str parmPurchId(str _purchid = purchid)

    {

        purchid = _purchid;

        return purchid;

    }


    [DataMember("Vendoraccount")]

    public str parmVendoraccount(str _vendoraccount = vendoraccount)

    {

        vendoraccount = _vendoraccount;

        return vendoraccount;

    }


    [DataMember("Vendorname")]

    public str parmVendorname(str _vendorname = vendorname)

    {

        vendorname = _vendorname;

        return vendorname;

    }


    [DataMemberAttribute('Purchlines'),

     AifCollectionTypeAttribute(

        '_purchlines',

        Types::Class,

        classStr(PurchaseorderLineResponseContract)),

     AifCollectionTypeAttribute(

        'return',

        Types::Class,

        classStr(PurchaseorderLineResponseContract))]

    public List parmPurchlines(List _purchlines = purchlines)

    {

        purchlines = _purchlines;

        return purchlines;

    }


}

3)PurchaseorderLineResponseContract

[DataContractAttribute]

 class PurchaseorderLineResponseContract

{

    public str purchid;

    public str lineNumber;

    public str itemId;

    public str lineAmount;

   


    [DataMember("PurchId")]

    public str parmPurchId(str _purchid = purchid)

    {

        purchid = _purchid;

        return purchid;

    }


    [DataMember("LineNumber")]

    public str parmLineNumber(str _lineNumber = lineNumber)

    {

        lineNumber = _lineNumber;

        return lineNumber;

    }


    [DataMember("ItemId")]

    public str parmItemId(str _itemId = itemId)

    {

        itemId = _itemId;

        return itemId;

    }


    [DataMember("LineAmount")]

    public str parmLineAmount(str _lineAmount = lineAmount)

    {

        lineAmount = _lineAmount;

        return lineAmount;

    }


}

4) PurchaseorderService

class PurchaseorderService

{

    public PurchaseorderHeaderResponseContract purchaseorderinfo(PurchaseorderRequestContract _purchaseorderRequestContract)

    {

        PurchaseorderHeaderResponseContract purchaseorderHeaderResponseContract=new PurchaseorderHeaderResponseContract();

        PurchaseorderLineResponseContract purchaseorderLineResponseContract;


        str                    purchid = _purchaseorderRequestContract.parmPurchId();

        str                    dataareaid = _purchaseorderRequestContract.parmDataAreaId();

        PurchTable             purchTable;

        PurchLine              purchLine;

        List                   purchlines=new List(Types::Class);


        select  firstonly crosscompany purchTable

            where purchTable.PurchId == purchid

            && purchTable.DataAreaId == dataareaid;


        purchaseorderHeaderResponseContract.parmPurchId(purchTable.PurchId);

        purchaseorderHeaderResponseContract.parmVendoraccount(purchTable.OrderAccount);

        purchaseorderHeaderResponseContract.parmVendorname(purchTable.PurchName);

        

        while select crosscompany purchLine

            where purchLine.PurchId == purchid

            && purchLine.DataAreaId == dataareaid

        {

            purchaseorderLineResponseContract=new PurchaseorderLineResponseContract();

            purchaseorderLineResponseContract.parmPurchId(purchLine.PurchId);

            purchaseorderLineResponseContract.parmLineNumber(any2Str(purchLine.LineNumber));

            purchaseorderLineResponseContract.parmItemId(purchLine.ItemId);

            purchaseorderLineResponseContract.parmLineAmount(any2Str(purchLine.LineAmount));

           


            purchlines.addEnd(purchaseorderLineResponseContract);

        }

        purchaseorderHeaderResponseContract.parmPurchlines(purchlines);


        return purchaseorderHeaderResponseContract;

    }


}

Now create a service object and service group and give classname, methodname 

To test generally go with Postman

and API link will be:-

generally 

D365url/api/services/ServiceGroup/Service/method


sample:-

https://usnconeboxax1aos.cloud.onebox.dynamics.com/api/services/PruchaseorderServiceGroup/PurchaseorderService/purchaseorderinfo


Note to test in postman one need appregistration that you can follow as below

Inside D365FO with Mani: Odata

Add a attchment for docuref

 Scenario :-

I have case where I need to attach base64(huge string which is convert from file) through custom services

>>So in the pam methods I will receive the string .

>> And code to attachment in below

Code:-

Docuref docuref;

 str fileName="test.pdf";

str notes="tesing";

str base64="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

using (System.IO.MemoryStream Stream = new System.IO.MemoryStream(System.Convert::FromBase64String(base64)))

{ 

   docuref=DocumentManagement::attachFile(tableNum(Tablename),Table.RecId,Table.DataAreaId,DocuType::typeFile(),Stream, System.IO.Path::GetFileName(fileName),System.Web.MimeMapping::GetMimeMapping(fileName), System.IO.Path::GetFileNameWithoutExtension(fileName),notes);

}

If you stream file we can directly pass in the above logic.

Custom services in d365fo

 In this blog we see how to develop custom services in d365fo Mainly we need to develop 1) Request class 2) Response class  3) service class...