Trabalhar com fluxos de cloud que utilizam código

Todos os fluxos são armazenados no Dataverse e pode usar o SDK do Dataverse para .NET ou a API Web para os gerir.

Este artigo abrange a gestão de fluxos incluídos no separador Soluções no Power Automate. Atualmente, a gestão dos fluxos em Os Meus Fluxos não são suportados com código.

Interagir com APIs do Dataverse

O Dataverse fornece capacidades equivalentes utilizando o SDK do Dataverse para .NET ou a API Web.

Que método devo utilizar?

O melhor método depende da tecnologia do projeto e das competências que tem.

Se o seu projeto utilizar .NET, recomendamos a utilização do SDK. O SDK simplifica a sua experiência de desenvolvimento fornecendo um modelo de objeto e métodos com tipo para autenticar.

Mais informações: Utilizar o serviço da Organização

Como ligar?

A forma de ligar depende se está a utilizar o SDK do Dataverse para .NET ou a API Web.

Com o SDK, precisa de ligar a uma aplicação cliente para obter acesso a uma instância IOrganizationService. IOrganizationService é uma interface que fornece métodos que pode utilizar para interagir com o Dataverse.

Mais informações:

Tabela de fluxo de trabalho

Os fluxos de cloud são armazenados na tabela Processo (Fluxo de Trabalho) representada na API Web como o EntityType do fluxo de trabalho

A tabela seguinte descreve as colunas importantes na tabela de fluxo de trabalho.

Nome Lógico Tipo Descrição
category Opção A categoria do fluxo. Eis as diferentes categorias.
0 — Fluxos de trabalho clássicos do Dataverse.
1 — Caixas de diálogo clássicas do Dataverse.
2 — Regras de negócio.
3 — Ações clássicas do Dataverse.
4 — Fluxos de processo empresarial.
5 — Fluxos Moderno (Fluxos automatizados, instantâneos ou agendados).
6 — Fluxos de ambiente de trabalho.
clientdata Cadeia (de carateres) Um JSON codificado por cadeia da definição de fluxo e da respetiva connectionReferences.
createdby Procura O utilizador que criou o fluxo.
createdon DateTime A data em que o fluxo foi criado.
description Cadeia (de carateres) A descrição inserida pelo utilizador do fluxo.
ismanaged Bool Indica se o fluxo foi instalado através de uma solução gerida.
modifiedby Procura O último utilizador que atualizou o fluxo.
modifiedon DateTime A última vez que o fluxo foi atualizado.
name Cadeia (de carateres) O nome a apresentar que deu ao fluxo.
ownerid Procura O utilizador ou a equipa proprietária do fluxo.
statecode Opção O estado do fluxo. O estado pode ser:
0 — Rascunho (Desligado)
1 — Ativado (Ligado)
2 — Suspenso.
type Opção Indica se o fluxo é um fluxo em execução ou um modelo que pode ser utilizado para criar mais fluxos.
1 — Definição,
2 — Ativação
3 — Modelo.
workflowid GUID O identificador exclusivo de um fluxo de cloud em todas as importações.
workflowidunique GUID O identificador exclusivo desta instalação do fluxo.

Nota

Com a API Web, os valores da Procura são propriedades de navegação de valor único que podem ser expandidas para obter detalhes do registo relacionado.

As colunas de procura também têm propriedades de procura GUID correspondentes que podem ser utilizadas em consultas. As propriedades de procura têm esta convenção de nomenclatura: _<logical name>_value. Para o entitytype de fluxo de trabalho na API Web, pode referenciar estas propriedades de procura: _createdby_value, _modifiedby_value e _ownerid_value.

Listar fluxos

Para obter uma lista de fluxos de cloud, pode consultar a tabela de fluxo de trabalho. A consulta que se segue devolve o primeiro fluxo automatizado, instantâneo ou agendado que está atualmente "ativo":

Este método OutputFirstActiveFlow estático necessita de um cliente autenticado que implemente o IOrganizationService. Utiliza o método IOrganizationService.RetrieveMultiple.

