NachrichteninspektorenMessage Inspectors

In diesem Beispiel wird veranschaulicht, wie Client- und Dienstnachrichteninspektoren implementiert und konfiguriert werden.This sample demonstrates how to implement and configure client and service message inspectors.

Ein Nachrichteninspektor ist ein erweiterbares Objekt, das programmgesteuert in der Clientlaufzeit und Dispatchlaufzeit des Dienstmodels oder durch Konfiguration verwendet werden kann. Außerdem kann es Nachrichten nach dem Empfang oder vor dem Versand überprüfen und ändern.A message inspector is an extensibility object that can be used in the service model's client runtime and dispatch runtime programmatically or through configuration and that can inspect and alter messages after they are received or before they are sent.

In diesem Beispiel wird ein Überprüfungsmechanismus für grundlegende Client- und Dienstnachrichten implementiert, der eingehende Nachrichten anhand eines Satzes von konfigurierbaren XML-Schemadokumenten überprüft.This sample implements a basic client and service message validation mechanism that validates incoming messages against a set of configurable XML Schema documents. Beachten Sie, dass in diesem Beispiel keine Nachrichten für jeden Vorgang überprüft werden.Note that this sample does not validate messages for each operation. Diese Vereinfachung ist beabsichtigt.This is an intentional simplification.

NachrichteninspektorMessage Inspector

Clientnachrichteninspektoren implementieren die IClientMessageInspector-Schnittstelle, und Dienstnachrichteninspektoren implementieren die IDispatchMessageInspector-Schnittstelle.Client message inspectors implement the IClientMessageInspector interface and service message inspectors implement the IDispatchMessageInspector interface. Die Implementierungen können in einer Klasse zusammengefasst werden, um einen Nachrichteninspektor zu bilden, der für beide Seiten funktioniert.The implementations can be combined into a single class to form a message inspector that works for both sides. In diesem Beispiel wird so ein kombinierter Nachrichteninspektor implementiert.This sample implements such a combined message inspector. Der Inspektor wird erstellt und übergibt einen Schemasatz, anhand dessen eingehende und ausgehende Nachrichten überprüft werden. Außerdem kann der Entwickler festlegen, ob eingehende oder ausgehende Nachrichten überprüft werden und ob der Inspektor sich im Dispatch- oder Clientmodus befindet. Diese letzte Einstellung beeinflusst die Fehlerbehandlung, die später in diesem Thema erläutert wird.The inspector is constructed passing in a set of schemas against which incoming and outgoing messages are validated and allows the developer to specify whether incoming or outgoing messages are validated and whether the inspector is in dispatch or client mode, which affects the error handling as discussed later in this topic.

public class SchemaValidationMessageInspector : IClientMessageInspector, IDispatchMessageInspector  
{  
    XmlSchemaSet schemaSet;  
    bool validateRequest;  
    bool validateReply;  
    bool isClientSide;  
    [ThreadStatic]  
    bool isRequest;  

