MiddlewareMiddleware

gilt für: SDK v4APPLIES TO: SDK v4

Middleware ist lediglich eine Klasse zwischen dem Adapter und der Bot-Logik, die während der Initialisierung der Middlewaresammlung Ihres Adapters hinzugefügt wird.Middleware is simply a class that sits between the adapter and your bot logic, added to your adapter's middleware collection during initialization. Das SDK ermöglicht Ihnen das Schreiben eigener Middleware sowie das Hinzufügen von Middleware, die von anderen Entwicklern erstellt wurde.The SDK allows you to write your own middleware or add middleware created by others. Jede ein- oder ausgehende Aktivität für Ihren Bot durchläuft Ihre Middleware.Every activity coming into or out of your bot flows through your middleware.

Der Adapter verarbeitet und leitet eingehende Aktivitäten in über die bot-middlewarepipeline an die Logik des Bots und dann wieder zurück.The adapter processes and directs incoming activities in through the bot middleware pipeline to your bot's logic and then back out again. Während jede Aktivität den Bot durchläuft, kann jede Middleware die Aktivität überprüfen und beeinflussen, sowohl bevor als auch nachdem die Bot-Logik ausgeführt wurde.As each activity flows in and out of the bot, each piece of middleware can inspect or act upon the activity, both before and after the bot logic runs.

Bevor Sie mit Middleware arbeiten, ist es wichtig, dass Sie Bots im Allgemeinen und wie sie Aktivitäten verarbeiten verstehen.Before jumping into middleware, it is important to understand bots in general and how they process activities.

Verwendungsmöglichkeiten für MiddlewareUses for middleware

Oft stellt sich folgende Frage: „Wann sollte ich Aktionen als Middleware implementieren und nicht meine normale Botlogik verwenden?“The question often comes up: "When should I implement actions as middleware versus using my normal bot logic?" Mit Middleware haben Sie zusätzliche Möglichkeiten zum Interagieren mit dem Konversationsfluss Ihrer Benutzer – sowohl vor als auch nach der Verarbeitung jedes Durchlaufs der Konversation.Middleware provides you with additional opportunities to interact with your users' conversation flow both before and after each turn of the conversation is processed. Darüber hinaus können Sie mit Middleware auch Informationen zur Konversation speichern und abrufen und bei Bedarf weitere Verarbeitungslogik aufrufen.Middleware also allows you to store and retrieve information concerning the conversation and call additional processing logic when required. Unten sind einige häufige Szenarien angegeben, die zeigen, wann Middleware hilfreich sein kann.Below are some common scenarios that show where middleware can be useful.

Ansehen oder Beeinflussen jeder AktivitätLooking at or acting on every activity

Es gibt viele Situationen, in denen Ihr Bot jede Aktivität bzw. jede Aktivität eines bestimmten Typs behandeln sollte.There are plenty of situations that require your bot to do something on every activity, or for every activity of a certain type. Angenommen, Sie möchten jedes MessageActivity-Objekt protokollieren, das der Bot empfängt, oder eine Fallbackantwort bereitstellen, wenn der Bot keine andere Antwort für diesen Durchlauf generiert hat.For example, you may want to log every message activity your bot receives or provide a fallback response if the bot has not otherwise generated a response this turn. Die Middleware ist ein guter Ausgangspunkt hierfür, da sie sowohl vor als auch nach der Ausführung der restlichen Bot-Logik agieren kann.Middleware is a great place for this, with its ability to act both before and after the rest of the bot logic has executed.

Ändern und Erweitern des Turn-KontextsModifying or enhancing the turn context

Bestimmte Konversationen können erfolgreicher sein, wenn der Bot über mehr Informationen verfügt, als in der Aktivität bereitgestellt werden.Certain conversations can be much more fruitful if the bot has more information than what is provided in the activity. In diesem Fall kann Middleware auf die bisher verfügbaren Informationen zum Konversationszustand zugreifen, eine externe Datenquelle abfragen und diese an das Turn-Kontextobjekt anfügen, bevor die Ausführung an die Bot-Logik übergeben wird.Middleware in this case could look at the conversation state information it has so far, query an external data source, and append that to the turn context object before passing execution on to the bot logic.

