Our Thoughts

  • Elegant Software Solutions

D365 F&O, OData, Slashes, Pluses, and Double Encoding

TL;DR

When using data in OData routes such as D365 products that contain forward slashes, backslashes, or plus signs, those characters need to be double encoded, not just URL encoded.


Problem

We're building integration services into Microsoft Dynamics 365 F&O. The web API is built with OData. When operating on a resource whose primary key contains a forward slash, backslash, or plus sign, you run into route problems that URL encoding doesn't fix.


Discussion

Here's an example: ProductNumber = Product1

GET https://yourmachine.cloudax.dynamics.com/data/ProductsV2(ProductNumber='Product1')

That works just fine.

However, ProductNumber = 105E11/74N does not work.


This URL, of course, does not work because the slash interferes with the route:

GET .../data/ProductsV2(ProductNumber='105E11/74N')

However, URL encoding the ProductNumber doesn't allow it to be found either.

GET .../data/ProductsV2(ProductNumber='105E11%2F74N')

Results in:

Status: 404 Not Found
{
"Message": "No HTTP resource was found that matches the request URI '.../data/ProductsV2(ProductNumber='105E11/74N')'. No route data was found for this request."
}

It's worth noting that making a GET request using the filter parameter works just fine if you URL encode the forward slash.


For example:

GET .../data/ProductsV2?$filter=ProductSearchName eq '105E11%2f74N' 

Results in an array that only has one item, but that means that using this approach for PATCH, PUT, and DELETE just doesn't work.


Doing so results in:

Status: 400 Bad Request
{
  "error": {
    "code": "",
    "message": "An error has occurred.",
    "innererror": {
      "message": "More than one resource was found when selecting for update.",
      "type": "Microsoft.Dynamics.Platform.Integration.Services.OData.ODataArgumentException",
    }
  }
}

Solution

It turns out the solution is pretty simple. It's just not well documented. Certain characters, such as forward slashes, pluses, and backslashes need to be DOUBLE encoded. I had never heard of that until I ran into this issue.


Here's the URL that works for the example product:

PATCH ../data/ProductsV2(ProductNumber='105E11%252f74N')

Here's an example of a utility that I use when building the URLs programmatically:


public static string EncodeProductNumber(string stringToEncode)
        {
            var encodedString = HttpUtility.UrlEncode(stringToEncode).ToUpper();
            if (encodedString.Contains("%2F") || encodedString.Contains("%2B") || encodedString.Contains("%5C"))
            {
                encodedString = encodedString.Replace("%2F", "%252F");
                encodedString = encodedString.Replace("%2B", "%252B");
                encodedString = encodedString.Replace("%5C", "%255C ");
            }
            return encodedString;
        }

I hope that helps someone!


Happy coding,

Tom Hundley



49 views

© Copyright Elegant Software Solutions, Inc.  2007-2020

  • Facebook Social Icon
  • Twitter Social Icon
  • LinkedIn Social Icon
  • RSS Social Icon

Alpharetta, GA | meetus@essrocks.io | 855-449-4649