Delen via


Azure Service Bus clientbibliotheek voor .NET - versie 7.13.1

met Azure Service Bus kunt u toepassingen bouwen die profiteren van asynchrone berichtpatronen met behulp van een zeer betrouwbare service om berichten tussen producenten en consumenten tussen te brengen. Azure Service Bus biedt flexibele, brokered messaging tussen client en server, samen met gestructureerde FIFO-berichten (first-in, first-out) en mogelijkheden voor publiceren/abonneren met complexe routering. Als u meer wilt weten over Azure Service Bus, kunt u het volgende lezen: Wat is Azure Service Bus?

Gebruik de clientbibliotheek voor Azure Service Bus om het volgende te doen:

  • Bedrijfsgegevens overdragen: maak gebruik van berichten voor duurzame uitwisseling van informatie, zoals verkoop- of inkooporders, tijdschriften of voorraadverplaatsingen.

  • Loskoppelen van toepassingen: verbeter de betrouwbaarheid en schaalbaarheid van toepassingen en services, zodat afzenders en ontvangers tegelijkertijd online moeten zijn.

  • Bepalen hoe berichten worden verwerkt: traditionele concurrerende consumenten ondersteunen voor berichten met behulp van wachtrijen of elke consument zijn eigen exemplaar van een bericht toestaan met behulp van onderwerpen en abonnementen.

  • Complexe werkstromen implementeren: berichtsessies ondersteunen scenario's waarvoor berichtvolgorde of uitstel van berichten is vereist.

Broncode | Pakket (NuGet) | API-referentiedocumentatie | Productdocumentatie | Migratiehandleiding | Gids voor probleemoplossing

Aan de slag

Vereisten

  • Microsoft Azure-abonnement: Als u Azure-services wilt gebruiken, waaronder Azure Service Bus, hebt u een abonnement nodig. Als u geen bestaand Azure-account hebt, kunt u zich registreren voor een gratis proefversie of de voordelen van uw MSDN-abonnee gebruiken wanneer u een account maakt.

  • Service Bus-naamruimte: Als u wilt communiceren met Azure Service Bus, moet er ook een naamruimte beschikbaar zijn. Als u niet bekend bent met het maken van Azure-resources, kunt u de stapsgewijze handleiding volgen voor het maken van een Service Bus-naamruimte met behulp van de Azure Portal. Daar vindt u ook gedetailleerde instructies voor het gebruik van de Azure CLI-, Azure PowerShell- of Arm-sjablonen (Azure Resource Manager) om een Service Bus-entiteit te maken.

  • C# 8.0: De Azure Service Bus clientbibliotheek maakt gebruik van nieuwe functies die zijn geïntroduceerd in C# 8.0. Als u wilt profiteren van de C# 8.0-syntaxis, wordt u aangeraden te compileren met behulp van de .NET Core SDK 3.0 of hoger met een taalversie van latest.

    Visual Studio-gebruikers die volledig willen profiteren van de C# 8.0-syntaxis, moeten Visual Studio 2019 of hoger gebruiken. Visual Studio 2019, met inbegrip van de gratis Community-editie, hier worden gedownload. Gebruikers van Visual Studio 2017 kunnen profiteren van de C# 8-syntaxis door gebruik te maken van het Microsoft.Net.Compilers NuGet-pakket en de taalversie in te stellen, hoewel de bewerkingservaring mogelijk niet ideaal is.

    U kunt de bibliotheek nog steeds gebruiken met eerdere C#-taalversies, maar u moet asynchrone opsommings- en asynchrone wegwerpleden handmatig beheren in plaats van te profiteren van de nieuwe syntaxis. U kunt zich nog steeds richten op elke frameworkversie die wordt ondersteund door uw .NET Core SDK, inclusief eerdere versies van .NET Core of het .NET Framework. Zie Doelframeworks opgeven voor meer informatie.

    Belangrijke opmerking: Als u de voorbeelden en voorbeelden wilt bouwen of uitvoeren zonder wijzigingen, is het gebruik van C# 8.0 verplicht. U kunt de voorbeelden nog steeds uitvoeren als u besluit ze aan te passen voor andere taalversies.

Als u snel de benodigde Service Bus-resources in Azure wilt maken en er een connection string voor wilt ontvangen, kunt u onze voorbeeldsjabloon implementeren door te klikken op:

Implementeren op Azure

Het pakket installeren

Installeer de Azure Service Bus-clientbibliotheek voor .NET met NuGet:

dotnet add package Azure.Messaging.ServiceBus

De client verifiëren

