Sdílet prostřednictvím


Přiřazování zpráv metodám podle elementu těla

Ukázka AdvancedDispatchByBody ukazuje, jak implementovat alternativní algoritmus pro přiřazování příchozích zpráv k operacím.

Ve výchozím nastavení dispečer modelu služby vybere odpovídající metodu zpracování příchozí zprávy na základě hlavičky WS-Adresování "Akce" zprávy nebo ekvivalentních informací v požadavku HTTP SOAP.

Některé zásobníky webových služeb SOAP 1.1, které nedodržují pravidla základního profilu WS-I 1.1, neodesílají zprávy na základě identifikátoru URI akce, ale spíše na základě kvalifikovaného názvu XML prvního prvku uvnitř těla SOAP. Podobně může klientská strana těchto zásobníků odesílat zprávy s prázdnou nebo libovolnou hlavičkou HTTP SoapAction, která byla povolena specifikací SOAP 1.1.

Pokud chcete změnit způsob odesílání zpráv do metod, ukázka implementuje IDispatchOperationSelector rozhraní rozšiřitelnosti na rozhraní DispatchByBodyElementOperationSelector. Tato třída vybere operace na základě prvního prvku textu zprávy.

Konstruktor třídy očekává slovník naplněný dvojicemi XmlQualifiedName a řetězci, přičemž kvalifikované názvy označují název prvního podřízeného textu SOAP a řetězce označují odpovídající název operace. Je defaultOperationName název operace, která přijímá všechny zprávy, které nelze spárovat s tímto slovníkem:

class DispatchByBodyElementOperationSelector : IDispatchOperationSelector
{
    Dictionary<XmlQualifiedName, string> dispatchDictionary;
    string defaultOperationName;

    public DispatchByBodyElementOperationSelector(Dictionary<XmlQualifiedName,string> dispatchDictionary, string defaultOperationName)
    {
        this.dispatchDictionary = dispatchDictionary;
        this.defaultOperationName = defaultOperationName;
    }
}

IDispatchOperationSelector implementace jsou velmi jednoduché k sestavení, protože existuje pouze jedna metoda v rozhraní: SelectOperation. Úkolem této metody je zkontrolovat příchozí zprávu a vrátit řetězec, který se rovná názvu metody pro kontrakt služby pro aktuální koncový bod.

V této ukázce získá selektor XmlDictionaryReader operace text příchozí zprávy pomocí GetReaderAtBodyContents. Tato metoda již umístí čtenáře do prvního podřízeného textu zprávy, aby bylo dostačující získat název aktuálního prvku a identifikátor URI oboru názvů a zkombinovat je do XmlQualifiedName toho, který se pak použije k vyhledání odpovídající operace ze slovníku, který je uložen volič operace.

public string SelectOperation(ref System.ServiceModel.Channels.Message message)
{
    XmlDictionaryReader bodyReader = message.GetReaderAtBodyContents();
    XmlQualifiedName lookupQName = new
       XmlQualifiedName(bodyReader.LocalName, bodyReader.NamespaceURI);
    message = CreateMessageCopy(message,bodyReader);
    if (dispatchDictionary.ContainsKey(lookupQName))
    {
         return dispatchDictionary[lookupQName];
    }
    else
    {
        return defaultOperationName;
    }
}

Přístup k textu zprávy s jinými metodami GetReaderAtBodyContents , které poskytují přístup k obsahu textu zprávy, způsobí, že zpráva bude označena jako "přečtená", což znamená, že zpráva je neplatná pro jakékoli další zpracování. Proto selektor operace vytvoří kopii příchozí zprávy s metodou zobrazenou v následujícím kódu. Vzhledem k tomu, že se pozice čtenáře během kontroly nezměnila, může na ni odkazovat nově vytvořená zpráva, na kterou se také zkopírují vlastnosti zprávy a záhlaví zprávy, což vede k přesnému klonování původní zprávy:

