Dynamics365 CRM - calling an Azure Function as webhook - challenge with text encoding

63 Views Asked by At

I have an Azure Function (C#, .NET 8) that gets called from a cloud-based MS Dynamics365 CRM system via a webhook, when the name of a custom entity of ours changes in Dynamics CRM.

The call works just fine, my Azure function gets called, and the POST request is made. However, I have trouble reading out the contents of the POST body.

Since I'm in a predominantly German-speaking region, many of our names will contain umlauts - ä ö ü Ä Ö Ü - and those somehow get "mangled" when the webhook is called.

This is my Azure Function (simplified):

public class MyFunction
{
    [Function("MyFunction")]
    public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestData req)
    {
        string postJson = await new StreamReader(req.Body, Encoding.UTF8).ReadToEndAsync();
 
        // handle the message that the entity has changed
    }
}   

Somewhere in that JSON that I get is the new name of the entity - unfortunately, the umlauts aren't represented properly.

When I changed one entity's name to Präsident 2024 in Dynamics, what I got in the JSON post body is:

Präsident 2024

I tried just about any encoding that I could think of that would make sense - Latin1, ASCII, UTF-32, Unicode - but nothing worked - all of them return a "garbled" new name.

Why does this happen? What encoding or what approach do I need to take to get the actual, proper new name of my Dynamics entity?

Update

This is what my input looks like in MS Dynamics:

enter image description here

What get stored into DataVerse - still looking just fine to me:

enter image description here

UPDATE #2

For @PanagiotisKanavos

Using

string postJson = await req.ReadAsStringAsync();

did not change a thing - still very much the same "mangling" (or double-encoding) of the German umlauts...

Here's the headers collection (slightly "tweaked" to protect the innocent - nothing seems to indicate anything to do with text encoding)...

Connection: Keep-Alive
Content-Length: 4667
Content-Type: application/json
Expect: 100-continue
Host: myfunction-dev.azurewebsites.net
Max-Forwards: 9
x-functions-key: HLruyEwOS2wn_al_4a8bsqM25pMGR1FpP7vZh9V6t5G6AzFuEXhFYA==
x-ms-dynamics-organization: ********.crm4.dynamics.com
x-ms-dynamics-entity-name: ambcust_tag
x-ms-dynamics-request-name: Update
x-ms-correlation-request-id: c51275a3-985d-4b5b-adb2-a375db9ab3d3
x-arr-log-id: fea83f29-a979-4e37-a6c5-0cd0f6763ebe
client-ip: 20.50.69.12:61953
disguised-host: myfunction-dev.azurewebsites.net
x-site-deployment-id: myfunction-dev
was-default-hostname: myfunction-dev.azurewebsites.net
x-forwarded-proto: https
x-appservice-proto: https
x-arr-ssl: 2048|256|CN=Microsoft Azure TLS Issuing CA 05, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US
x-forwarded-tlsversion: 1.3
x-forwarded-for: 20.50.69.12:61953, 20.50.69.12
x-original-url: /api/HandleUpdate
x-waws-unencoded-url: /api/HandleUpdate
x-ms-coldstart: 1
1

There are 1 best solutions below

1
Vivek Vaibhav Shandilya On

Thanks to @madreflection.

As I said in the comment issue is not related to function. Input is getting changed before coming to function body.

My code;

       [Function("Function1")]
       public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req)
       {
           _logger.LogInformation("C# HTTP trigger function processed a request.");
           string postJson = await new StreamReader(req.Body, Encoding.UTF8).ReadToEndAsync();

           string decoded = Encoding.UTF8.GetString(Encoding.Default.GetBytes(postJson));

           return new OkObjectResult($"{decoded}");

Input:

Präsident

OUTPUT:

Präsident