Azure Service Bus biblioteca cliente para .NET: versión 7.16.2

Azure Service Bus permite crear aplicaciones que aprovechen los patrones de mensajería asincrónica mediante un servicio de alta confianza para intermediar mensajes entre productores y consumidores. Azure Service Bus proporciona mensajería flexible, asincrónica entre el cliente y el servidor, junto con la mensajería estructurada primero en entrada, primero en salir (FIFO) y funcionalidades de publicación y suscripción con enrutamiento complejo. Si desea obtener más información sobre Azure Service Bus, puede que desee revisar: ¿Qué es Azure Service Bus?

Use la biblioteca cliente para Azure Service Bus para:

  • Transferir datos empresariales: aproveche la mensajería para un intercambio duradero de información, como ventas o pedidos de compra, diarios o movimientos de inventario.

  • Desacoplar aplicaciones: mejorar la confiabilidad y escalabilidad de las aplicaciones y los servicios, lo que reduce los remitentes y receptores de la necesidad de estar en línea al mismo tiempo.

  • Controlar cómo se procesan los mensajes: admiten los consumidores tradicionales de la competencia para los mensajes mediante colas o permiten a cada consumidor su propia instancia de un mensaje mediante temas y suscripciones.

  • Implementación de flujos de trabajo complejos: las sesiones de mensajes admiten escenarios que requieren el orden de mensajes o el aplazamiento de mensajes.

Código | fuentePaquete (NuGet) | Documentación | de referencia de APIDocumentación | del productoGuía de migración (Microsoft.Azure.ServiceBus) | Guía de migración (WindowsAzure.ServiceBus) | Guía de solución de problemas

Introducción

Requisitos previos

  • Suscripción de Microsoft Azure: Para usar los servicios de Azure, incluida Azure Service Bus, necesitará una suscripción. Si no tiene una cuenta de Azure existente, puede registrarse para obtener una evaluación gratuita o usar las ventajas del suscriptor de MSDN al crear una cuenta.

  • Espacio de nombres de Service Bus: Para interactuar con Azure Service Bus, también deberá tener un espacio de nombres disponible. Si no está familiarizado con la creación de recursos de Azure, puede seguir la guía paso a paso para crear un espacio de nombres de Service Bus mediante el Azure Portal. Allí también puede encontrar instrucciones detalladas para usar la CLI de Azure, Azure PowerShell o plantillas de Azure Resource Manager (ARM) para crear una entidad de Service Bus.

  • C# 8.0: La biblioteca cliente de Azure Service Bus usa nuevas características que se introdujeron en C# 8.0. Para aprovechar la sintaxis de C# 8.0, se recomienda compilar con el SDK de .NET Core 3.0 o posterior con una versión de lenguaje de .latest

    Los usuarios de Visual Studio que deseen aprovechar al máximo la sintaxis de C# 8.0 tendrán que usar Visual Studio 2019 o posterior. Visual Studio 2019, incluida la edición gratuita Community, se puede descargar aquí. Los usuarios de Visual Studio 2017 pueden aprovechar la sintaxis de C# 8 haciendo uso del paquete NuGet Microsoft.Net.Compilers y estableciendo la versión del lenguaje, aunque es posible que la experiencia de edición no sea ideal.

    Todavía puede usar la biblioteca con versiones anteriores del lenguaje C#, pero tendrá que administrar miembros asincrónicos enumerables y asincrónicos descartables manualmente en lugar de beneficiarse de la nueva sintaxis. Puede seguir teniendo como destino cualquier versión de marco compatible con el SDK de .NET Core, incluidas las versiones anteriores de .NET Core o .NET Framework. Para obtener más información, vea: cómo especificar marcos de destino.

    Nota importante: Para compilar o ejecutar los ejemplos y los ejemplos sin modificaciones, el uso de C# 8.0 es obligatorio. Todavía puede ejecutar los ejemplos si decide ajustarlos para otras versiones de lenguaje.

Para crear rápidamente los recursos de Service Bus necesarios en Azure y recibir una cadena de conexión para ellos, puede implementar nuestra plantilla de ejemplo haciendo clic en:

Implementación en Azure

Instalar el paquete

Instale la biblioteca cliente de Azure Service Bus para .NET con NuGet:

dotnet add package Azure.Messaging.ServiceBus

Autenticar el cliente