    public SchemaValidationMessageInspector(XmlSchemaSet schemaSet,  
         bool validateRequest, bool validateReply, bool isClientSide)  
    {  
        this.schemaSet = schemaSet;  
        this.validateReply = validateReply;  
        this.validateRequest = validateRequest;  
        this.isClientSide = isClientSide;  
    }  

Jeder Dienstnachrichteninspektor (Dienstverteilernachrichteninspektor) muss die beiden IDispatchMessageInspector-Methoden AfterReceiveRequest und BeforeSendReply(Message, Object) implementieren.Any service (dispatcher) message inspector must implement the two IDispatchMessageInspector methods AfterReceiveRequest and BeforeSendReply(Message, Object).

AfterReceiveRequest wird vom Verteiler aufgerufen, wenn eine Nachricht empfangen, durch den Kanalstapel verarbeitet und einem Dienst zugeordnet wurde, jedoch bevor sie deserialisiert und an einen Vorgang verteilt wurde.AfterReceiveRequest is invoked by the dispatcher when a message has been received, processed by the channel stack and assigned to a service, but before it is deserialized and dispatched to an operation. Wenn die eingehende Nachricht verschlüsselt war, ist die Nachricht bereits entschlüsselt, wenn sie den Nachrichteninspektor erreicht.If the incoming message was encrypted, the message is already decrypted when it reaches the message inspector. Die Methode ruft die request-Nachricht ab, die als Verweisparameter übergeben wurde. Dadurch kann die Nachricht nach Bedarf überprüft, bearbeitet oder ersetzt werden.The method gets the request message passed as a reference parameter, which allows the message to be inspected, manipulated or replaced as required. Der Rückgabewert kann jedes Objekt sein und wird als Korrelationsstatusobjekt verwendet, dass an BeforeSendReply übergeben wird, wenn der Dienst eine Antwort auf eine aktuelle Nachricht zurückgibt.The return value can be any object and is used as a correlation state object that is passed to BeforeSendReply when the service returns a reply to the current message. In diesem Beispiel delegiert AfterReceiveRequest die Inspektion (Überprüfung) der Nachricht an eine private, lokale Methode ValidateMessageBody und gibt kein Korrelationsstatusobjekt zurück.In this sample, AfterReceiveRequest delegates the inspection (validation) of the message to the private, local method ValidateMessageBody and returns no correlation state object. Diese Methode stellt sicher, dass keine ungültigen Nachrichten an den Dienst übergeben werden.This method ensures that no invalid messages pass into the service.

object IDispatchMessageInspector.AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)  
{  
    if (validateRequest)  
    {  
        // inspect the message. If a validation error occurs,  
        // the thrown fault exception bubbles up.  
        ValidateMessageBody(ref request, true);  
    }  
    return null;  
}  

BeforeSendReply(Message, Object) wird immer dann aufgerufen, wenn eine Antwort zum Versenden zurück an einen Client bereit ist, oder bei unidirektionalen Nachrichten, wenn die eingehende Nachricht verarbeitet wurde.BeforeSendReply(Message, Object) is invoked whenever a reply is ready to be sent back to a client, or in the case of one-way messages, when the incoming message has been processed. Dadurch können sich Erweiterungen darauf verlassen, unabhängig von MEP symmetrisch aufgerufen zu werden.This allows extensions to count on being called symmetrically, regardless of MEP. Wie bei AfterReceiveRequest wird die Nachricht als Verweisparameter übergeben und kann überprüft, bearbeitet oder ersetzt werden.As with AfterReceiveRequest, the message is passed as a reference parameter and can be inspected, modified or replaced. Die in diesem Beispiel durchgeführte Überprüfung der Nachricht wird ebenfalls an die ValidMessageBody-Methode delegiert, die Behandlung der Validierungsfehler erfolgt in diesem Fall jedoch etwas anders.The validation of the message that is performed in this sample is again delegated to the ValidMessageBody method, but the handling of validation errors is slightly different in this case.

Wenn ein Validierungsfehler beim Dienst auftritt, löst die ValidateMessageBody-Methode von FaultException abgeleitete Ausnahmen aus.If a validation error occurs on the service, the ValidateMessageBody method throws FaultException-derived exceptions. In der AfterReceiveRequest-Methode können diese Ausnahmen in der Infrastruktur des Dienstmodells abgelegt werden, wo sie automatisch in SOAP-Fehler umgewandelt und an den Client weitergeleitet werden.In AfterReceiveRequest, these exceptions can be put into the service model infrastructure where they are automatically transformed into SOAP faults and relayed to the client. In der BeforeSendReply-Methode dürfen FaultException-Ausnahmen nicht in der Infrastruktur abgelegt werden, da die Transformation der vom Dienst ausgelösten Fehlerausnahmen vor dem Aufrufen des Nachrichteninspektors erfolgt.In BeforeSendReply, FaultException exceptions must not be put into the infrastructure, because the transformation of fault exceptions thrown by the service occurs before the message inspector is called. Die folgende Implementierung erfasst deshalb die bekannte ReplyValidationFault-Ausnahme und ersetzt die Antwortnachricht durch eine explizite Fehlermeldung.Therefore the following implementation catches the known ReplyValidationFault exception and replaces the reply message with an explicit fault message. Diese Methode stellt sicher, dass keine ungültigen Nachrichten von der Dienstimplementierung zurückgegeben werden.This method ensures that no invalid messages are returned by the service implementation.

