Suporte à codificação de caracteres não Unicode em Aplicativos Lógicos do Azure

Quando você trabalha com conteúdos de texto, os Aplicativos Lógicos do Azure inferem que o texto está codificado em um formato Unicode, como UTF-8. Você pode ter problemas para receber, enviar ou processar caracteres com codificações diferentes em seu fluxo de trabalho. Por exemplo, você pode obter caracteres corrompidos em arquivos simples ao trabalhar com sistemas herdados que não são compatíveis com Unicode.

Para trabalhar com texto que tenha outra codificação de caracteres, aplique a codificação base64 ao conteúdo não Unicode. Esta etapa impede que os Aplicativos Lógicos suponham que o texto está no formato UTF-8. Em seguida, você pode converter qualquer codificação compatível com o .NET para UTF-8 usando o Azure Functions.

Essa solução funciona com fluxos de trabalho multi-locatário e de locatário único. Você também pode usar essa solução com o conector AS2.

Converter codificação de conteúdo

Primeiro, verifique se o gatilho pode identificar corretamente o tipo de conteúdo. Essa etapa garante que os Aplicativos Lógicos não presumam mais que o texto seja UTF-8.

Em gatilhos e ações que têm a propriedade Inferir Tipo de Conteúdo, selecione Não. Normalmente, você encontra essa propriedade na lista Adicionar parâmetros da operação. No entanto, se a operação não incluir a propriedade, o tipo de conteúdo será definido pela mensagem de entrada.

Esta lista mostra alguns dos conectores em que você pode desabilitar automaticamente a inferência do tipo de conteúdo:

Se você está usando o gatilho de solicitação para conteúdo text/plain, defina o parâmetro charset no cabeçalho Content-Type da chamada. Caso contrário, os caracteres poderão ficar corrompidos ou o parâmetro não corresponderá ao formato de codificação do conteúdo. Para saber mais, confira como lidar com o tipo de conteúdo text/plain.

Por exemplo, o gatilho HTTP converte o conteúdo de entrada em UTF-8 quando o cabeçalho Content-Type é definido com o parâmetro charset correto:

{
    "headers": {
        <...>
        "Content-Type": "text/plain; charset=windows-1250"
        },
        "body": "non UTF-8 text content"
}

Se você definir o cabeçalho Content-Type como application/octet-stream, você também poderá receber caracteres que não são UTF-8. Para obter mais informações, veja como lidar com o tipo de conteúdo application/octet-stream.

Conteúdo codificado em Base64

Antes de codificar o conteúdo em base64 com a cadeia de caracteres, verifique se você converteu o texto em UTF-8. Caso contrário, os caracteres poderão retornar corrompidos.

Em seguida, converta qualquer codificação com suporte do .NET para outra codificação com suporte do .NET. Examine o exemplo de código do Azure Functions ou o exemplo de código do .NET:

Dica

Para aplicativos lógicos de locatário único, você pode melhorar o desempenho e diminuir a latência, executando localmente a função de conversão.

Versão do Azure Functions

O seguinte exemplo é para o Azure Functions versão 2:

using System;
using System.IO;
using System.Text;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Azure.WebJobs.Host;
using Newtonsoft.Json;

public static class ConversionFunctionv2 {
  [FunctionName("ConversionFunctionv2")]
  public static IActionResult Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, TraceWriter log) {
    log.Info("C# HTTP trigger function processing a request.");

    Encoding inputEncoding = null;

    string requestBody = new StreamReader(req.Body).ReadToEnd();
    dynamic data = JsonConvert.DeserializeObject(requestBody);

    if (data == null || data.text == null || data.encodingInput == null || data.encodingOutput == null) {
      return new BadRequestObjectResult("Please pass text/encodingOutput properties in the input JSON object.");
    }

    Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

    try {
      string encodingInput = data.encodingInput.Value;
      inputEncoding = Encoding.GetEncoding(name: encodingInput);
    } catch (ArgumentException) {
      return new BadRequestObjectResult($"Input character set value '{data.encodingInput.Value}' is not supported. Supported values are listed at https://msdn.microsoft.com/en-us/library/system.text.encoding(v=vs.110).aspx.");
    }

    Encoding encodingOutput = null;
    try {
      string outputEncoding = data.encodingOutput.Value;
      encodingOutput = Encoding.GetEncoding(outputEncoding);
    } catch (ArgumentException) {
      return new BadRequestObjectResult($"Output character set value '{data.encodingOutput.Value}' is not supported. Supported values are listed at https://msdn.microsoft.com/en-us/library/system.text.encoding(v=vs.110).aspx.");
    }

    return (ActionResult) new JsonResult(
      value: new {
        text = Convert.ToBase64String(
          Encoding.Convert(
            srcEncoding: inputEncoding,
            dstEncoding: encodingOutput,
            bytes: Convert.FromBase64String((string) data.text)))
      });
  }
}