Para que la biblioteca cliente de Service Bus interactúe con una cola o tema, deberá comprender cómo conectarse y autorizarla. Los medios más fáciles para hacerlo es usar una cadena de conexión, que se crea automáticamente al crear un espacio de nombres de Service Bus. Si no está familiarizado con las directivas de acceso compartido en Azure, puede seguir la guía paso a paso para obtener una cadena de conexión de Service Bus.

Una vez que tenga un cadena de conexión, puede autenticar al cliente con él.

// Create a ServiceBusClient that will authenticate using a connection string
string connectionString = "<connection_string>";
await using var client = new ServiceBusClient(connectionString);

Para ver cómo autenticarse mediante Azure.Identity, vea este ejemplo.

Para obtener ejemplos de cómo autenticarse para una aplicación de ASP.NET Core, vea este ejemplo.

Para ver cómo iniciar la conexión con un punto de conexión personalizado, vea este ejemplo.

Conceptos clave

Una vez que haya inicializado un ServiceBusClient, puede interactuar con los tipos de recursos principales dentro de un espacio de nombres de Service Bus, de los cuales varios pueden existir y en qué transmisión real de mensajes tiene lugar, el espacio de nombres a menudo actúa como contenedor de aplicaciones:

  • Cola: permite enviar y recibir mensajes. A menudo se usa para la comunicación de punto a punto.

  • Tema: en lugar de las colas, los temas son más adecuados para escenarios de publicación o suscripción. Se puede enviar un tema a , pero requiere una suscripción, de la que puede haber varios en paralelo, para consumir.

  • Suscripción: mecanismo para consumir desde un tema. Cada suscripción es independiente y recibe una copia de cada mensaje enviado al tema. Las reglas y filtros se pueden usar para adaptar los mensajes que recibe una suscripción específica.

Para obtener más información sobre estos recursos, consulte ¿Qué es Azure Service Bus?.

Para interactuar con estos recursos, debe estar familiarizado con los siguientes conceptos del SDK:

  • Un cliente de Service Bus es la interfaz principal para los desarrolladores que interactúan con la biblioteca cliente de Service Bus. Actúa como puerta de enlace desde la que se producirá toda la interacción con la biblioteca.

  • Un remitente de Service Bus tiene como ámbito una cola o tema concretos y se crea mediante el cliente de Service Bus. El remitente le permite enviar mensajes a una cola o tema. También permite programar mensajes para que estén disponibles para la entrega en una fecha especificada.

  • Un receptor de Service Bus tiene como ámbito una determinada cola o suscripción y se crea mediante el cliente de Service Bus. El receptor le permite recibir mensajes de una cola o suscripción. También permite que los mensajes se resuelvan después de recibirlos. Hay cuatro maneras de establecer mensajes:

    • Completado: hace que el mensaje se elimine de la cola o tema.
    • Abandonar: libera el bloqueo del receptor en el mensaje que permite que otros receptores reciban el mensaje.
    • Aplazar: aplaza el mensaje de recibirse por medios normales. Para recibir mensajes diferidos, es necesario conservar el número de secuencia del mensaje.
    • DeadLetter: mueve el mensaje a la cola de mensajes fallidos. Esto impedirá que se vuelva a recibir el mensaje. Para recibir mensajes de la cola de mensajes fallidos, se necesita un receptor con ámbito en la cola de mensajes fallidos.
  • Un receptor de sesión de Service Bus tiene como ámbito una determinada cola o suscripción habilitada para sesión y se crea mediante el cliente de Service Bus. El receptor de sesión es casi idéntico al receptor estándar, con la diferencia de que las operaciones de administración de sesión se exponen que solo se aplican a las entidades habilitadas para sesión. Estas operaciones incluyen la obtención y configuración del estado de sesión, así como la renovación de bloqueos de sesión.

  • Un procesador de Service Bus tiene como ámbito una cola o suscripción determinada y se crea mediante el cliente de Service Bus. ServiceBusProcessor se puede considerar como una abstracción en torno a un conjunto de receptores. Usa un modelo de devolución de llamada para permitir que el código se especifique cuando se recibe un mensaje y cuando se produce una excepción. Ofrece la finalización automática de los mensajes procesados, la renovación automática del bloqueo de mensajes y la ejecución simultánea de controladores de eventos especificados por el usuario. Debido a su conjunto de características, debe ser la herramienta ir a para escribir aplicaciones que reciben de entidades de Service Bus. ServiceBusReceiver se recomienda para escenarios más complejos en los que el procesador no puede proporcionar el control específico que se puede esperar al usar ServiceBusReceiver directamente.

  • Un procesador de sesión de Service Bus tiene como ámbito una determinada cola o suscripción habilitada para sesión y se crea mediante el cliente de Service Bus. El procesador de sesión es casi idéntico al procesador estándar, con la diferencia de que las operaciones de administración de sesión se exponen, lo que solo se aplica a las entidades habilitadas para sesión.