/// <summary>
/// Outputs the first active flow
/// </summary>
/// <param name="service">Authenticated client implementing the IOrganizationService interface</param>
public static void OutputFirstActiveFlow(IOrganizationService service)
{
   var query = new QueryExpression("workflow")
   {
         ColumnSet = new ColumnSet("category",
                                    "createdby",
                                    "createdon",
                                    "description",
                                    "ismanaged",
                                    "modifiedby",
                                    "modifiedon",
                                    "name",
                                    "ownerid",
                                    "statecode",
                                    "type",
                                    "workflowid",
                                    "workflowidunique"),
         Criteria = new FilterExpression(LogicalOperator.And)
         {
            Conditions = {
            {  new ConditionExpression(
               "category",
                     ConditionOperator.Equal,
                     5) }, // Cloud Flow
            {  new ConditionExpression(
                     "statecode",
                     ConditionOperator.Equal,
                     1) } // Active
         }
         },
         TopCount = 1 // Limit to one record
   };

   EntityCollection workflows = service.RetrieveMultiple(query);

   Entity workflow = workflows.Entities.FirstOrDefault();

   Console.WriteLine($"category: {workflow.FormattedValues["category"]}");
   Console.WriteLine($"createdby: {workflow.FormattedValues["createdby"]}");
   Console.WriteLine($"createdon: {workflow.FormattedValues["createdon"]}");
   // Description may be null
   Console.WriteLine($"description: {workflow.GetAttributeValue<string>("description")}");
   Console.WriteLine($"ismanaged: {workflow.FormattedValues["ismanaged"]}");
   Console.WriteLine($"modifiedby: {workflow.FormattedValues["modifiedby"]}");
   Console.WriteLine($"modifiedon: {workflow.FormattedValues["modifiedon"]}");
   Console.WriteLine($"name: {workflow["name"]}");
   Console.WriteLine($"ownerid: {workflow.FormattedValues["ownerid"]}");
   Console.WriteLine($"statecode: {workflow.FormattedValues["statecode"]}");
   Console.WriteLine($"type: {workflow.FormattedValues["type"]}");
   Console.WriteLine($"workflowid: {workflow["workflowid"]}");
   Console.WriteLine($"workflowidunique: {workflow["workflowidunique"]}");
}

Para obter mais registos, remova o limite TopCount.

Saída

category: Modern Flow
createdby: SYSTEM
createdon: 5/20/2020 9:37 PM
description:
ismanaged: Unmanaged
modifiedby: Kiana Anderson
modifiedon: 5/6/2023 3:37 AM
name: When an account is updated -> Create a new record
ownerid: Monica Thomson
statecode: Activated
type: Definition
workflowid: d9e875bf-1c9b-ea11-a811-000d3a122b89
workflowidunique: c17af45c-10a1-43ca-b816-d9cc352718cf

Mais informações:

Criar um fluxo de cloud

As propriedades obrigatórias para fluxos automatizados, instantâneos ou agendados são: category, name, type, primaryentity e clientdata. Utilize none como primaryentity para este tipo de fluxos.

Este método estático necessita de um cliente autenticado que implemente o IOrganizationService. Utiliza o método IOrganizationService.Create.