Im SDK ist das Protokollieren der Middleware definiert, mit der ein- und ausgehende Aktivitäten aufgezeichnet werden können, aber Sie können auch Ihre eigene Middleware definieren.The SDK defines logging middleware that can record incoming and outgoing activities, but you can also define your own middleware.

Die Bot-MiddlewarepipelineThe bot middleware pipeline

Der Adapter ruft für jede Aktivität Middleware in der Reihenfolge auf, in der Sie sie hinzugefügt haben.For each activity, the adapter calls middleware in the order in which you added it. Der Adapter übergibt das Kontextobjekt für den Turn und einen next-Delegaten, und die Middleware ruft den Delegaten auf, um die Steuerung an die nächste Middleware in der Pipeline zu übergeben.The adapter passes in the context object for the turn and a next delegate, and the middleware calls the delegate to pass control to the next middleware in the pipeline. Middleware hat auch die Möglichkeit, Aktionen durchzuführen, nachdem der next-Delegat zurückgegeben wird, bevor die Methode abgeschlossen wird.Middleware also has an opportunity to do things after the next delegate returns before completing the method. Sie können es sich so vorstellen, dass jedes Middleware-Objekt die Möglichkeit hat, in Bezug auf Middleware-Objekte, die in der Pipeline folgen, als erstes und als letztes zu agieren.You can think of it as each middleware object has the first-and-last chance to act with respect to the middleware objects that follow it in the pipeline.

Beispiel:For example:

  • der Turn-Handler des 1. Middleware-Objekts führt Code vor dem Aufrufen von Next aus.1st middleware object's turn handler executes code before calling next.
    • der Turn-Handler für das 2. Middleware-Objekt führt Code vor dem Aufrufen von Next aus2nd middleware object's turn handler executes code before calling next.
      • Der Turn-Handler des bot führt aus und gibt zurück.The bot's turn handler executes and returns.
    • der Turn-Handler für das 2. Middleware-Objekt führt den restlichen Code vor der Rückgabe aus.2nd middleware object's turn handler executes any remaining code before returning.
  • der Turn-Handler des 1. Middleware-Objekts führt vor der Rückgabe den gesamten verbleibenden Code aus.1st middleware object's turn handler executes any remaining code before returning.

Wenn die Middleware den nächsten Delegaten nicht aufruft, ruft der Adapter keinen der nachfolgenden Middleware-oder botturn Handler und die kurz Leitungen der Pipeline auf.If middleware doesn't call the next delegate, the adapter does not call any of the subsequent middleware or bot turn handlers, and the pipeline short circuits.

Nach Abschluss der Bot-Middlewarepipeline endet der Turn und der Gültigkeitsbereich des Turn-Kontexts.Once the bot middleware pipeline completes, the turn is over, and the turn context goes out of scope.

Die Middleware oder der Bot kann Antworten generieren und Antwortereignishandler registrieren. Beachten Sie, dass Antworten in separaten Prozessen verarbeitet werden.Middleware or the bot can generate responses and register response event handlers, but keep in mind that responses are handled in separate processes.

Reihenfolge der MiddlewareOrder of middleware

Die Reihenfolge, in der die Middleware hinzugefügt wird, ist eine wichtige Entscheidung, da sie bestimmt, in welcher Reihenfolge die Middleware eine Aktivität verarbeitet.Since the order in which middleware is added determines the order in which the middleware processes an activity, it's important to decide the sequence that middleware should be added.

Hinweis

Damit soll ein allgemeines Muster bereitgestellt werden, das für die meisten Bots funktioniert. Beachten Sie jedoch, wie jeder Teil der Middleware mit den Anderen in Ihrer Situation interagiert.This is meant to give you a common pattern that works for most bots, but be sure to consider how each piece of middleware will interact with the others for your situation.

Die ersten Schritte in Ihrer Pipeline sollten wahrscheinlich die sein, die sich um die allgemeinsten Aufgaben kümmern und jedes Mal verwendet werden.The first things in your middleware pipeline should likely be those that take care of the lowest-level tasks that are used every time. Hierzu gehören beispielsweise die Protokollierung, die Ausnahmebehandlung und die Übersetzung.Examples include logging, exception handling, and translation. Die Festlegung der Reihenfolge hierfür kann je nach Ihren Anforderungen variieren, z.B. ob eingehende Nachrichten zuerst übersetzt werden sollen, bevor Nachrichten gespeichert werden, oder ob zuerst das Speichern der Nachrichten erfolgen soll. Dies kann bedeuten, dass die gespeicherten Nachrichten nicht übersetzt sind.Ordering these can vary depending on your needs, such as whether you want the incoming message to be translated first, before messages are stored, or if message storage should occur first, which could mean stored messages wouldn't be translated.