Para obtener más conceptos y una explicación más detallada, consulte: Características avanzadas de Service Bus.

Duración del cliente

Los ServiceBusClient, remitentes, receptores y procesadores son seguros para almacenar en caché y usar como singleton durante la vigencia de la aplicación, que es el procedimiento recomendado cuando se envían o reciben mensajes con regularidad. Son responsables de la administración eficaz de la red, la CPU y el uso de memoria, trabajando para mantener el uso bajo durante períodos de inactividad.

Estos tipos son descartables y llaman DisposeAsync a o CloseAsync para asegurarse de que los recursos de red y otros objetos no administrados se limpien correctamente. Es importante tener en cuenta que, cuando se elimina una ServiceBusClient instancia, se cerrará y limpiará automáticamente los remitentes, receptores y procesadores que se crearon con él.

Seguridad para subprocesos

Garantizamos que todos los métodos de instancia de cliente sean seguros para subprocesos e independientes entre sí (guía). Esto garantiza que la recomendación de reutilizar instancias de cliente siempre es segura, incluso entre subprocesos.

Conceptos adicionales

Opciones | de clienteDiagnóstico | Burla

Ejemplos

Enviar y recibir un mensaje

El envío de mensajes se realiza mediante ServiceBusSender. La recepción se realiza mediante ServiceBusReceiver.

string connectionString = "<connection_string>";
string queueName = "<queue_name>";
// since ServiceBusClient implements IAsyncDisposable we create it with "await using"
await using var client = new ServiceBusClient(connectionString);

// create the sender
ServiceBusSender sender = client.CreateSender(queueName);

// create a message that we can send. UTF-8 encoding is used when providing a string.
ServiceBusMessage message = new ServiceBusMessage("Hello world!");

// send the message
await sender.SendMessageAsync(message);

// create a receiver that we can use to receive the message
ServiceBusReceiver receiver = client.CreateReceiver(queueName);

// the received message is a different type as it contains some service set properties
ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();

// get the message body as a string
string body = receivedMessage.Body.ToString();
Console.WriteLine(body);

Envío de un lote de mensajes

Hay dos maneras de enviar varios mensajes a la vez. La primera forma de hacerlo usa el procesamiento por lotes seguro. Con el procesamiento por lotes seguro, puede crear un ServiceBusMessageBatch objeto , que le permitirá intentar agregar mensajes de uno en uno al lote mediante el TryAdd método . Si el mensaje no cabe en el lote, TryAdd devolverá false.

// add the messages that we plan to send to a local queue
Queue<ServiceBusMessage> messages = new Queue<ServiceBusMessage>();
messages.Enqueue(new ServiceBusMessage("First message"));
messages.Enqueue(new ServiceBusMessage("Second message"));
messages.Enqueue(new ServiceBusMessage("Third message"));

// create a message batch that we can send
// total number of messages to be sent to the Service Bus queue
int messageCount = messages.Count;

// while all messages are not sent to the Service Bus queue
while (messages.Count > 0)
{
    // start a new batch
    using ServiceBusMessageBatch messageBatch = await sender.CreateMessageBatchAsync();

    // add the first message to the batch
    if (messageBatch.TryAddMessage(messages.Peek()))
    {
        // dequeue the message from the .NET queue once the message is added to the batch
        messages.Dequeue();
    }
    else
    {
        // if the first message can't fit, then it is too large for the batch
        throw new Exception($"Message {messageCount - messages.Count} is too large and cannot be sent.");
    }

    // add as many messages as possible to the current batch
    while (messages.Count > 0 && messageBatch.TryAddMessage(messages.Peek()))
    {
        // dequeue the message from the .NET queue as it has been added to the batch
        messages.Dequeue();
    }

    // now, send the batch
    await sender.SendMessagesAsync(messageBatch);

    // if there are any remaining messages in the .NET queue, the while loop repeats
}