private Message CreateMessageCopy(Message message,
                                     XmlDictionaryReader body)
{
    Message copy = Message.CreateMessage(message.Version,message.Headers.Action,body);
    copy.Headers.CopyHeaderFrom(message,0);
    copy.Properties.CopyProperties(message.Properties);
    return copy;
}

Přidání selektoru operace do služby

Selektory operací odeslání služby jsou rozšíření dispečeru WCF (Windows Communication Foundation). Pro výběr metod v kanálu zpětného volání duplexních kontraktů existují také selektory operací klienta, které fungují velmi podobně jako selektory operací odeslání popsané zde, ale které nejsou výslovně popsány v této ukázce.

Stejně jako většina rozšíření modelu služby se do dispečera přidávají selektory operací odesílání pomocí chování. Chování je objekt konfigurace, který buď přidá jedno nebo více rozšíření do modulu runtime dispatch (nebo do modulu runtime klienta), nebo jinak změní jeho nastavení.

Vzhledem k tomu, že selektory operací mají rozsah kontraktu, je vhodné chování implementovat zde .IContractBehavior Vzhledem k tomu, že rozhraní je implementováno v Attribute odvozené třídě, jak je znázorněno v následujícím kódu, chování lze deklarativním způsobem přidat do libovolného kontraktu služby. ServiceHost Při každém otevření a sestavení modulu runtime dispečera se všechna chování nalezená buď jako atributy u kontraktů, operací a implementací služeb, nebo jako element v konfiguraci služby se automaticky přidají a následně se zobrazí výzva k přispívání rozšíření nebo úpravě výchozí konfigurace.

Pro stručnost ukazuje následující výňatek kódu pouze implementaci metody ApplyDispatchBehavior, což má vliv na změny konfigurace dispečera v této ukázce. Ostatní metody se nezobrazují, protože se vrátí volajícímu, aniž by prováděly žádnou práci.

[AttributeUsage(AttributeTargets.Class|AttributeTargets.Interface)]
class DispatchByBodyElementBehaviorAttribute : Attribute, IContractBehavior
{
    // public void AddBindingParameters(...)
    // public void ApplyClientBehavior(...)
    // public void Validate(...)

ApplyDispatchBehavior Nejprve implementace nastaví vyhledávací slovník pro selektor operace iterací prvků OperationDescription v koncovém bodu ContractDescriptionslužby . Popis každé operace se pak zkontroluje za přítomnost DispatchBodyElementAttribute chování, což je implementace IOperationBehavior , která je definována také v této ukázce. I když je tato třída také chování, je pasivní a aktivně nepřispívá žádné změny konfigurace do modulu runtime dispatch. Všechny jeho metody se vrátí volajícímu bez provedení jakýchkoli akcí. Chování operace existuje pouze tak, aby metadata požadovaná pro nový mechanismus odeslání, konkrétně kvalifikovaný název prvku těla, na jehož výskytu je vybrána operace, mohou být přidružena k příslušným operacím.

Pokud se takové chování najde, přidá se do slovníku pár hodnot vytvořený z kvalifikovaného názvu XML (QName vlastnosti) a název operace (Name vlastnost).

Po naplnění slovníku se vytvoří nový DispatchByBodyElementOperationSelector s touto informací a nastaví se jako selektor operace modulu runtime dispečeru:

public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.DispatchRuntime dispatchRuntime)
{
    Dictionary<XmlQualifiedName,string> dispatchDictionary =
                     new Dictionary<XmlQualifiedName,string>();
    foreach( OperationDescription operationDescription in
                              contractDescription.Operations )
    {
        DispatchBodyElementAttribute dispatchBodyElement =
   operationDescription.Behaviors.Find<DispatchBodyElementAttribute>();
        if ( dispatchBodyElement != null )
        {
             dispatchDictionary.Add(dispatchBodyElement.QName,
                              operationDescription.Name);
        }
    }
    dispatchRuntime.OperationSelector =
            new DispatchByBodyElementOperationSelector(
               dispatchDictionary,
               dispatchRuntime.UnhandledDispatchOperation.Name);
    }
}