void IDispatchMessageInspector.BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)  
{  
    if (validateReply)  
    {  
        // Inspect the reply, catch a possible validation error   
        try  
        {  
            ValidateMessageBody(ref reply, false);  
        }  
        catch (ReplyValidationFault fault)  
        {  
            // if a validation error occurred, the message is replaced  
            // with the validation fault.  
            reply = Message.CreateMessage(reply.Version,   
                    fault.CreateMessageFault(), reply.Headers.Action);  
        }  
    }  

Der Clientnachrichteninspektor ist sehr ähnlich.The client message inspector is very similar. Die beiden Methoden, die von IClientMessageInspector implementiert werden müssen, lauten AfterReceiveReply und BeforeSendRequest.The two methods that must be implemented from IClientMessageInspector are AfterReceiveReply and BeforeSendRequest.

BeforeSendRequest wird aufgerufen, wenn die Nachricht entweder von der Clientanwendung oder vom Vorgangsformatierer erstellt wurde.BeforeSendRequest is invoked when the message has been composed either by the client application or by the operation formatter. Wie bei Verteilernachrichteninspektoren kann die Nachricht entweder nur überprüft oder vollständig ersetzt werden.As with the dispatcher message inspectors, the message can just be inspected or entirely replaced. In diesem Beispiel delegiert der Inspektor dieselbe lokale ValidateMessageBody-Hilfsmethode, die auch für Verteilernachrichteninspektoren verwendet wird.In this sample, the inspector delegates to the same local ValidateMessageBody helper method that is also used for the dispatch message inspectors.

Die Verhaltensunterschiede zwischen Client- und die Dienstüberprüfung (wie im Konstruktor festgelegt) bestehen darin, dass die Clientüberprüfung lokale Ausnahmen, die im Benutzercode abgelegt sind, auslöst, weil sie lokal auftreten und nicht aufgrund eines Dienstausfalls.The behavioral difference between the client and service validation (as specified in the constructor) is that the client validation throws local exceptions that are put into the user code because they occur locally and not because of a service failure. Im Allgemeinen gilt, dass Dienstverteilerinspektoren Fehler auslösen und Clientinspektoren Ausnahmen auslösen.Generally, the rule is that service dispatcher inspectors throw faults and that client inspectors throw exceptions.

Diese BeforeSendRequest-Implementierung stellt sicher, dass keine ungültigen Nachrichten an den Dienst gesendet werden.This BeforeSendRequest implementation ensures that no invalid messages are sent to the service.

object IClientMessageInspector.BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)  
{  
    if (validateRequest)  
    {  
        ValidateMessageBody(ref request, true);  
    }  
    return null;  
}  

Die AfterReceiveReply-Implementierung stellt sicher, dass keine ungültigen, vom Dienst empfangenen Nachrichten an den Client-Benutzercode weitergeleitet werden.The AfterReceiveReply implementation ensures that no invalid messages received from the service are relayed to the client user code.

void IClientMessageInspector.AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)  
{  
    if (validateReply)  
    {  
        ValidateMessageBody(ref reply, false);  
    }  
}  

Das Kernstück dieses bestimmten Nachrichteninspektors ist die ValidateMessageBody-Methode.The heart of this particular message inspector is the ValidateMessageBody method. Um seine Funktion auszuführen, umschließt er die Teilstruktur des Textinhalts der weitergeleiteten Nachricht mit einem Validierungs-XmlReader.To perform its work, it wraps a validating XmlReader around the body content sub-tree of the passed message. Der Reader wird mit dem Schemasatz aufgefüllt, den der Nachrichteninspektor enthält und der Validierungsrückruf wird auf einen Delegaten festgelegt, der auf InspectionValidationHandler verweist, der wiederum gemeinsam mit dieser Methode definiert ist.The reader is populated with the set of schemas that the message inspector holds and the validation callback is set to a delegate referring to the InspectionValidationHandler that is defined alongside this method. Um die Validierung auszuführen, wird die Nachricht dann gelesen und in einen Speicherstream-gesicherten XmlDictionaryWriter übertragen.To perform the validation, the message is then read and spooled into a memory stream-backed XmlDictionaryWriter. Wenn ein Validierungsfehler oder eine Warnung im Prozess auftritt, wird die Rückrufmethode aufgerufen.If a validation error or warning occurs in the process, the callback method is invoked.