Als u wilt dat de Service Bus-clientbibliotheek kan communiceren met een wachtrij of onderwerp, moet deze weten hoe u verbinding kunt maken en ermee kunt autoriseren. De eenvoudigste manier om dit te doen, is het gebruik van een connection string, die automatisch wordt gemaakt bij het maken van een Service Bus-naamruimte. Als u niet bekend bent met beleid voor gedeelde toegang in Azure, kunt u de stapsgewijze handleiding volgen om een Service Bus-connection string te krijgen.

Zodra u een connection string hebt, kunt u uw client hiermee verifiëren.

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

Bekijk dit voorbeeld om te zien hoe u zich kunt verifiëren met behulp van Azure.Identity.

Bekijk dit voorbeeld om te zien hoe u de verbinding met een aangepast eindpunt start.

ASP.NET Core

Als u wilt injecteren ServiceBusClient als een afhankelijkheid in een ASP.NET Core-app, installeert u de integratie van de Azure-clientbibliotheek voor ASP.NET Core-pakket.

dotnet add package Microsoft.Extensions.Azure

Registreer vervolgens de client in de Startup.ConfigureServices methode:

public void ConfigureServices(IServiceCollection services)
{
    services.AddAzureClients(builder =>
    {
        builder.AddServiceBusClient(Configuration.GetConnectionString("ServiceBus"));
    });
  
    services.AddControllers();
}

Als u de voorgaande code wilt gebruiken, voegt u deze toe aan uw configuratie:

{
  "ConnectionStrings": {
    "ServiceBus": "<connection_string>"
  }
}

Zie Afhankelijkheidsinjectie met de Azure SDK voor .NET voor meer informatie.

Belangrijkste concepten

Zodra u een ServiceBusClienthebt geïnitialiseerd, kunt u communiceren met de primaire resourcetypen in een Service Bus-naamruimte, waarvan er meerdere kunnen bestaan en waarop de daadwerkelijke berichtoverdracht plaatsvindt. De naamruimte fungeert vaak als een toepassingscontainer:

  • Wachtrij: hiermee kunt u berichten verzenden en ontvangen. Vaak gebruikt voor punt-naar-punt-communicatie.

  • Onderwerp: In tegenstelling tot wachtrijen zijn onderwerpen beter geschikt voor scenario's voor publiceren/abonneren. Een onderwerp kan worden verzonden naar, maar hiervoor is een abonnement vereist, waarvan er meerdere parallel kunnen zijn, waaruit kan worden verbruikt.

  • Abonnement: het mechanisme om te gebruiken vanuit een onderwerp. Elk abonnement is onafhankelijk en ontvangt een kopie van elk bericht dat naar het onderwerp wordt verzonden. Regels en filters kunnen worden gebruikt om aan te passen welke berichten worden ontvangen door een specifiek abonnement.

Zie Wat is Azure Service Bus? voor meer informatie over deze resources.