Die letzten Schritte in Ihrer Middleware-Pipeline sollten sich auf Bot-spezifische Middleware beziehen. Also Middleware, die Sie implementieren, um jede Nachricht an den Bot zu verarbeiten.The last things in your middleware pipeline should be bot-specific middleware, which is middleware you implement to do some processing on every message sent to your bot. Wenn Ihre Middleware Zustandsinformationen oder andere Informationen im Kontext des Bots verwendet, fügen Sie sie nach der Middleware, die den Zustand oder Kontext ändert, der Middleware-Pipeline hinzu.If your middleware uses state information or other information set in the bot context, add it to the middleware pipeline after the middleware that modifies state or context.

KurzschlüsseShort circuiting

Kurzschlüsse sind ein wichtiges Konzept bei der Middleware (und bei Antworthandlern).An important idea around middleware and response handlers is short circuiting. Wenn die Ausführung durch die nachfolgenden Ebenen fortgesetzt werden soll, ist eine Middleware (oder ein Antworthandler) erforderlich, um die Ausführung durch Aufrufen des next-Delegaten zu übergeben.If execution is to continue through the layers that follow it, middleware (or a response handler) is required to pass execution on by calling its next delegate. Wenn der next-Delegat in der Middleware (oder dem Antworthandler) aufgerufen wird, tritt für die zugeordnete Pipeline ein Kurzschluss auf, und die nachfolgenden Ebenen werden nicht ausgeführt.If the next delegate is not called within that middleware (or response handler), the associated pipeline short circuits and subsequent layers are not executed. Dies bedeutet, dass die gesamte Botlogik sowie jegliche Middleware im weiteren Verlauf der Pipeline übersprungen wird.This means all bot logic, and any middleware further along the pipeline, is skipped. Es besteht ein feiner Unterschied dazwischen, ob der Kurzschluss eines Durchlaufs von Ihrer Middleware oder von Ihrem Antworthandler ausgeht.There is a subtle difference between your middleware and your response handler short circuiting a turn.

Wenn der Kurschluss eines Durchlaufs von der Middleware ausgeht, wird Ihr Handler für den Botdurchlauf nicht aufgerufen, aber der gesamte Middleware-Code, der in der Pipeline vor diesem Punkt ausgeführt wurde, wird trotzdem bis zum Ende ausgeführt.When middleware short circuits a turn, your bot turn handler will not be called, but all middleware code executed prior to this point in the pipeline will still run to completion.

Wenn next bei Ereignishandlern nicht aufgerufen wird, wird das Ereignis abgebrochen, was ein deutlich anderes Ergebnis als das Überspringen der Logik durch die Middleware ist.For event handlers, not calling next means that the event is cancelled, which is a significantly different result than middleware skipping logic. Wenn der Rest des Ereignisses nicht verarbeitet wird, sendet der Adapter es nicht.By not processing the rest of the event, the adapter never sends it.

Tipp

Stellen Sie sicher, dass es dem gewünschten Verhalten entspricht, wenn Sie für ein Antwortereignis wie SendActivities einen Kurzschluss durchführen.If you do short-circuit a response event, such as SendActivities, be sure it's the behavior you intend. Andernfalls kann es schwierig sein, Fehler zu beheben.Otherwise, it can result in difficult to fix bugs.

AntwortereignishandlerResponse event handlers

Zusätzlich zur Anwendungs- und Middlewarelogik können Antworthandler (manchmal auch als Ereignishandler oder Aktivitätsereignishandler bezeichnet) dem Kontextobjekt hinzugefügt werden.In addition to the application and middleware logic, response handlers (also sometimes referred to as event handlers, or activity event handlers) can be added to the context object. Diese Ereignishandler werden aufgerufen, wenn die dazugehörige Antwort im aktuellen Kontextobjekt vor der Ausführung der tatsächlichen Antwort stattfindet.These handlers are called when the associated response happens on the current context object, before executing the actual response. Diese Handler sind nützlich, wenn Sie wissen, dass Sie vor oder nach dem eigentlichen Ereignis etwas für jede Aktivität dieses Typs für den Rest der aktuellen Antwort tun wollen.These handlers are useful when you know you'll want to do something, either before or after the actual event, for every activity of that type for the rest of the current response.