Wenn kein Fehler auftritt, wird eine neue Nachricht erstellt, die die Eigenschaften und Header der ursprünglichen Nachricht kopiert und das jetzt validierte Infoset im Speicherstream verwendet, der von einem XmlDictionaryReader umschlossen und zur Ersatznachricht hinzugefügt wurde.If no error occurs, a new message is constructed that copies the properties and headers from the original message and uses the now-validated infoset in the memory stream, which is wrapped by an XmlDictionaryReader and added to the replacement message.

void ValidateMessageBody(ref System.ServiceModel.Channels.Message message, bool isRequest)  
{  
    if (!message.IsFault)  
    {  
        XmlDictionaryReaderQuotas quotas =   
                new XmlDictionaryReaderQuotas();  
        XmlReader bodyReader =   
            message.GetReaderAtBodyContents().ReadSubtree();  
        XmlReaderSettings wrapperSettings =   
                              new XmlReaderSettings();  
        wrapperSettings.CloseInput = true;  
        wrapperSettings.Schemas = schemaSet;  
        wrapperSettings.ValidationFlags =   
                                XmlSchemaValidationFlags.None;  
        wrapperSettings.ValidationType = ValidationType.Schema;  
        wrapperSettings.ValidationEventHandler += new   
           ValidationEventHandler(InspectionValidationHandler);  
        XmlReader wrappedReader = XmlReader.Create(bodyReader,   
                                            wrapperSettings);  

        // pull body into a memory backed writer to validate  
        this.isRequest = isRequest;  
        MemoryStream memStream = new MemoryStream();  
        XmlDictionaryWriter xdw =  
              XmlDictionaryWriter.CreateBinaryWriter(memStream);  
        xdw.WriteNode(wrappedReader, false);  
        xdw.Flush(); memStream.Position = 0;  
        XmlDictionaryReader xdr =   
        XmlDictionaryReader.CreateBinaryReader(memStream, quotas);  

        // reconstruct the message with the validated body  
        Message replacedMessage =   
            Message.CreateMessage(message.Version, null, xdr);  
        replacedMessage.Headers.CopyHeadersFrom(message.Headers);  
        replacedMessage.Properties.CopyProperties(message.Properties);  
        message = replacedMessage;  
    }  
}  

Die InspectionValidationHandler-Methode wird immer dann vom validierenden XmlReader aufgerufen, wenn ein Schemavalidierungsfehler oder eine Warnung auftritt.The InspectionValidationHandler method is called by the validating XmlReader whenever a schema validation error or warning occurs. Die folgende Implementierung funktioniert nur mit Fehlern und ignoriert alle Warnungen.The following implementation only works with errors and ignores all warnings.

Auf den ersten Blick scheint es möglich, einen validierenden XmlReader in die Nachricht mit dem Nachrichteninspektor einzufügen und die Validierung bei der Verarbeitung der Nachricht durchzuführen, ohne die Nachricht zu sichern.On first consideration, it might seem possible to inject a validating XmlReader into the message with the message inspector and let the validation happen as the message is processed and without buffering the message. Dies würde jedoch bedeuten, dass dieser Rückruf die Validierungsausnahmen an einem beliebigen Punkt der Dienstmodellinfrastruktur oder des Benutzercodes auslöst, wenn ungültige XML-Knoten erkannt werden. Das kann zu unvorhersehbarem Verhalten führen.That, however, means that this callback throws the validation exceptions somewhere into the service model infrastructure or the user code as invalid XML nodes are detected, resulting in unpredictable behavior. Der Pufferungsansatz schützt den Benutzercode vollständig vor ungültigen Nachrichten.The buffering approach shields the user code from invalid messages, entirely.