Implementace služby

Chování implementované v této ukázce přímo ovlivňuje, jak se interpretují a odesílají zprávy z drátu, což je funkce kontraktu služby. V důsledku toho by mělo být chování deklarováno na úrovni kontraktu služby v jakékoli implementaci služby, která se rozhodne ji použít.

Ukázka projektové služby použije chování kontraktu DispatchByBodyElementBehaviorAttributeIDispatchedByBody na kontrakt služby a označí každou ze dvou operací OperationForBodyA() a OperationForBodyB() chováním DispatchBodyElementAttribute operace. Při otevření hostitele služby pro službu, která implementuje tuto smlouvu, je tato metadata vyzvednuta tvůrcem dispečera, jak jsme popsali dříve.

Vzhledem k tomu, že selektor operace odesílá výhradně na základě základního prvku zprávy a ignoruje "Action", je nutné, aby modul runtime nekontroluje hlavičku Akce u vrácených odpovědí přiřazením zástupného znaku "*" vlastnosti ReplyActionOperationContractAttribute. Kromě toho je nutné mít výchozí operaci, která má vlastnost "Action" nastavenou na zástupný znak "*". Výchozí operace přijímá všechny zprávy, které nelze odeslat a nemá DispatchBodyElementAttribute:

[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples"),
                            DispatchByBodyElementBehavior]
public interface IDispatchedByBody
{
    [OperationContract(ReplyAction="*"),
     DispatchBodyElement("bodyA","http://tempuri.org")]
    Message OperationForBodyA(Message msg);
    [OperationContract(ReplyAction = "*"),
     DispatchBodyElement("bodyB", "http://tempuri.org")]
    Message OperationForBodyB(Message msg);
    [OperationContract(Action="*", ReplyAction="*")]
    Message DefaultOperation(Message msg);
}

Implementace ukázkové služby je jednoduchá. Každá metoda zabalí přijatou zprávu do zprávy odpovědi a vrátí ji zpět klientovi.

Spuštění a sestavení ukázky

Při spuštění ukázky se základní obsah odpovědí operace zobrazí v okně konzoly klienta podobně jako následující (formátovaný) výstup.

Klient odešle do služby tři zprávy, jejichž základní prvek obsahu je pojmenován bodyA, bodyBa bodyX, v uvedeném pořadí. Jak je možné odložit od předchozího popisu a zobrazený kontrakt služby, příchozí zpráva s bodyA prvkem je odeslána do OperationForBodyA() metody. Vzhledem k tomu, že neexistuje žádný explicitní cíl odeslání zprávy s bodyX základním prvkem, zpráva je odeslána do objektu DefaultOperation(). Každá z operací služby zabalí přijatý text zprávy do prvku specifického pro metodu a vrátí ho, což se provádí ke korelaci vstupních a výstupních zpráv jasně pro tuto ukázku:

<?xml version="1.0" encoding="IBM437"?>
<replyBodyA xmlns="http://tempuri.org">
   <q:bodyA xmlns:q="http://tempuri.org">test</q:bodyA>
</replyBodyA>
<?xml version="1.0" encoding="IBM437"?>
<replyBodyB xmlns="http://tempuri.org">
  <q:bodyB xmlns:q="http://tempuri.org">test</q:bodyB>
</replyBodyB>
<?xml version="1.0" encoding="IBM437"?>
<replyDefault xmlns="http://tempuri.org">
   <q:bodyX xmlns:q="http://tempuri.org">test</q:bodyX>
</replyDefault>

Nastavení, sestavení a spuštění ukázky

  1. Ujistěte se, že jste pro ukázky windows Communication Foundation provedli jednorázovou instalační proceduru.

  2. Pokud chcete sestavit řešení, postupujte podle pokynů v části Sestavení ukázek Windows Communication Foundation.

  3. Pokud chcete spustit ukázku v konfiguraci s jedním nebo více počítači, postupujte podle pokynů v části Spuštění ukázek windows Communication Foundation.