La segunda forma usa la SendMessagesAsync sobrecarga que acepta un valor IEnumerable de ServiceBusMessage. Con este método, intentaremos ajustar todos los mensajes proporcionados en un único lote de mensajes que enviaremos al servicio. Si los mensajes son demasiado grandes para caber en un solo lote, la operación producirá una excepción.

IList<ServiceBusMessage> messages = new List<ServiceBusMessage>();
messages.Add(new ServiceBusMessage("First"));
messages.Add(new ServiceBusMessage("Second"));
// send the messages
await sender.SendMessagesAsync(messages);

Recepción de un lote de mensajes

// create a receiver that we can use to receive the messages
ServiceBusReceiver receiver = client.CreateReceiver(queueName);

// the received message is a different type as it contains some service set properties
// a batch of messages (maximum of 2 in this case) are received
IReadOnlyList<ServiceBusReceivedMessage> receivedMessages = await receiver.ReceiveMessagesAsync(maxMessages: 2);

// go through each of the messages received
foreach (ServiceBusReceivedMessage receivedMessage in receivedMessages)
{
    // get the message body as a string
    string body = receivedMessage.Body.ToString();
}

Completar un mensaje

Para quitar un mensaje de una cola o suscripción, podemos llamar al CompleteMessageAsync método .

string connectionString = "<connection_string>";
string queueName = "<queue_name>";
// since ServiceBusClient implements IAsyncDisposable we create it with "await using"
await using var client = new ServiceBusClient(connectionString);

// create the sender
ServiceBusSender sender = client.CreateSender(queueName);

// create a message that we can send
ServiceBusMessage message = new ServiceBusMessage("Hello world!");

// send the message
await sender.SendMessageAsync(message);

// create a receiver that we can use to receive and settle the message
ServiceBusReceiver receiver = client.CreateReceiver(queueName);

// the received message is a different type as it contains some service set properties
ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();

// complete the message, thereby deleting it from the service
await receiver.CompleteMessageAsync(receivedMessage);

Abandonar un mensaje

Al abandonar un mensaje, se libera el bloqueo del receptor, que permite que este u otros receptores reciban el mensaje.

ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();

// abandon the message, thereby releasing the lock and allowing it to be received again by this or other receivers
await receiver.AbandonMessageAsync(receivedMessage);

Aplazar un mensaje

Aplazar un mensaje impedirá que se reciba de nuevo mediante los ReceiveMessageAsync métodos o ReceiveMessagesAsync . En su lugar, hay métodos ReceiveDeferredMessageAsync independientes y ReceiveDeferredMessagesAsync para recibir mensajes diferidos.

ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();

// defer the message, thereby preventing the message from being received again without using
// the received deferred message API.
await receiver.DeferMessageAsync(receivedMessage);

// receive the deferred message by specifying the service set sequence number of the original
// received message
ServiceBusReceivedMessage deferredMessage = await receiver.ReceiveDeferredMessageAsync(receivedMessage.SequenceNumber);

Mensajes fallidos de un mensaje

La entrega de mensajes fallidos a un mensaje es similar a aplazarse con una diferencia principal, ya que el servicio enviará automáticamente mensajes fallidos una vez recibidos un número determinado de veces. Las aplicaciones pueden optar por enviar mensajes fallidos manualmente en función de sus requisitos. Cuando se envía un mensaje fallido, se mueve realmente a una subconsulta de la cola original. Tenga en cuenta que ServiceBusReceiver se usa para recibir mensajes de la subconsulta de mensajes fallidos, independientemente de si la cola principal está habilitada para sesión o no.

ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();

// Dead-letter the message, thereby preventing the message from being received again without receiving from the dead letter queue.
// We can optionally pass a dead letter reason and dead letter description to further describe the reason for dead-lettering the message.
await receiver.DeadLetterMessageAsync(receivedMessage, "sample reason", "sample description");

// receive the dead lettered message with receiver scoped to the dead letter queue.
ServiceBusReceiver dlqReceiver = client.CreateReceiver(queueName, new ServiceBusReceiverOptions
{
    SubQueue = SubQueue.DeadLetter
});
ServiceBusReceivedMessage dlqMessage = await dlqReceiver.ReceiveMessageAsync();

