Em algum um projeto que você trabalhou ou que está trabalhando, e durante o desenvolvimento de um plugin para o Dataverse sentiu a necessidade de utilizar uma biblioteca de terceiros, ou até mesmo uma própria e que já era utilizada em outros projetos de desenvolvimentos?

Pois bem, sabemos que referenciar outras bibliotecas que nãos as do próprio .NET framework diretamente no seu projeto de plugin não é suportado, pois quando vamos registrar o assembly no Plugin Registration Tool ele apresentava o clássico onde não era possível registrar pois não encontrou a DLL que estava sendo adicionada como referência do projeto.

E como resolvíamos isso? Utilizando o famoso ILMerge! Tenho certeza que a maioria dos desenvolvedores que codificam plugin conhecem ele. Ele faz a mágica de gerar um assembly contendo as dll de terceiros dentro o mesmo arquivo. Isso permitia que o registro do assembly funcione dentro do Plugin Registration Tool.

Porém, desde 2009-2010 a própria Microsoft no seu time de suporte começou a divulgar que o uso do ILMerge para o desenvolvimentos de plugins para o Dynamics CRM/Dataverse era algo não suportado. Isso fez com que muito dos desenvolvimentos de plugin fossem modificados ou até mesmo inviabilizando devido a necessidade de uma biblioteca de terceiros.

Ficamos órfãos de poder utilizar biblioteca de terceiros até 2022 (Claro que o ILMerge não deixou de ser usado, porém não era aceito), onde surgiu então em preview e agora já está há algum tempo disponível para todos que é o: “Dependent Assembly”. Que é a maneira atualmente correta de conseguir utilizar bibliotecas externas dentro da execução de plugin.

E como funciona ele? Ele nada mais é que um projeto de class library normal, porém ao invés de registrar a DLL, registramos um pacote Nuget, isso permite que o motor interno do Datervse consiga trabalhar de maneira isolada a execução por pacotes Nuget. Por exemplo, poderia existir na sua DLL um assembly Microsoft.Office.Word que estivesse diferente de uma versão de outro plugin ou até mesmo do que a plataforma utiliza gerando conflito para o seu uso durante a execução do plugin.

Alguns pontos importantes para ficar atento ao uso do “Dependent Assembly”:

  1. Framework:
    • Os plug-ins devem ser construídos usando o .NET Framework 4.6.2. Isso garante compatibilidade e estabilidade dentro do ambiente do Power Apps, aproveitando os recursos robustos e melhorias de segurança fornecidas por essa versão do .NET.
  2. Tamanho do Assembly:
    • Os assemblies devem ter um tamanho máximo de 16 MB. Assemblies maiores podem impactar negativamente o desempenho e os tempos de implantação. Manter os assemblies enxutos garante tempos de importação mais rápidos e melhor desempenho geral das soluções do Power Apps.
  3. Assinatura de Assemblies:
    • A assinatura de assemblies de plug-ins é obrigatória, a menos que você esteja usando dependent assembly. Este processo adiciona uma camada de segurança, verificando a fonte e a integridade dos assemblies, prevenindo adulterações e garantindo que o código executado seja de uma fonte confiável.
  4. Formato do Projeto:
    • Projetos de plug-ins devem usar o formato de projeto SDK style. Esse formato moderno simplifica o gerenciamento de arquivos de projeto e dependências, proporcionando melhor compatibilidade com ferramentas de desenvolvimento modernas e sistemas de integração contínua.
  5. Pacotes NuGet:
    • Pacotes NuGet CoreAssemblies são essenciais para construir plug-ins no ambiente sandbox. Esses pacotes incluem referências e dependências necessárias, simplificando o processo de desenvolvimento e evitando conflitos.

Vamos botar a mão na massa e criar o nosso dependent assembly. Para isso vamos criar um plugin que valide o CPF do contato na criação. Porém vamos supor que você já tenha uma dll que utiliza em outros projeto e deseja reutilizar no plugin como referência.

Para iniciar vamos primeiramente baixar e instalar Power Platform CLI (pac), pois ele auxilia na criação do projeto no visual studio de maneira fácil.

Com ele instalado, vamos iniciar o projeto com a seguinte linha de comando:

pac plugin init --skip-signing

Esse comando faz com que o projeto seja criado, porém ele não vai ter a assinatura do assembly, pois não é obrigatório para registrar no plugin registration tool (ao contrário do plugin normal que é requerido). Ele vai criar o nome do projeto com o mesmo nome da pasta aonde a linha de comando foi executada.

Agora vamos abrir o nosso projeto!

Você irá ver o arquivo PluginBase.cs e Plugin1.cs. Vamos renomear o plugin1.cs para PluginValidacaoCPF.cs, ficando assim:

Agora vamos aplicar o seguinte código c#:

using MFPHelper;
using Microsoft.Xrm.Sdk;
using System;