Wie bereits erläutert unterscheiden sich die vom Handler ausgelösten Ausnahmen zwischen dem Client und dem Dienst.As previously discussed, the exceptions thrown by the handler differ between the client and the service. Beim Dienst werden die Ausnahmen von FaultException abgeleitet, beim Client sind die Ausnahmen reguläre benutzerdefinierte Ausnahmen.On the service, the exceptions are derived from FaultException, on the client the exceptions are regular custom exceptions.

        void InspectionValidationHandler(object sender, ValidationEventArgs e)  
{  
    if (e.Severity == XmlSeverityType.Error)  
    {  
        // We are treating client and service side validation errors  
        // differently here. Client side errors cause exceptions  
        // and are thrown straight up to the user code. Service side  
        // validations cause faults.  
        if (isClientSide)  
        {  
            if (isRequest)  
            {  
                throw new RequestClientValidationException(e.Message);  
            }  
            else  
            {  
                throw new ReplyClientValidationException(e.Message);  
            }  
        }  
        else  
        {  
            if (isRequest)  
            {  
                // this fault is caught by the ServiceModel   
                // infrastructure and turned into a fault reply.  
                throw new RequestValidationFault(e.Message);  
             }  
             else  
             {  
                // this fault is caught and turned into a fault message  
                // in BeforeSendReply in this class  
                throw new ReplyValidationFault(e.Message);  
              }  
          }  
      }  
    }  

VerhaltenBehavior

Nachrichteninspektoren sind Erweiterungen zur Clientlaufzeit oder der Dispatchlaufzeit.Message inspectors are extensions to the client runtime or the dispatch runtime. Solche Erweiterungen werden mithilfe von konfiguriert Verhalten.Such extensions are configured using behaviors. Eine Verhaltensweise ist eine Klasse, die das Verhalten der Dienstmodelllaufzeit ändert, indem sie die Standardkonfiguration ändert oder Erweiterungen (wie Nachrichteninspektoren) hinzufügt.A behavior is a class that changes the behavior of the service model runtime by changing the default configuration or adding extensions (such as message inspectors) to it.

Bei der folgenden SchemaValidationBehavior-Klasse handelt es sich um die Verhaltensweise, mit der der Nachrichteninspektor dieses Beispiels zur Client- oder Dispatchlaufzeit hinzugefügt wird.The following SchemaValidationBehavior class is the behavior used to add this sample's message inspector to the client or dispatch runtime. Die Implementierung ist in beiden Fällen ganz einfach.The implementation is rather basic in both cases. In ApplyClientBehavior und ApplyDispatchBehavior wird der Nachrichteninspektor erstellt und zur MessageInspectors-Auflistung der entsprechenden Laufzeit hinzugefügt.In ApplyClientBehavior and ApplyDispatchBehavior, the message inspector is created and added to the MessageInspectors collection of the respective runtime.

public class SchemaValidationBehavior : IEndpointBehavior  
{  
    XmlSchemaSet schemaSet;   
    bool validateRequest;   
    bool validateReply;  

    public SchemaValidationBehavior(XmlSchemaSet schemaSet, bool   
                           inspectRequest, bool inspectReply)  
    {  
        this.schemaSet = schemaSet;  
        this.validateReply = inspectReply;  
        this.validateRequest = inspectRequest;  
    }  
    #region IEndpointBehavior Members  

    public void AddBindingParameters(ServiceEndpoint endpoint,   
       System.ServiceModel.Channels.BindingParameterCollection   
                                            bindingParameters)  
    {  
    }  

    public void ApplyClientBehavior(ServiceEndpoint endpoint,   
            System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)  
    {  
        SchemaValidationMessageInspector inspector =   
           new SchemaValidationMessageInspector(schemaSet,   
                      validateRequest, validateReply, true);  
            clientRuntime.MessageInspectors.Add(inspector);  
    }  

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint,   
         System.ServiceModel.Dispatcher.EndpointDispatcher   
                                          endpointDispatcher)  
    {  
        SchemaValidationMessageInspector inspector =   
           new SchemaValidationMessageInspector(schemaSet,   
                        validateRequest, validateReply, false);  
   endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);  
    }  

   public void Validate(ServiceEndpoint endpoint)  
   {  
   }  

    #endregion  
}  

Hinweis