// The reason and the description that we specified when dead-lettering the message will be available in the received dead letter message.
string reason = dlqMessage.DeadLetterReason;
string description = dlqMessage.DeadLetterErrorDescription;

Para más información, consulte la introducción a las colas de mensajes fallidos de ServiceBus.

Uso del procesador

ServiceBusProcessor se puede considerar como una abstracción en torno a un conjunto de receptores. Usa un modelo de devolución de llamada para permitir que el código se especifique cuando se recibe un mensaje y cuando se produce una excepción. Ofrece la finalización automática de los mensajes procesados, la renovación automática del bloqueo de mensajes y la ejecución simultánea de controladores de eventos especificados por el usuario. Debido a su conjunto de características, debe ser la herramienta ir a para escribir aplicaciones que reciben de entidades de Service Bus. ServiceBusReceiver se recomienda para escenarios más complejos en los que el procesador no puede proporcionar el control específico que se puede esperar al usar ServiceBusReceiver directamente.

string connectionString = "<connection_string>";
string queueName = "<queue_name>";
// since ServiceBusClient implements IAsyncDisposable we create it with "await using"
await using var client = new ServiceBusClient(connectionString);

// create the sender
ServiceBusSender sender = client.CreateSender(queueName);

// create a set of messages that we can send
ServiceBusMessage[] messages = new ServiceBusMessage[]
{
    new ServiceBusMessage("First"),
    new ServiceBusMessage("Second")
};

// send the message batch
await sender.SendMessagesAsync(messages);

// create the options to use for configuring the processor
var options = new ServiceBusProcessorOptions
{
    // By default or when AutoCompleteMessages is set to true, the processor will complete the message after executing the message handler
    // Set AutoCompleteMessages to false to [settle messages](/azure/service-bus-messaging/message-transfers-locks-settlement#peeklock) on your own.
    // In both cases, if the message handler throws an exception without settling the message, the processor will abandon the message.
    AutoCompleteMessages = false,

    // I can also allow for multi-threading
    MaxConcurrentCalls = 2
};

// create a processor that we can use to process the messages
await using ServiceBusProcessor processor = client.CreateProcessor(queueName, options);

// configure the message and error handler to use
processor.ProcessMessageAsync += MessageHandler;
processor.ProcessErrorAsync += ErrorHandler;

async Task MessageHandler(ProcessMessageEventArgs args)
{
    string body = args.Message.Body.ToString();
    Console.WriteLine(body);

    // we can evaluate application logic and use that to determine how to settle the message.
    await args.CompleteMessageAsync(args.Message);
}

Task ErrorHandler(ProcessErrorEventArgs args)
{
    // the error source tells me at what point in the processing an error occurred
    Console.WriteLine(args.ErrorSource);
    // the fully qualified namespace is available
    Console.WriteLine(args.FullyQualifiedNamespace);
    // as well as the entity path
    Console.WriteLine(args.EntityPath);
    Console.WriteLine(args.Exception.ToString());
    return Task.CompletedTask;
}

// start processing
await processor.StartProcessingAsync();

// since the processing happens in the background, we add a Console.ReadKey to allow the processing to continue until a key is pressed.
Console.ReadKey();

Autenticación con Azure.Identity

La biblioteca de identidades de Azure proporciona compatibilidad sencilla con Azure Active Directory para la autenticación.

// Create a ServiceBusClient that will authenticate through Active Directory
string fullyQualifiedNamespace = "yournamespace.servicebus.windows.net";
await using var client = new ServiceBusClient(fullyQualifiedNamespace, new DefaultAzureCredential());

Trabajar con sesiones

Las sesiones proporcionan un mecanismo para agrupar mensajes relacionados. Para usar sesiones, debe trabajar con una entidad habilitada para sesión.

Registro con inserción de dependencias de ASP.NET Core

Para insertar ServiceBusClient como dependencia en una aplicación de ASP.NET Core, instale la integración de la biblioteca cliente de Azure para ASP.NET Core paquete.

dotnet add package Microsoft.Extensions.Azure

A continuación, registre el cliente donde están configurados los servicios. Para ASP.NET Core aplicaciones, esto suele estar directamente en Program.cs o en el StartupConfigureServices método :

public void ConfigureServices(IServiceCollection services)
{
    services.AddAzureClients(builder =>
    {
        builder.AddServiceBusClient("<< SERVICE BUS CONNECTION STRING >>");
    });

    // Register other services, controllers, and other infrastructure.
}