Versão do .NET

O seguinte exemplo é para uso com o .NET Standard e o Azure Functions versão 2:

    using System;
    using System.IO;
    using System.Text;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.Http;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Azure.WebJobs.Host;
    using Newtonsoft.Json;

    public static class ConversionFunctionNET
    {
        [FunctionName("ConversionFunctionNET")]
        public static IActionResult Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]HttpRequest req, TraceWriter log)
        {
            log.Info("C# HTTP trigger function processing a request.");

            Encoding inputEncoding = null;

            string requestBody = new StreamReader(req.Body).ReadToEnd();
            dynamic data = JsonConvert.DeserializeObject(requestBody);

            if (data == null || data.text == null || data.encodingInput == null || data.encodingOutput == null)
            {
                return new BadRequestObjectResult("Please pass text/encodingOutput properties in the input JSON object.");
            }

            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

            try
            {
                string encodingInput = data.encodingInput.Value;
                inputEncoding = Encoding.GetEncoding(name: encodingInput);
            }
            catch (ArgumentException)
            {
                return new BadRequestObjectResult($"Input character set value '{data.encodingInput.Value}' is not supported. Supported values are listed at https://msdn.microsoft.com/en-us/library/system.text.encoding(v=vs.110).aspx.");
            }

            Encoding encodingOutput = null;
            try
            {
                string outputEncoding = data.encodingOutput.Value;
                encodingOutput = Encoding.GetEncoding(outputEncoding);
            }
            catch (ArgumentException)
            {
                return new BadRequestObjectResult($"Output character set value '{data.encodingOutput.Value}' is not supported. Supported values are listed at https://msdn.microsoft.com/en-us/library/system.text.encoding(v=vs.110).aspx.");
            }

            return (ActionResult)new JsonResult(
                value: new
                {
                    text = Convert.ToBase64String(
                        Encoding.Convert(
                            srcEncoding: inputEncoding,
                            dstEncoding: encodingOutput,
                            bytes: Convert.FromBase64String((string)data.text)))
                });
        }
    }

Usando esses mesmos conceitos, você também pode enviar um conteúdo não-Unicode do fluxo de trabalho.

Conversões de conteúdo de exemplo

Neste exemplo, a cadeia de caracteres de entrada de exemplo codificada em Base64 é um nome pessoal, Héloïse, que contém caracteres acentuados

Entrada de exemplo:

{  
    "text": "SMOpbG/Dr3Nl",
    "encodingInput": "utf-8",
    "encodingOutput": "windows-1252"
}

Saída de exemplo:

{
    "text": "U01PcGJHL0RyM05s"
}

Enviar conteúdo não-Unicode

Se você precisar enviar um conteúdo não-Unicode de seu fluxo de trabalho, execute as etapas para converter o conteúdo em UTF-8 na ordem inversa. Mantenha o texto em UTF-8 tanto quanto possível em seu sistema. Em seguida, use a mesma função para converter os caracteres UTF-8 codificados em Base64 para a codificação necessária. Em seguida, aplique a decodificação de Base64 ao texto e envie seu conteúdo.

Converter conteúdos para AS2

Você também pode usar essa solução com conteúdos não-Unicode no conector do AS2 v2. Se você não converter conteúdos que passa para AS2 para UTF-8, poderá ter problemas com a interpretação de conteúdo. Esses problemas podem resultar em uma incompatibilidade com o hash do MIC entre os parceiros devido a caracteres mal interpretados.

Próximas etapas