Trabajar en flujos de nube con código

Todos los flujos se almacenan en Dataverse y puedes usar el Dataverse SDK para .NET o Web API para gestionarlos.

Este contenido cubre la administración de flujos incluidos en la pestaña Soluciones de Power Automate. Actualmente, la gestión de flujos bajo Mis flujos no es compatible con el código.

Interactuar con las API de Dataverse

Dataverse proporciona capacidades equivalentes usando Dataverse SDK para .NET o Web API.

¿Qué método debo usar?

El mejor método depende de la tecnología del proyecto y de las habilidades que tenga.

Si su proyecto usa .NET, le recomendamos usar el SDK. El SDK simplifica su experiencia de desarrollo al proporcionar un modelo de objetos tipificados y métodos para la autenticación.

Más información: Usar el servicio de organización

¿Cómo conectarse?

La forma de conectarse depende de si está utilizando Dataverse SDK para .NET o Web API.

Con el SDK, debe conectarse con una aplicación cliente para obtener acceso a una instancia de IOrganizationService. IOrganizationService es una interfaz que proporciona métodos que puede utilizar para interactuar con Dataverse.

Más información:

Tabla de flujos de trabajo

Los flujos en la nube se almacenan en la tabla Proceso (Flujo de trabajo) que se representa en la API web como flujo de trabajo EntityType

La siguiente tabla describe las columnas importantes en la tabla de flujo de trabajo:

Nombre lógico Type Description
category Opción Categoría del flujo. Aquí están las diferentes categorías.
0 - Flujos de trabajo de Dataverse clásicos.
1 - Diálogos de Dataverse clásicos.
2 - Reglas de negocio.
3 - Acciones clásicas de Dataverse.
4 - Flujos de proceso de negocio.
5 - Flujo moderno (flujos automatizados, instantáneos o programados).
6 - Flujos de escritorio.
clientdata String Un JSON con codificación de cadena de la definición de flujo y sus connectionReferences.
createdby Lookup Usuario que creó el flujo.
createdon Fecha y hora Fecha en que se creó el flujo.
description String Descripción del flujo proporcionada por el usuario.
ismanaged Booleano Indica si el flujo se ha instalado a través de una solución administrada.
modifiedby Lookup Último usuario que actualizó el flujo.
modifiedon Fecha y hora Última vez que se actualizó el flujo.
name String Nombre para mostrar que se le ha dado al flujo.
ownerid Lookup El usuario o el equipo propietario del flujo.
statecode Opción Estado del flujo. El estado puede ser:
0 - Borrador (Desactivado)
1 - Activado (On)
2 - Suspendido.
type Opción Indica si el flujo es un flujo en ejecución o una plantilla que se puede usar para crear más flujos.
1 - Definición,
2 - Activación
3 - Plantilla.
workflowid GUID Identificador único de un flujo de nube en todas las importaciones.
workflowidunique GUID Identificador único de esta instalación del flujo.

Nota

Con Web API, los valores de búsqueda son propiedades de navegación de valor único que se pueden expandir para obtener detalles del registro relacionado.

Las columnas de búsqueda también tienen propiedades de búsqueda de GUID correspondientes que se pueden usar en las consultas. Las propiedades de búsqueda tienen esta convención de nomenclatura: _<logical name>_value. Para el tipo de entidad de flujo de trabajo en la API web, puede hacer referencia a estas propiedades de búsqueda: _createdby_value, _modifiedby_value y _ownerid_value.

Enumerar flujos

Para recuperar una lista de flujos en la nube, puede consultar la tabla de flujo de trabajo. La consulta siguiente devuelve el primer flujo automatizado, instantáneo o programado que está activado actualmente:

Este método OutputFirstActiveFlow estático requiere un cliente autenticado que implemente IOrganizationService. Usa el 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 recuperar más registros, elimine el límite TopCount.

Output

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

Más información:

Crear de un flujo de nube

Las propiedades necesarias en los flujos automatizados, instantáneos o programados son category, name, type, primaryentity y clientdata. Use none como primaryentity en estos tipos de flujos.

Este método estático requiere un cliente autenticado que implemente IOrganizationService. Usa el 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);
}

Más información: Crear filas de tabla usando el servicio de la organización

El statecode de todos los flujos creados de esta manera se establece en 0 (Borrador o Desactivado). El flujo debe habilitarse antes de que pueda usarse.

La propiedad más importante es clientdata, que contiene el parámetro connectionReferences que el flujo usa y la propiedad definition del flujo. connectionReferences son las asignaciones a cada conexión que el flujo 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"
}

Actualizar un flujo de nube

Para actualizar un flujo, establezca solo las propiedades que desea cambiar.

Este método estático requiere un cliente autenticado que implemente IOrganizationService. Utiliza el método IOrganizationService.Update para actualizar una descripción de flujo y establecer el propietario.

/// <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);
}

Más información: Actualizar y eliminar filas de la tabla mediante el servicio de organización > Actualización básica

Eliminar un flujo de nube

Los siguientes ejemplos muestran cómo eliminar el registro de flujo de trabajo que representa un flujo en la nube.

El método DeleteCloudFlow estático elimina un registro de flujo de trabajo.

/// <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);

}

Más información: Eliminar un registro mediante el SDK

Obtener todos los usuarios con los que se comparte un flujo de nube

Utilice el mensaje RetrieveSharedPrincipalsAndAccess para obtener una lista de todos los usuarios con los que se comparte un flujo en la nube.

Con el SDK, use RetrieveSharedPrincipalsAndAccessRequest Class y con la API web use RetrieveSharedPrincipalsAndAccess Function.

Más información: Conseguir entidades de seguridad con acceso a un registro

Compartir o dejar de compartir un flujo de nube

Comparta un flujo en la nube como cualquier otro registro de Dataverse mediante el mensaje GrantAccess. Con el SDK, use la clase GrantAccessRequest y con la API web use la acción GrantAccess. Más información: Ejemplo de GrantAccess

Si desea cambiar los derechos de acceso que otorga cuando comparte un registro, utilice el mensaje ModifyAccess. Con el SDK, use la clase ModifyAccessRequest y con la API web use la acción ModifyAccess. Más información: Ejemplo de ModifyAccess

Para dejar de compartir un registro, use el mensaje RevokeAccess. Con el SDK, use la clase RevokeAccessRequest y con la API web use la acción RevokeAccess. Más información: Revocar el acceso

Exportar flujos

Cuando un flujo es parte de una solución, puede exportarlo exportando la solución que contiene el flujo mediante el mensaje ExportSolution.

El siguiente método de ejemplo estático ExportSolution utiliza ExportSolutionRequest para recuperar un byte[] que contiene el archivo ZIP de la solución no administrada con el 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 flujos

Cuando tenga un archivo ZIP de solución, puede importarlo usando el mensaje ImportSolution.

Cuando importa flujos, debe establecer los siguientes parámetros:

Nombre de la propiedad Description
OverwriteUnmanagedCustomizations Si no hay instancias existentes de estos flujos en Dataverse, esta marca se debe establecer en true para importarlos. En caso contrario, no se sobrescribirán.
PublishWorkflows Indica si los flujos de trabajo clásicos de Dataverse se activarán con la importación. Esta configuración no es válida con ningún otro tipo de flujo.
CustomizationFile Archivo ZIP con codificación en Base64 que contiene la solución.

El método de ejemplo ImportSolution estático muestra cómo importar un archivo de solución mediante la clase 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 también

Operaciones de clase de la entidad con el servicio de organización
Realizar operaciones mediante la API web
Compartir y asignar
Verificar el acceso en el código
Trabajar con soluciones con el SDK de Dataverse