namespace DependentAssemblies
{
    /// <summary>
    /// Plugin development guide: https://docs.microsoft.com/powerapps/developer/common-data-service/plug-ins
    /// Best practices and guidance: https://docs.microsoft.com/powerapps/developer/common-data-service/best-practices/business-logic/
    /// </summary>
    public class PluginValidacaoCPF : PluginBase
    {
        public PluginValidacaoCPF(string unsecureConfiguration, string secureConfiguration)
            : base(typeof(PluginValidacaoCPF))
        {
            // TODO: Implement your custom configuration handling
            // https://docs.microsoft.com/powerapps/developer/common-data-service/register-plug-in#set-configuration-data
        }

        // Entry point for custom business logic execution
        protected override void ExecuteDataversePlugin(ILocalPluginContext localPluginContext)
        {
            if (localPluginContext == null)
            {
                throw new ArgumentNullException(nameof(localPluginContext));
            }

            var context = localPluginContext.PluginExecutionContext;

            // The InputParameters collection contains all the data passed in the request.
            if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
            {
                Entity entity = (Entity)context.InputParameters["Target"];

                // Check if the entity has a CPF attribute
                if (entity.Attributes.Contains("mfp_cpf"))
                {
                    string cpf = entity.Attributes["mfp_cpf"].ToString();

                    // Validate the CPF
                    if (!Validador.IsValidCPF(cpf))
                    {
                        throw new InvalidPluginExecutionException("O CPF informado é inválido.");
                    }
                }
            }
        }

        
    }
}

Se você tentar compilar vai ver que está dando erro, pois a classe “Validador” não existe no assembly do plugin pois está em outro projeto então eu vou adicionar a referência do meu projeto de validação com o de plugin para ter a referência:

Código do validador:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MFPHelper
{
    public class Validador
    {
        public static bool IsValidCPF(string cpf)
        {
            int[] multiplier1 = new int[9] { 10, 9, 8, 7, 6, 5, 4, 3, 2 };
            int[] multiplier2 = new int[10] { 11, 10, 9, 8, 7, 6, 5, 4, 3, 2 };

            cpf = cpf.Trim().Replace(".", "").Replace("-", "");
            if (cpf.Length != 11)
                return false;

            for (int j = 0; j < 10; j++)
                if (j.ToString().PadLeft(11, char.Parse(j.ToString())) == cpf)
                    return false;

            string tempCpf = cpf.Substring(0, 9);
            int sum = 0;

            for (int i = 0; i < 9; i++)
                sum += int.Parse(tempCpf[i].ToString()) * multiplier1[i];

            int remainder = sum % 11;
            if (remainder < 2)
                remainder = 0;
            else
                remainder = 11 - remainder;

            string digit = remainder.ToString();
            tempCpf += digit;

            sum = 0;
            for (int i = 0; i < 10; i++)
                sum += int.Parse(tempCpf[i].ToString()) * multiplier2[i];

            remainder = sum % 11;
            if (remainder < 2)
                remainder = 0;
            else
                remainder = 11 - remainder;

            digit += remainder.ToString();
            return cpf.EndsWith(digit);
        }
    }
}

Pronto! Agora o código compila corretamente. Agora se formos olhar na basta /bin do nosso projeto de plugin vamos encontrar uma estrutura diferente:

Como podemos ver um pacote nuget é criado durante a compilação, e com esse pacote que vamos então registrar no plugin registration tool. E para abrir o Plugin Registration Tool basta utilizar Power Platform CLI, com a seguinte linha de comando:

pac tool prt

Agora com o aplicativo aberto vamos clicar em Register > Register New Package.

Uma janela surgirá para você selecionar o arquivo do seu pacote nuget que deseja adicionar. Após isso informa qual solution ele deverá pertencer.

Após isso clique em import para registrar o pacote. Após o registro podemos selecionar o modo de exibição para ver o pacotes.

Será apresentada a lista de pacotes disponíveis no seu ambiente, incluindo seu pacote que foi registrado.

Agora vamos registrar um step de plugin na criação do contato

Pronto! Agora Podemos testar se o nosso plugin que em uma referência a outra biblioteca vai rodar.

Tento criar um contato com um CPF inválido e clico em salvar.

E o resultado é o bloqueio da criação conforme esperado.

Agora como pode ver o seu plugin rodou sem problemas utilizando uma biblioteca externa.

Além de projeto e biblioteca, você pode usar sem problema outro pacotes nuget dentro dele também que irá funcionar normalmente. Então agora quando você precisar utilizar um recurso que não tem no seu assembly, basta adicionar ele como um referência do seu projeto e registar como um pacote nuget dentro do plugin registration tool. ?

Bacana né? Espero que tenham gostado é até o próximo post.

Leave a Reply

Your email address will not be published. Required fields are marked *

Protected by WP Anti Spam