Als u met deze resources wilt werken, moet u bekend zijn met de volgende SDK-concepten:

  • Een Service Bus-client is de primaire interface voor ontwikkelaars die communiceren met de Service Bus-clientbibliotheek. Het fungeert als de gateway van waaruit alle interactie met de bibliotheek plaatsvindt.

  • Een Service Bus-afzender is gericht op een bepaalde wachtrij of onderwerp en wordt gemaakt met behulp van de Service Bus-client. Met de afzender kunt u berichten verzenden naar een wachtrij of onderwerp. Het maakt het ook mogelijk dat planningsberichten beschikbaar zijn voor bezorging op een opgegeven datum.

  • Een Service Bus-ontvanger is gericht op een bepaalde wachtrij of een bepaald abonnement en wordt gemaakt met behulp van de Service Bus-client. Met de ontvanger kunt u berichten ontvangen van een wachtrij of abonnement. Hiermee kunnen de berichten ook worden vereffend nadat ze zijn ontvangen. Er zijn vier manieren om berichten te vereffenen:

    • Voltooid: zorgt ervoor dat het bericht uit de wachtrij of het onderwerp wordt verwijderd.
    • Afbreken: hiermee wordt de vergrendeling van de ontvanger op het bericht vrijgegeven, zodat het bericht kan worden ontvangen door andere ontvangers.
    • Uitstellen - uitstelt de ontvangst van het bericht op normale wijze. Als u uitgestelde berichten wilt ontvangen, moet het volgnummer van het bericht worden behouden.
    • DeadLetter: hiermee verplaatst u het bericht naar de wachtrij Voor onbestelbare berichten. Hiermee voorkomt u dat het bericht opnieuw wordt ontvangen. Als u berichten van de wachtrij Met dode brieven wilt ontvangen, hebt u een ontvanger nodig die is gericht op de wachtrij Voor onbestelbare berichten.
  • Een Service Bus-sessieontvanger is gericht op een bepaalde wachtrij of een bepaald abonnement met sessie en wordt gemaakt met behulp van de Service Bus-client. De sessieontvanger is bijna identiek aan de standaardontvanger, met het verschil dat sessiebeheerbewerkingen beschikbaar zijn die alleen van toepassing zijn op entiteiten met sessiefunctionaliteit. Deze bewerkingen omvatten het verkrijgen en instellen van de sessiestatus, evenals het vernieuwen van sessievergrendelingen.

  • Een Service Bus-processor is gericht op een bepaalde wachtrij of een bepaald abonnement en wordt gemaakt met behulp van de Service Bus-client. De ServiceBusProcessor kan worden beschouwd als een abstractie rond een set ontvangers. Er wordt een callback-model gebruikt om toe te staan dat code wordt opgegeven wanneer een bericht wordt ontvangen en wanneer een uitzondering optreedt. Het biedt automatische voltooiing van verwerkte berichten, automatische verlenging van berichtvergrendeling en gelijktijdige uitvoering van door de gebruiker opgegeven gebeurtenis-handlers. Vanwege de functieset moet dit het hulpprogramma go to zijn voor het schrijven van toepassingen die ontvangen van Service Bus-entiteiten. De ServiceBusReceiver wordt aanbevolen voor complexere scenario's waarin de processor niet de fijnmazige controle kan bieden die kan worden verwacht wanneer u de ServiceBusReceiver rechtstreeks gebruikt.

  • Een Service Bus-sessieprocessor is gericht op een bepaalde wachtrij of een bepaald abonnement met sessie en wordt gemaakt met behulp van de Service Bus-client. De sessieprocessor is bijna identiek aan de standaardprocessor, met als verschil dat sessiebeheerbewerkingen beschikbaar zijn die alleen van toepassing zijn op entiteiten met sessiefunctionaliteit.

Zie: Geavanceerde functies van Service Bus voor meer concepten en uitgebreidere discussies.

Clientlevensduur

De ServiceBusClient, afzenders, ontvangers en processors kunnen veilig in de cache worden opgeslagen en worden gebruikt als een singleton voor de levensduur van de toepassing. Dit is de best practice wanneer berichten regelmatig worden verzonden of ontvangen. Ze zijn verantwoordelijk voor een efficiënt beheer van netwerk-, CPU- en geheugengebruik, waarbij het gebruik laag blijft tijdens perioden van inactiviteit.

Deze typen zijn eenmalig en roepen of DisposeAsyncCloseAsync aan om ervoor te zorgen dat netwerkbronnen en andere onbeheerde objecten correct worden opgeschoond. Het is belangrijk te weten dat wanneer een ServiceBusClient exemplaar wordt verwijderd, alle afzenders, ontvangers en processors die met het exemplaar zijn gemaakt, automatisch worden gesloten en opgeschoond.

Veiligheid van schroefdraad

We garanderen dat alle clientexemplaarmethoden thread-veilig en onafhankelijk van elkaar zijn (richtlijn). Dit zorgt ervoor dat de aanbeveling om clientexemplaren opnieuw te gebruiken altijd veilig is, zelfs voor alle threads.

Aanvullende concepten

Clientopties | Diagnostics | Spottende

Voorbeelden

Een bericht verzenden en ontvangen

Het verzenden van berichten wordt uitgevoerd met behulp van de ServiceBusSender. Het ontvangen wordt uitgevoerd met behulp van de 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);

Een batch berichten verzenden

Er zijn twee manieren om meerdere berichten tegelijk te verzenden. De eerste manier om dit te doen, maakt gebruik van veilige batchverwerking. Met veilige batchverwerking kunt u een ServiceBusMessageBatch -object maken, waarmee u kunt proberen berichten één voor één toe te voegen aan de batch met behulp van de TryAdd methode . Als het bericht niet in de batch past, TryAdd retourneert 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
}

De tweede manier maakt gebruik van de SendMessagesAsync overbelasting die een IEnumerable van ServiceBusMessageaccepteert. Met deze methode proberen we alle opgegeven berichten in één berichtenbatch te plaatsen die we naar de service verzenden. Als de berichten te groot zijn om in één batch te passen, genereert de bewerking een uitzondering.

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

Een batch berichten ontvangen

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

Een bericht voltooien