/// <summary>
/// Creates a cloud flow
/// </summary>
/// <param name="service">Authenticated client implementing the IOrganizationService interface</param>
/// <returns>The workflowid</returns>
public static Guid CreateCloudFlow(IOrganizationService service)
{
   var workflow = new Entity("workflow")
   {
         Attributes = {
            {"category", new OptionSetValue(5) }, // Cloud flow
            {"name", "Sample flow name"},
            {"type", new OptionSetValue(1) }, //Definition
            {"description", "This flow reads some data from Dataverse." },
            {"primaryentity", "none" },
            {"clientdata", "{\"properties\":{\"connectionReferences\":{\"shared_commondataserviceforapps\":{\"impersonation\":{},\"runtimeSource\":\"embedded\",\"connection\":{\"name\":\"shared-commondataser-114efb88-a991-40c7-b75f-2693-b1ca6a0c\",\"connectionReferenceLogicalName\":\"crdcb_sharedcommondataserviceforapps_109ea\"},\"api\":{\"name\":\"shared_commondataserviceforapps\"}}},\"definition\":{\"$schema\":\"https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#\",\"contentVersion\":\"1.0.0.0\",\"parameters\":{\"$connections\":{\"defaultValue\":{},\"type\":\"Object\"},\"$authentication\":{\"defaultValue\":{},\"type\":\"SecureObject\"}},\"triggers\":{\"manual\":{\"metadata\":{\"operationMetadataId\":\"76f87a86-89b3-48b4-92a2-1b74539894a6\"},\"type\":\"Request\",\"kind\":\"Button\",\"inputs\":{\"schema\":{\"type\":\"object\",\"properties\":{},\"required\":[]}}}},\"actions\":{\"List_rows\":{\"runAfter\":{},\"metadata\":{\"operationMetadataId\":\"9725b30f-4a8e-4695-b6fd-9a4985808809\"},\"type\":\"OpenApiConnection\",\"inputs\":{\"host\":{\"apiId\":\"/providers/Microsoft.PowerApps/apis/shared_commondataserviceforapps\",\"connectionName\":\"shared_commondataserviceforapps\",\"operationId\":\"ListRecords\"},\"parameters\":{\"entityName\":\"accounts\",\"$select\":\"name\",\"$top\":1},\"authentication\":\"@parameters('$authentication')\"}}}}},\"schemaVersion\":\"1.0.0.0\"}" }
         }
   };

   return service.Create(workflow);
}

Mais informações: Criar linhas de tabela utilizando o Serviço da Organização

O statecode de todos os fluxos criados desta forma são definidos como 0 (Rascunho ou "Desligado"). O fluxo tem de ser ativado antes de poder ser utilizado.

A propriedade mais importante é clientdata, que contém connectionReferences que o fluxo utiliza e a definição do fluxo. As connectionReferences são os mapeamentos a cada ligação que o fluxo utiliza.

{
  "properties": {
    "connectionReferences": {
      "shared_commondataserviceforapps": {
        "runtimeSource": "embedded",
        "connection": {},
        "api": { 
         "name": "shared_commondataserviceforapps" 
         }
      }
    },
    "definition": {
      "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
      "contentVersion": "1.0.0.0",
      "parameters": {
        "$connections": { "defaultValue": {}, "type": "Object" },
        "$authentication": { "defaultValue": {}, "type": "SecureObject" }
      },
      "triggers": {
        "manual": {
          "metadata": {},
          "type": "Request",
          "kind": "Button",
          "inputs": {
            "schema": { "type": "object", "properties": {}, "required": [] }
          }
        }
      },
      "actions": {
        "List_rows": {
          "runAfter": {},
          "metadata": {},
          "type": "OpenApiConnection",
          "inputs": {
            "host": {
              "apiId": "/providers/Microsoft.PowerApps/apis/shared_commondataserviceforapps",
              "connectionName": "shared_commondataserviceforapps",
              "operationId": "ListRecords"
            },
            "parameters": {
              "entityName": "accounts",
              "$select": "name",
              "$top": 1
            },
            "authentication": "@parameters('$authentication')"
          }
        }
      }
    }
  },
  "schemaVersion": "1.0.0.0"
}

Atualizar um fluxo de cloud

Para atualizar um fluxo, defina apenas as propriedades que pretende alterar.

Este método estático necessita de um cliente autenticado que implemente o IOrganizationService. Utiliza o método IOrganizationService.Update para atualizar uma descrição de fluxo e definir o proprietário.

/// <summary>
/// Updates a cloud flow
/// </summary>
/// <param name="service">Authenticated client implementing the IOrganizationService interface</param>
/// <param name="workflowid">The ID of the flow to update.</param>
/// <param name="systemuserid">The id of the user to assign the flow to.</param>
public static void UpdateCloudFlow(IOrganizationService service, Guid workflowid, Guid systemuserid) {

   var workflow = new Entity("workflow",workflowid)
   {
         Attributes = {

            {"description", "This flow will ensure consistency across systems." },
            {"ownerid", new EntityReference("systemuser",systemuserid)},
            {"statecode", new OptionSetValue(1) } //Turn on the flow.
         }
   };

   service.Update(workflow);
}

Mais informações: Atualizar e eliminar linhas de tabela utilizando a atualização Serviço da Organização > Básico

Eliminar um fluxo de cloud