En el caso de las aplicaciones que prefieren usar una credencial compartida Azure.Identity para sus clientes, el registro tiene un aspecto ligeramente diferente:

public void ConfigureServices(IServiceCollection services)
 {
     services.AddAzureClients(builder =>
     {
         // This will register the ServiceBusClient using an Azure Identity credential.
         builder.AddServiceBusClientWithNamespace("<< YOUR NAMESPACE >>.servicebus.windows.net");

         // By default, DefaultAzureCredential is used, which is likely desired for most
         // scenarios. If you need to restrict to a specific credential instance, you could
         // register that instance as the default credential instead.
         builder.UseCredential(new ManagedIdentityCredential());
     });

     // Register other services, controllers, and other infrastructure.
 }

También es posible registrar sub-clientes, como ServiceBusSender y ServiceBusReceiver con DI mediante la instancia registrada ServiceBusClient . Por ejemplo, para registrar un remitente para cada cola que pertenezca al espacio de nombres:

public async Task ConfigureServicesAsync(IServiceCollection services)
{
    // Query the available queues for the Service Bus namespace.
    var adminClient = new ServiceBusAdministrationClient("<< SERVICE BUS CONNECTION STRING >>");
    var queueNames = new List<string>();

    // Because the result is async, they need to be captured to a standard list to avoid async
    // calls when registering.  Failure to do so results in an error with the services collection.
    await foreach (var queue in adminClient.GetQueuesAsync())
    {
        queueNames.Add(queue.Name);
    }

    // After registering the ServiceBusClient, register a named factory for each
    // queue.  This allows them to be lazily created and managed as singleton instances.

    services.AddAzureClients(builder =>
    {
        builder.AddServiceBusClient("<< SERVICE BUS CONNECTION STRING >>");

        foreach (var queueName in queueNames)
        {
            builder.AddClient<ServiceBusSender, ServiceBusClientOptions>((_, _, provider) =>
                provider
                    .GetService<ServiceBusClient>()
                    .CreateSender(queueName)
            )
            .WithName(queueName);
        }
    });

    // Register other services, controllers, and other infrastructure.
}

Dado que los remitentes se denominan para su cola asociada, al insertarlos, no se enlaza directamente a ellos. En su lugar, enlazará a un generador que se puede usar para recuperar el remitente con nombre:

public class ServiceBusSendingController : ControllerBase
{
    private readonly ServiceBusSender _sender;

    public ServiceBusSendingController(IAzureClientFactory<ServiceBusSender> serviceBusSenderFactory)
    {
        // Though the method is called "CreateClient", the factory will manage the sender as a
        // singleton, creating a new instance only on the first use.
        _sender = serviceBusSenderFactory.CreateClient("<< QUEUE NAME >>");
    }
}

Para más información y ejemplos, consulte Inserción de dependencias con el SDK de Azure para .NET.

Solución de problemas

Consulte la Guía de solución de problemas de Service Bus.

Pasos siguientes

Más allá de los escenarios introductorios descritos, la biblioteca cliente de Azure Service Bus ofrece compatibilidad con escenarios adicionales para ayudar a aprovechar el conjunto de características completo del servicio Azure Service Bus. Para ayudar a explorar algunos de estos escenarios, la biblioteca cliente de Service Bus ofrece un proyecto de ejemplos para servir como ilustración para escenarios comunes. Consulte los ejemplos Léame para obtener más información.

Contribuciones

Este proyecto agradece las contribuciones y sugerencias. La mayoría de las contribuciones requieren que acepte un Contrato de licencia para el colaborador (CLA) que declara que tiene el derecho a concedernos y nos concede los derechos para usar su contribución. Para más detalles, visite https://cla.microsoft.com.

Cuando se envía una solicitud de incorporación de cambios, un bot de CLA determinará de forma automática si tiene que aportar un CLA y completar la PR adecuadamente (por ejemplo, la etiqueta, el comentario). Solo siga las instrucciones que le dará el bot. Solo será necesario que lo haga una vez en todos los repositorios con nuestro CLA.

Este proyecto ha adoptado el Código de conducta de Microsoft Open Source. Para más información, consulte las preguntas más frecuentes del código de conducta o póngase en contacto con opencode@microsoft.com si tiene cualquier otra pregunta o comentario.

Consulte nuestra guía de contribución para obtener más información.

Impresiones