Diese bestimmte Verhaltensweise tritt nicht als Attribut auf und kann deshalb nicht deklarativ zu einem Vertragstyp eines Diensttyps hinzugefügt werden.This particular behavior does not double as an attribute and therefore cannot be added declaratively onto a contract type of a service type. Diese Entscheidung wurde absichtlich getroffen, da die Schemaauflistung nicht in einer Attributdeklaration geladen werden kann und für den Verweis auf einen gesonderten Konfigurationsspeicherort (z. B. auf die Anwendungseinstellungen) in diesem Attribut müsste ein Konfigurationselement erstellt werden, dass nicht mit der restlichen Dienstmodellkonfiguration konsistent ist.This is a by-design decision made because the schema collection cannot be loaded in an attribute declaration and referring to an extra configuration location (for instance to the application settings) in this attribute means creating a configuration element that is not consistent with the rest of the service model configuration. Deshalb kann diese Verhaltensweise nur zwingend über Code und eine Erweiterung der Dienstmodellkonfiguration hinzugefügt werden.Therefore, this behavior can only be added imperatively through code and through a service model configuration extension.

Hinzufügen des Nachrichteninspektors durch KonfigurationAdding the Message Inspector through Configuration

Für das Konfigurieren einer benutzerdefinierten Verhaltensweise an einem Endpunkt in der Anwendungskonfigurationsdatei, benötigt das Dienstmodell Implementierungen, um eine Konfiguration erstellen Erweiterungselement dargestellt, die von einer abgeleiteten Klasse BehaviorExtensionElement.For configuring a custom behavior on an endpoint in the application configuration file, the service model requires implementers to create a configuration extension element represented by a class derived from BehaviorExtensionElement. Diese Erweiterung muss dann zum Konfigurationsabschnitt für Erweiterungen des Dienstmodells hinzugefügt werden, wie für die folgende in diesem Abschnitt erläuterte Erweiterung gezeigt.This extension must then be added to the service model's configuration section for extensions as shown for the following extension discussed in this section.

<system.serviceModel>  
…  
   <extensions>  
      <behaviorExtensions>  
        <add name="schemaValidator" type="Microsoft.ServiceModel.Samples.SchemaValidationBehaviorExtensionElement, MessageInspectors, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>  
      </behaviorExtensions>  
    </extensions>  
…  
</system.serviceModel>  

Erweiterungen können entweder in der Anwendungs- oder der ASP.NET-Konfigurationsdatei (häufigste Auswahl) oder in der Konfigurationsdatei für den Computer hinzugefügt werden.Extensions can be added in the application or ASP.NET configuration file, which is the most common choice, or in the machine configuration file.

Wenn die Erweiterung zu einem Konfigurationsbereich hinzugefügt wird, kann die Verhaltensweise zu einer Verhaltenskonfiguration hinzugefügt werden, wie in folgendem Code gezeigt.When the extension is added to a configuration scope, the behavior can be added to a behavior configuration as it is shown in the following code. Verhaltenskonfigurationen sind wiederverwendbare Elemente, die nach Bedarf auf mehrere Endpunkte angewendet werden können.Behavior configurations are reusable elements that can be applied to multiple endpoints as required. Da die bestimmte Verhaltensweise, die hier konfiguriert werden soll, IEndpointBehavior implementiert, ist sie nur im entsprechenden Konfigurationsbereich in der Konfigurationsdatei gültig.Because the particular behavior to be configured here implements IEndpointBehavior, it is only valid in the respective configuration section in the configuration file.

<system.serviceModel>  
   <behaviors>  
      …  
     <endpointBehaviors>  
        <behavior name="HelloServiceEndpointBehavior">  
          <schemaValidator validateRequest="True" validateReply="True">  
            <schemas>  
              <add location="messages.xsd" />    
            </schemas>  
          </schemaValidator>  
        </behavior>  
      </endpointBehaviors>  
      …  
    </behaviors>  
</system.serviceModel>  