Os exemplos que se seguem mostram como eliminar o registo de fluxo de trabalho que representa um fluxo de cloud.

O método DeleteCloudFlow estático elimina um registo de fluxo de trabalho.

/// <summary>
/// Deletes a workflow
/// </summary>
/// <param name="service">Authenticated client implementing the IOrganizationService interface</param>
/// <param name="workflowId">The id of the cloud flow to delete.</param>
public static void DeleteCloudFlow(IOrganizationService service, Guid workflowId) { 

service.Delete(entityName:"workflow",id: workflowId);

}

Mais informações: Eliminar um registo utilizando o SDK

Obter todos os utilizadores com quem um fluxo de cloud foi partilhado

Utilize a mensagem RetrieveSharedPrincipalsAndAccess para obter uma lista de todos os utilizadores com quem um fluxo de cloud é partilhado.

Com o SDK, use a Classe RetrieveSharedPrincipalsAndAccessRequest e, com a API Web, use a Função RetrieveSharedPrincipalsAndAccess.

Mais informações: Obter principais com acesso a um registo

Partilhar ou deixar de partilhar um fluxo de cloud

Partilhar um fluxo de cloud, como qualquer outro registo do Dataverse utilizando a mensagem GrantAccess. Com o SDK, use a Classe GrantAccessRequest e, com a API Web, use a Ação GrantAccess. Mais informações: Exemplo de GrantAccess

Se pretende alterar os direitos de acesso que concede quando partilha um registo, utilize a mensagem ModifyAccess. Com o SDK, use a Classe ModifyAccessRequest e, com a API Web, use a Ação ModifyAccess. Mais informações: Exemplo de ModifyAccess

Para deixar de partilhar um registo, utilize a mensagem RevokeAccess. Com o SDK, use a Classe RevokeAccessRequest e, com a API Web, use a Ação RevokeAccess. Mais informações: Revogar acesso

Exportar fluxos

Quando um fluxo faz parte de uma solução, pode exportá-la ao exportar a solução que contém o fluxo utilizando a mensagem ExportSolution.

O método ExportSolution estático de exemplo abaixo utiliza ExportSolutionRequest para obter um byte[] que contém o ficheiro ZIP da solução não gerida com o UniqueName especificado.

/// <summary>
/// Exports an unmanaged solution
/// </summary>
/// <param name="service">Authenticated client implementing the IOrganizationService interface</param>
/// <param name="solutionUniqueName">The uniquename of the solution.</param>
/// <returns></returns>
public static byte[] ExportSolution(
   IOrganizationService service, 
   string solutionUniqueName) 
{
   ExportSolutionRequest request = new() { 
         SolutionName = solutionUniqueName,
         Managed = false
   };

   var response = (ExportSolutionResponse)service.Execute(request);

   return response.ExportSolutionFile;
}

Importar fluxos

Quando tiver um ficheiro ZIP da solução, poderá importá-lo utilizando a mensagem ImportSolution.

Quando importa fluxos, deve definir os seguintes parâmetros:

Property name Descrição
OverwriteUnmanagedCustomizations Se existirem instâncias destes fluxos no Dataverse, este sinalizador necessita de ser definido como true para importá-los. Caso contrário, não serão substituídos.
PublishWorkflows Indica se o Dataverse clássico será ativado na importação. Esta definição não é aplicável a outros tipos de fluxos.
CustomizationFile Um ficheiro zip com codificação Base 64 que contém a solução.

O método ImportSolution estático de amostra mostra como importar um ficheiro de solução utilizando a Classe ImportSolutionRequest

/// <summary>
/// Imports a solution.
/// </summary>
/// <param name="service">Authenticated client implementing the IOrganizationService interface</param>
/// <param name="solutionFile">The byte[] data representing a solution file. </param>
public static void ImportSolution(
   IOrganizationService service, 
   byte[] solutionFile) {

   ImportSolutionRequest request = new() { 
         OverwriteUnmanagedCustomizations = true,
         CustomizationFile = solutionFile
   };

   service.Execute(request);
}

Consulte também

Operações de classes de entidades que utilizam o serviço de Organização
Executar operações utilizando a API Web
Partilhar e atribuir
Verificar acesso no código
Trabalhar com soluções utilizando o SDK do Dataverse