Knowledge base article sync to external portal fails due to HTML encoding

We’re syncing knowledge base articles from Dynamics 365 Sales to our customer-facing portal using Power Automate and the Web API. The flow executes successfully, but HTML content renders incorrectly on the external portal-special characters appear as encoded entities (like   instead of spaces).

Our current approach uses encodeUriComponent in Power Automate when passing article content through the Web API:

encodeUriComponent(triggerOutputs()?['body/content'])

The Web API integration works for plain text articles, but rich HTML content with formatting, links, and special characters gets double-encoded. We’ve tried content sanitization on the receiving end, but that strips necessary HTML tags. The portal displays garbled content, making articles unusable for customers. Has anyone dealt with HTML encoding issues in Web API article sync scenarios?

Let me provide a complete solution addressing all the encoding, integration, and sanitization concerns:

1. Power Automate Flow Configuration: Don’t use encodeUriComponent for HTML payloads. Instead, structure your HTTP action properly:

2. Proper JSON Escaping: If you must construct JSON manually, use Power Automate expressions correctly:

@{json(concat('{"msdyn_content":"', replace(replace(body('Get_Article')?['msdyn_content'], '"', '\"'), char(10), ' '), '"}'))}

This escapes quotes and newlines while preserving HTML tags.

3. Web API Integration Best Practices: The Web API automatically handles content encoding when you pass properly formatted JSON. The issue isn’t the API-it’s how you’re preparing the data. Use the Dataverse connector’s ‘Update a row’ action which handles all serialization:

  • Entity: knowledgearticle
  • Row ID: dynamic from trigger
  • Content field: direct reference to HTML field (no manual encoding)

4. Content Sanitization Strategy: Implement dual-layer sanitization:

Source (Dynamics): Create a pre-operation plugin on knowledgearticle Create/Update:

// Pseudocode - Sanitization steps:
1. Extract HTML content from target entity
2. Parse HTML using AngleSharp or HtmlAgilityPack
3. Allowlist tags: p, strong, em, ul, ol, li, a, h1-h6, br
4. Strip script, iframe, object, embed tags
5. Validate href attributes (no javascript: protocol)
6. Update entity with sanitized content

Destination (Portal): Before rendering, use DOMPurify or similar:

const clean = DOMPurify.sanitize(articleContent, {
  ALLOWED_TAGS: ['p', 'strong', 'em', 'ul', 'ol', 'li', 'a', 'h1', 'h2', 'h3', 'br'],
  ALLOWED_ATTR: ['href', 'target', 'class']
});

5. Handling Special Characters: The encoding issue you’re experiencing comes from treating HTML as a URL parameter. HTML content should flow through the request body as properly escaped JSON. The Web API and Dataverse connector handle this automatically-you don’t need manual encoding.

6. Testing Approach: Create test articles with:

  • Quotes and apostrophes: “test” and ‘test’
  • Special HTML entities:  , &, <
  • Line breaks and paragraphs
  • Links with query parameters:

If these render correctly in your portal, your encoding is working.

7. Error Handling: Add retry logic in Power Automate (Configure run after settings) and implement logging:

  • Log successful syncs to a Dataverse table
  • On failure, log the article ID and error details
  • Set up alerts for repeated failures

Key Takeaway: Remove all manual encoding functions (encodeUriComponent, custom escaping). Use the Dataverse connector’s native actions which handle HTML content serialization correctly. Implement content sanitization at both source and destination for security. This approach has resolved HTML encoding issues for multiple implementations I’ve worked on.


This draft is based on general Microsoft Dynamics 365 Sales knowledge. It has not been verified against your specific version and environment. Practitioners: verify the steps and share your experience below.

I’ve seen this exact issue. The problem is that encodeUriComponent is meant for URL parameters, not HTML content payloads. When you’re sending article content through the Web API, you’re double-encoding-Dynamics already handles encoding for the API response, and then Power Automate encodes it again. Try removing the encodeUriComponent wrapper and send the raw HTML directly in your POST body. The Web API will handle proper encoding automatically.

Thanks Mike! I removed encodeUriComponent, but now I’m getting 400 Bad Request errors from the Web API when articles contain quotes or line breaks. Should I be setting specific headers for HTML content? Currently using Content-Type: application/json.

The Content-Type is correct, but you need to properly escape the HTML content for JSON. In Power Automate, use the json() function to ensure proper escaping. Your compose action should look like this: json(concat(‘{“content”:"’, replace(replace(triggerOutputs()?[‘body/content’], '', ‘\’), ‘"’, ‘"’), ‘"}’)). This handles quotes and backslashes without affecting HTML tags. Also verify your portal’s content sanitization isn’t too aggressive-you need to allowlist standard HTML tags like

, , , etc.

We had similar issues and found that using the Dataverse connector in Power Automate instead of raw Web API calls handles encoding automatically. The ‘Get a row by ID’ and ‘Update a row’ actions properly serialize HTML content. You lose some low-level control, but gain reliability. Our article sync has been running flawlessly for 8 months this way. Worth considering if you don’t need custom Web API headers.

Alex, that’s interesting. We initially went with Web API for more control over error handling and retries. Are you handling HTML sanitization on the Dynamics side or portal side? We’re concerned about XSS vulnerabilities if we accept raw HTML without validation.

For XSS protection with HTML content sync, implement sanitization at both ends. In Dynamics, use a plugin to validate HTML against an allowlist before saving (prevent malicious content at source). On the portal, use a library like DOMPurify to sanitize again before rendering. This defense-in-depth approach protects against both stored XSS and any encoding issues during transit. Never trust HTML content blindly, even from your own CRM.