Als u een bericht uit een wachtrij of abonnement wilt verwijderen, kunnen we de CompleteAsync methode aanroepen.

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

Een bericht afbreken

Als u een bericht afgeeft, wordt de vergrendeling van de ontvanger losgelaten, waardoor het bericht kan worden ontvangen door deze of andere ontvangers.

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

Een bericht uitstellen

Als u een bericht uitstelt, wordt het bericht niet opnieuw ontvangen met behulp van de ReceiveMessageAsync methode of ReceiveMessagesAsync . In plaats daarvan zijn er afzonderlijke methoden ReceiveDeferredMessageAsync en ReceiveDeferredMessagesAsync voor het ontvangen van uitgestelde berichten.

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

Een bericht met een onbestelbare brief

Een bericht met een onbestelbaar bericht is vergelijkbaar met uitstellen. Een belangrijk verschil is dat berichten automatisch onbestelbaar worden gesteld door de service nadat ze een bepaald aantal keren zijn ontvangen. Toepassingen kunnen ervoor kiezen om berichten met onbestelbare berichten handmatig te verzenden op basis van hun vereisten. Wanneer een bericht onbestelbaar is, wordt het verplaatst naar een submap van de oorspronkelijke wachtrij. Houd er rekening mee dat de ServiceBusReceiver wordt gebruikt om berichten te ontvangen van de sublocatie voor onbestelbare berichten, ongeacht of de hoofdwachtrij al dan niet sessie is ingeschakeld.

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;

Zie het overzicht van wachtrijen met onbestelbare brieven van ServiceBus voor meer informatie.

De processor gebruiken

De ServiceBusProcessor kan worden beschouwd als een abstractie rond een set ontvangers. Er wordt een callback-model gebruikt om toe te staan dat code wordt opgegeven wanneer een bericht wordt ontvangen en wanneer een uitzondering optreedt. Het biedt automatische voltooiing van verwerkte berichten, automatische verlenging van berichtvergrendeling en gelijktijdige uitvoering van door de gebruiker opgegeven gebeurtenis-handlers. Vanwege de functieset moet dit het hulpprogramma go to zijn voor het schrijven van toepassingen die ontvangen van Service Bus-entiteiten. De ServiceBusReceiver wordt aanbevolen voor complexere scenario's waarin de processor niet de fijnmazige controle kan bieden die kan worden verwacht wanneer u de ServiceBusReceiver rechtstreeks gebruikt.

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

Verifiëren met Azure.Identity

De Azure Identity-bibliotheek biedt eenvoudige Ondersteuning voor Azure Active Directory voor verificatie.

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

Werken met sessies

Sessies bieden een mechanisme voor het groeperen van gerelateerde berichten. Als u sessies wilt gebruiken, moet u werken met een entiteit die is ingeschakeld voor sessies.

Problemen oplossen

Raadpleeg de Handleiding voor het oplossen van problemen met Service Bus.

Volgende stappen

Naast de inleidende scenario's die worden besproken, biedt de Azure Service Bus-clientbibliotheek ondersteuning voor aanvullende scenario's om te profiteren van de volledige functieset van de Azure Service Bus-service. Om een aantal van deze scenario's te verkennen, biedt de Service Bus-clientbibliotheek een project met voorbeelden ter illustratie voor veelvoorkomende scenario's. Raadpleeg de voorbeelden LEESMIJ voor meer informatie.

Bijdragen

Wij verwelkomen bijdragen en suggesties voor dit project. Voor de meeste bijdragen moet u instemmen met een licentieovereenkomst voor bijdragers (CLA: Contributor License Agreement) waarin u verklaart dat u gerechtigd bent ons het recht te geven uw bijdrage te gebruiken, en dat u dit ook doet. Ga naar https://cla.microsoft.com voor meer informatie.

Wanneer u een pull-aanvraag indient, wordt met een CLA-bot automatisch bepaald of u een CLA moet verschaffen en wordt de pull-aanvraag dienovereenkomstig opgemaakt (bijvoorbeeld met een label of commentaar). Volg gewoon de instructies van de bot. U hoeft dit maar eenmaal te doen voor alle repo's waar gebruik wordt gemaakt van onze CLA.

Op dit project is de Microsoft Open Source Code of Conduct (Microsoft Open Source-gedragscode) van toepassing. Zie voor meer informatie de veelgestelde vragen over de gedragscode of neem contact op opencode@microsoft.com met eventuele aanvullende vragen of opmerkingen.

Raadpleeg onze gids voor bijdragen voor meer informatie.

Weergaven