Das <schemaValidator>-Element, das den Nachrichteninspektor konfiguriert, wird von der SchemaValidationBehaviorExtensionElement-Klasse unterstützt.The <schemaValidator> element that configures the message inspector is backed by the SchemaValidationBehaviorExtensionElement class. Die Klasse macht zwei öffentliche boolesche Eigenschaften namens ValidateRequest und ValidateReply verfügbar.The class exposes two Boolean public properties named ValidateRequest and ValidateReply. Beide Eigenschaften sind mit einem ConfigurationPropertyAttribute gekennzeichnet.Both of these are marked with a ConfigurationPropertyAttribute. Dieses Attribut bildet die Verknüpfung zwischen den Codeeigenschaften und den XML-Attributen, die im vorangehenden XML-Konfigurationselement sichtbar sind.This attribute constitutes the link between the code properties and the XML attributes that can be seen on the preceding XML configuration element. Die Klasse verfügt auch über eine Eigenschaft Schemas, die zusätzlich mit dem ConfigurationCollectionAttribute gekennzeichnet und vom Typ SchemaCollection ist. Diese Eigenschaft ist ebenfalls Teil des Beispiels, ist aber zur besseren Übersichtlichkeit nicht in diesem Dokument enthalten.The class also has a property Schemas that is additionally marked with the ConfigurationCollectionAttribute and is of the type SchemaCollection, which is also part of this sample but omitted from this document for brevity. Diese Eigenschaft unterstützt zusammen mit der Auflistung und der Auflistelementklasse SchemaConfigElement das <schemas>-Element im vorangehenden Konfigurationsausschnitt und ermöglicht das Hinzufügen einer Schemaauflistung zum Validierungssatz.This property along with the collection and the collection element class SchemaConfigElement backs the <schemas> element in the preceding configuration snippet and allows adding a collection of schemas to the validation set.

Die überschriebene CreateBehavior-Methode wandelt die Konfigurationsdaten in ein Verhaltensobjekt um, wenn die Laufzeit die Konfigurationsdaten beim Erstellen eines Clients oder Endpunkts bewertet.The overridden CreateBehavior method turns the configuration data into a behavior object when the runtime evaluates the configuration data as it builds a client or an endpoint.

public class SchemaValidationBehaviorExtensionElement : BehaviorExtensionElement  
{  
    public SchemaValidationBehaviorExtensionElement()  
    {  
    }  

    public override Type BehaviorType   
    {   
        get  
        {  
            return typeof(SchemaValidationBehavior);  
        }   
    }  

    protected override object CreateBehavior()  
    {  
        XmlSchemaSet schemaSet = new XmlSchemaSet();  
        foreach (SchemaConfigElement schemaCfg in this.Schemas)  
        {  
            Uri baseSchema = new   
                Uri(AppDomain.CurrentDomain.BaseDirectory);  
            string location = new   
                Uri(baseSchema,schemaCfg.Location).ToString();  
            XmlSchema schema =   
                XmlSchema.Read(new XmlTextReader(location), null);  
            schemaSet.Add(schema);  
        }  
     return new   
     SchemaValidationBehavior(schemaSet,ValidateRequest,ValidateReply);  
    }  

[ConfigurationProperty("validateRequest",DefaultValue=false,IsRequired=false)]  
public bool ValidateRequest  
{  
    get { return (bool)base["validateRequest"]; }  
    set { base["validateRequest"] = value; }  
}  

[ConfigurationProperty("validateReply", DefaultValue = false, IsRequired = false)]  
        public bool ValidateReply  
        {  
            get { return (bool)base["validateReply"]; }  
            set { base["validateReply"] = value; }  
        }  

     //Declare the Schema collection property.  
     //Note: the "IsDefaultCollection = false" instructs   
     //.NET Framework to build a nested section of   
     //the kind <Schema> ...</Schema>.  
    [ConfigurationProperty("schemas", IsDefaultCollection = true)]  
    [ConfigurationCollection(typeof(SchemasCollection),  
        AddItemName = "add",  
        ClearItemsName = "clear",  
        RemoveItemName = "remove")]  
    public SchemasCollection Schemas  
    {  
        get  
        {  
            SchemasCollection SchemasCollection =  
            (SchemasCollection)base["schemas"];  
            return SchemasCollection;  
        }  
    }  
}  

Imperatives Hinzufügen von NachrichteninspektorenAdding Message Inspectors Imperatively

