web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Finance | Project Operations, Human Resources, ...
Unanswered

Getting error while calling D365 custom service from Postman

(0) ShareShare
ReportReport
Posted on by 11,633

Hi All,

I have a custom service in D365 which takes List object as a parameter and performing certain logic on that. Now, I am calling this custom service from Postman to test the code. I am passing the values as follows through Postman:

{
   "_InvoiceIdList": [
      "INV600004",
      "INV601783"
   ]
}
where _InvoiceIdList is the name of the parameter in D365 custom service. Getting below error while calling custom service:
"Message""An exception occured when deserializing a parameters - Exception occurred when parsing and deserializing parameter '_InvoiceIdList' - 'Error while deserializing contract class'",
  "ExceptionType""XppServicesDeserializationException".
Can anyone please give me an idea what code needs to be written inside custom service to deserialize the parameter that is being passed from Postman ? I was just using the List object as we usually used in X++ and traversing through it. Need to know how to deserialize before I can use the values for further processing.
Thanks,
Baber.
 
I have the same question (0)
  • Martin Dráb Profile Picture
    237,976 Most Valuable Professional on at

    Can you show us the the header of your method (including attributes), please?

  • syed baber Profile Picture
    11,633 on at

    Hi Martin,

    Here is the method signature I have in X++ class:

    public List downloadInvoices(List _summaryInvoiceIdList)

       {

           System.Byte[]           bytes;

           System.IO.MemoryStream  stream;

           List                    summaryInvoiceIdList, summaryInvoiceListBytes;

           ListEnumerator          listEnumerator;

           summaryInvoiceIdList    = new List(Types::String);

           summaryInvoiceListBytes = new List(Types::AnyType);

           summaryInvoiceIdList = _summaryInvoiceIdList;

           listEnumerator = summaryInvoiceIdList.getEnumerator();

           while (listEnumerator.moveNext())

           {

               bytes = SummaryInvoiceHelper::generateSummaryInvoice(listEnumerator.current());  

               summaryInvoiceListBytes.addEnd(bytes);

           }

           return summaryInvoiceListBytes;

       }

    Trying to use the following code for deserialization, but not exactly sure if it works. Please confirm if it is the right approach:

    obj = Newtonsoft.Json.JsonConvert::DeserializeObject(_summaryInvoiceIdList);

    summaryInvoiceIdList  = obj;

    Let me know if you need further info.

    Thanks,

    Baber.

  • Martin Dráb Profile Picture
    237,976 Most Valuable Professional on at

    First of all, let me repost your code with Insert > Insert code, to make it easier to read. Please use it next time.

    public List downloadInvoices(List _summaryInvoiceIdList)
    {
    	System.Byte[]           bytes;
    	System.IO.MemoryStream  stream;
    	List                    summaryInvoiceIdList, summaryInvoiceListBytes;
    	ListEnumerator          listEnumerator;
    	summaryInvoiceIdList    = new List(Types::String);
    	summaryInvoiceListBytes = new List(Types::AnyType);
    	summaryInvoiceIdList = _summaryInvoiceIdList;
    	listEnumerator = summaryInvoiceIdList.getEnumerator();
    	while (listEnumerator.moveNext())
    	{
    		bytes = SummaryInvoiceHelper::generateSummaryInvoice(listEnumerator.current());  
    		summaryInvoiceListBytes.addEnd(bytes);
    	}
    	return summaryInvoiceListBytes;
    }

    We can also simplify it, make it even easier to follow:

    public List downloadInvoices(List _summaryInvoiceIdList)
    {
    	List summaryInvoiceListBytes = new List(Types::AnyType);
    
    	ListEnumerator listEnumerator = _summaryInvoiceIdList.getEnumerator();
    	while (listEnumerator.moveNext())
    	{
    		System.Byte[] bytes = SummaryInvoiceHelper::generateSummaryInvoice(listEnumerator.current());  
    		summaryInvoiceListBytes.addEnd(bytes);
    	}
    	return summaryInvoiceListBytes;
    }

    There was a reason why I asked you for attributes - the bug is that you didn't include attributes describing the content of the lists. If the parameter is a list of strings, you should declare this way:

    [AifCollectionType('_summaryInvoiceIdList', Types::String)

    I'm not sure about the return type - I don't think I've ever tried anything like your design. You can try the code below, but I don't really expect it to work:

    [
    	AifCollectionType('_summaryInvoiceIdList', Types::String),
    	AifCollectionType('return', Types::Class, 'System.Byte[]')
    ]
    public List downloadInvoices(List _summaryInvoiceIdList)
    {
        ...
    }

  • syed baber Profile Picture
    11,633 on at

    Thanks Martin for your detailed response. I will try that. Regarding return type, what you suggest, I should use, if I want to return Multiple values for System.Bytes[] array ?

  • Martin Dráb Profile Picture
    237,976 Most Valuable Professional on at

    If you want that particular implementation, then there is not much to do.

    But you shouldn't limit yourself to a single implementation detail and you should rather consider other ways as well. For example, what if you encode the data with base64 and return a list of strings?

    I would also consider returning a data contract objects. You currently depend on the order, e.g. you would have to remember that the second byte array is for INV601783. Using a contract class would allow you to map the IDs and data.

    You could also consider completely different designs, such as making a request and letting F&O to asynchronously generate files and putting them to a storage, where you'd take them from when ready.

    Obviously I can't really suggest a design suitable for your business scenario, because you just showed a piece of code and didn't mention the business goal.

  • syed baber Profile Picture
    11,633 on at

    Hi Martin,

    There is already a method which returns Byte array for one Invoice only and external application is consuming it. On that side, the customer's team is converting it to PDF or CSV as requested. Now, the requirement is to return multiple Byte array for multiple Invoices. I suggested the approach to generate the file in F&O, place it in blob storage and return file URL, but customer is not agreeing to that due to other issues like scanning file and other security issues.

    Regarding covnerstion to Base64, I will try this option, as this might be acceptable to customer.  Is there a direct method in X++ to convert byte array to Base64 string? After googling, I found the following method, but it is a C# implementation:

    docs.microsoft.com/.../system.convert.tobase64string

    Thanks,

    Baber.

  • Martin Dráb Profile Picture
    237,976 Most Valuable Professional on at

    You can use .NET types and method in X++. In fact, you're already doing it - System.Byte[] is such a type; you also mentioned calling Newtonsoft.Json.JsonConvert::DeserializeObject(). You want basically the same: System.Convert::ToBase64String(bytes).

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Responsible AI policies

As AI tools become more common, we’re introducing a Responsible AI Use…

Neeraj Kumar – Community Spotlight

We are honored to recognize Neeraj Kumar as our Community Spotlight honoree for…

Leaderboard > Finance | Project Operations, Human Resources, AX, GP, SL

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 449 Super User 2025 Season 2

#2
Martin Dráb Profile Picture

Martin Dráb 422 Most Valuable Professional

#3
BillurSamdancioglu Profile Picture

BillurSamdancioglu 239 Most Valuable Professional

Last 30 days Overall leaderboard

Product updates

Dynamics 365 release plans