Warnung

Achten Sie darauf, eine Aktivitätsantwortmethode nicht in ihrem jeweiligen Antwortereignishandler aufzurufen, z. B. indem Sie die SendActivity-Methode in einem onSendActivity-Handler aufrufen.Be careful to not call an activity response method from within its respective response event handler, for example, calling the send activity method from within an on send activity handler. Anderenfalls wird eine Endlosschleife generiert.Doing so can generate an infinite loop.

Beachten Sie, dass jede neue Aktivität einen neuen Thread für die Ausführung erhält.Remember, each new activity gets a new thread to execute on. Wenn der Thread zur Verarbeitung der Aktivität erstellt wird, wird die Liste der Handler für diese Aktivität in den neuen Thread kopiert.When the thread to process the activity is created, the list of handlers for that activity is copied to that new thread. Handler, die nach diesem Punkt hinzugefügt wurden, werden für dieses spezielle Aktivitätsereignis nicht ausgeführt.No handlers added after that point will be executed for that specific activity event. Die unter einem Kontextobjekt registrierten Handler werden auf eine Weise verarbeitet, die der Verwaltung der Middlewarepipeline durch den Adapter sehr ähnelt.The handlers registered on a context object are handled very similarly to how the adapter manages the middleware pipeline. Handler werden daher in der Reihenfolge aufgerufen, in der sie hinzugefügt wurden, und der Aufruf des nächsten Delegaten übergibt die Steuerung an den nächsten registrierten Ereignishandler.Namely, handlers get called in the order they're added, and calling the next delegate passes control to the next registered event handler. Wenn ein Handler den nächsten Delegaten nicht aufruft, wird keiner der nachfolgenden Ereignishandler aufgerufen, die Ereignis Kurzleitungen, und der Adapter sendet die Antwort nicht an den Kanal.If a handler doesn't call the next delegate, none of the subsequent event handlers are called, the event short circuits, and the adapter does not send the response to the channel.

Verarbeiten des Zustands in MiddlewareHandling state in middleware

Eine gängige Methode zum Speichern des Zustands ist das Aufrufen der „save changes“-Methode am Ende des Turn-Handlers.A common method to save state is to call the save changes method at the end of the turn handler. Hier ist ein Diagramm angegeben, in dem der Schwerpunkt auf dem Aufruf liegt.Here is a diagram with a focus on the call.

Zustand der Middleware – Probleme

Das Problem bei diesem Ansatz ist, dass alle Zustands Aktualisierungen aus einer benutzerdefinierten Middleware, die nach dem Zurückgeben des bot-Handlers erfolgt, nicht im permanenten Speicher gespeichert werden.The problem with this approach is that any state updates made from some custom middleware that happens after the bot's turn handler has returned will not be saved to durable storage. Die Lösung besteht darin, den Aufruf der SaveChanges-Methode zu verschieben und nach dem Abschluss der benutzerdefinierten Middleware auszuführen. Dazu wird eine Instanz der auto-save changes-Middleware am Anfang des Middlewarestapels oder spätestens vor der Middleware, die den Zustand möglicherweise aktualisiert, hinzugefügt.The solution is to move the call to the save changes method to after the custom middleware has completed by adding an instance of the auto-save changes middleware to the beginning of the middleware stack, or at least before any of the middleware that might update state. Die Ausführung ist unten dargestellt.The execution is shown below.

Zustand der Middleware – Lösung

Fügen Sie die Objekte für die Zustandsverwaltung hinzu, die eine Aktualisierung eines BotStateSet-Objekts erfordern, und verwenden Sie diese dann, wenn Sie Ihre „auto-save changes“-Middleware erstellen.Add the state management objects that will need updating to a bot state set object, and then use that when you create your auto-save changes middleware.

Zusätzliche RessourcenAdditional resources

Sie können sich die Middleware für die Transkriptprotokollierung ansehen, die im Bot Framework SDK implementiert ist [C# | JS].You can take a look at the transcript logger middleware, as implemented in the Bot Framework SDK [C# | JS].