Außer über Attribute (was aus dem oben genannten Grund in diesem Beispiel nicht unterstützt wird) und die Konfiguration können Verhaltensweisen relativ einfach mithilfe von imperativem Code zu einem Client oder einer Dienstlaufzeit hinzugefügt werden.Except through attributes (which is not supported in this sample for the reason cited previously) and configuration, behaviors can quite easily be added to a client and service runtime using imperative code. In diesem Beispiel wird dies in der Clientanwendung durchgeführt, um den Clientnachrichteninspektor zu testen.In this sample, this is done in the client application to test the client message inspector. Die GenericClient-Klasse wird von ClientBase<TChannel> abgeleitet, der dem Benutzercode die Endpunktkonfiguration verfügbar macht.The GenericClient class is derived from ClientBase<TChannel>, which exposes the endpoint configuration to the user code. Bevor der Client implizit geöffnet wird, kann die Endpunktkonfiguration geändert werden, z. B. durch Hinzufügen von Verhaltensweisen, wie im folgenden Code dargestellt.Before the client is implicitly opened the endpoint configuration can be changed, for instance by adding behaviors as shown in the following code. Das Hinzufügen von Verhaltensweisen zum Dienst ist in großen Teilen mit der hier dargestellten Clienttechnik vergleichbar und muss vor dem Öffnen des Diensthosts durchgeführt werden.Adding the behavior on the service is largely equivalent to the client technique shown here and must be performed before the service host is opened.

try  
{  
    Console.WriteLine("*** Call 'Hello' with generic client, with client behavior");  
    GenericClient client = new GenericClient();  

    // Configure client programmatically, adding behavior  
    XmlSchema schema = XmlSchema.Read(new StreamReader("messages.xsd"),   
                                                          null);  
    XmlSchemaSet schemaSet = new XmlSchemaSet();  
    schemaSet.Add(schema);  
    client.Endpoint.Behaviors.Add(new   
                SchemaValidationBehavior(schemaSet, true, true));  

    Console.WriteLine("--- Sending valid client request:");  
    GenericCallValid(client, helloAction);  
    Console.WriteLine("--- Sending invalid client request:");  
    GenericCallInvalid(client, helloAction);  

    client.Close();  
}  
catch (Exception e)  
{  
    DumpException(e);  
}  

So können Sie das Beispiel einrichten, erstellen und ausführenTo set up, build, and run the sample

  1. Stellen Sie sicher, dass Sie ausgeführt haben die Setupprozedur für die Windows Communication Foundation-Beispiele zum einmaligen.Ensure that you have performed the One-Time Setup Procedure for the Windows Communication Foundation Samples.

  2. Führen Sie zum Erstellen der Projektmappe die Anweisungen im Erstellen der Windows Communication Foundation-Beispiele.To build the solution, follow the instructions in Building the Windows Communication Foundation Samples.

  3. Um das Beispiel in einer einzelnen oder computerübergreifenden Konfiguration ausführen möchten, folgen Sie den Anweisungen Ausführen der Windows Communication Foundation-Beispiele.To run the sample in a single- or cross-machine configuration, follow the instructions in Running the Windows Communication Foundation Samples.

Wichtig

Die Beispiele sind möglicherweise bereits auf dem Computer installiert.The samples may already be installed on your machine. Suchen Sie nach dem folgenden Verzeichnis (Standardverzeichnis), bevor Sie fortfahren.Check for the following (default) directory before continuing.

<InstallDrive>:\WF_WCF_Samples

Wenn dieses Verzeichnis nicht vorhanden ist, rufen Sie Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) Samples for .NET Framework 4 auf, um alle Windows Communication Foundation (WCF)Windows Communication Foundation (WCF) - und WFWF -Beispiele herunterzuladen.If this directory does not exist, go to Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) Samples for .NET Framework 4 to download all Windows Communication Foundation (WCF)Windows Communication Foundation (WCF) and WFWF samples. Dieses Beispiel befindet sich im folgenden Verzeichnis.This sample is located in the following directory.

<InstallDrive>:\WF_WCF_Samples\WCF\Extensibility\MessageInspectors

Siehe auchSee Also