Aracılığıyla paylaş


Gövde Öğesine Göre Yönlendirme

AdvancedDispatchByBody örneği, gelen iletileri işlemlere atamak için alternatif bir algoritmanın nasıl uygulanduğunu gösterir.

Varsayılan olarak, hizmet modeli dağıtıcısı, iletinin WS-Addressing "Eylem" üst bilgisine veya HTTP SOAP isteğindeki eşdeğer bilgilere göre gelen ileti için uygun işleme yöntemini seçer.

WS-I Temel Profil 1.1 yönergelerine uymayan bazı SOAP 1.1 Web hizmetleri yığınları, eylem URI'sine göre değil, SOAP gövdesindeki ilk öğenin XML nitelenmiş adına göre ileti göndermez. Benzer şekilde, bu yığınların istemci tarafı, SOAP 1.1 belirtiminin izin verdiği boş veya rastgele bir HTTP SoapAction üst bilgisi içeren iletiler gönderebilir.

İletilerin yöntemlere dağıtılma şeklini değiştirmek için, örnek üzerinde IDispatchOperationSelector genişletilebilirlik arayüzünü DispatchByBodyElementOperationSelector uygular. Bu sınıf, ileti gövdesinin ilk öğesine göre işlemleri seçer.

Sınıf oluşturucu, XmlQualifiedName ve dize çiftleriyle doldurulmuş bir sözlük bekler; burada tanımlanmış adlar SOAP gövdesinin ilk alt öğesinin adını, dizeler ise eşleşen işlem adını belirtir. defaultOperationName, bu sözlükle eşleştirilemeyen tüm iletileri alan işlemin adıdır:

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

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

IDispatchOperationSelector arabiriminde yalnızca bir yöntem olduğundan, uygulamaları oluşturmak çok basittir: SelectOperation. Bu yöntemin işi, gelen bir iletiyi incelemek ve geçerli uç nokta için hizmet sözleşmesindeki bir yöntemin adına eşit bir dize döndürmektir.

Bu örnekte, işlem seçici, XmlDictionaryReader kullanarak gelen iletinin gövdesi için bir GetReaderAtBodyContents alır. Bu yöntem, okuyucuyu ileti gövdesinin ilk alt öğesine konumlandırdığı için, geçerli öğenin adını ve ad alanı URI'sini almak ve bunları işlem seçicisinin sakladığı sözlükte ilgili işlemi bulmak için kullanılan bir XmlQualifiedName içinde birleştirmek yeterlidir.

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

İleti gövdesine veya iletinin gövde GetReaderAtBodyContents içeriğine erişim sağlayan diğer yöntemlerden herhangi biriyle erişilmesi, iletinin "okundu" olarak işaretlenmesine neden olur ve bu da iletinin başka işlemler için geçersiz olduğu anlamına gelir. Bu nedenle, işlem seçici aşağıdaki kodda gösterilen yöntemiyle gelen iletinin bir kopyasını oluşturur. İnceleme sırasında okuyucunun konumu değiştirilmediğinden, ileti özellikleri ve ileti üst bilgilerinin de kopyalandığı yeni oluşturulan ileti tarafından başvurulabilir ve bu da özgün iletinin tam bir kopyasıyla sonuçlanır:

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

Hizmete İşlem Seçici Ekleme

Hizmet dağıtım işlemi seçicileri, Windows Communication Foundation (WCF) dağıtıcısının uzantılarıdır. Çift yönlü anlaşmaların geri çağırma kanalında yöntemleri seçmek için, burada açıklanan dağıtım işlemi seçicilerine çok benzeyen ancak bu örnekte açıkça ele alınmayan istemci işlemi seçicileri de vardır.

Çoğu hizmet modeli uzantısında olduğu gibi, gönderme işlemi seçicileri de davranışlar kullanılarak dağıtıcıya eklenir. Davranış, dağıtım çalışma zamanına (veya istemci çalışma zamanına) bir veya daha fazla uzantı ekleyen veya ayarlarını başka bir şekilde değiştiren bir yapılandırma nesnesidir.

İşlem seçicileri sözleşme kapsamına sahip olduğundan, burada uygulanması gereken uygun davranış IContractBehavior'dir. Arabirim, aşağıdaki kodda gösterildiği gibi türetilmiş bir Attribute sınıfa uygulandığından, davranış bildirim temelli olarak herhangi bir hizmet sözleşmesine eklenebilir. Bir ServiceHost açıldığında ve sevk çalışma zamanı oluşturulduğunda, sözleşmeler, işlemler ve hizmet uygulamalarındaki öznitelikler veya hizmet yapılandırmasındaki öğeler olarak bulunan tüm davranışlar otomatik olarak eklenir ve ardından uzantılara katkıda bulunmaları veya varsayılan yapılandırmayı değiştirmeleri istenir.

Kısalık için, aşağıdaki kod alıntısı yalnızca yönteminin ApplyDispatchBehavioruygulamasını gösterir ve bu örnekte dağıtıcı için yapılandırma değişikliklerini etkiler. Diğer yöntemler, herhangi bir iş yapmadan çağırana geri döndükleri için gösterilmez.

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

İlk olarak, ApplyDispatchBehavior uygulama, OperationDescription öğeleri üzerinde iterasyon yaparak hizmet uç noktasının ContractDescription işlem seçicisi için arama sözlüğünü ayarlar. Ardından her işlem açıklaması, bu örnekte de tanımlanmış olan ve DispatchBodyElementAttribute davranışını içeren bir IOperationBehavior uygulamasının varlığı açısından incelenir. Bu sınıf aynı zamanda bir davranış olsa da pasiftir ve dağıtım çalışma zamanına yapılandırma değişikliklerine etkin bir şekilde katkıda bulunmaz. Tüm yöntemler, herhangi bir eylem gerçekleştirmeden çağırana geri döner. İşlem davranışı yalnızca yeni dağıtım mekanizması için gerekli olan meta verilerin ( örneğin, bir işlemin geçtiği gövde öğesinin nitelenmiş adı) ilgili işlemlerle ilişkilendirilmesi için vardır.

Böyle bir davranış bulunursa, XML nitelenmiş adından (QName özelliği) ve işlem adından (Name özelliği) oluşturulan bir değer çifti sözlüğe eklenir.

Sözlük doldurulduktan sonra, bu bilgilerle yeni bir DispatchByBodyElementOperationSelector oluşturulur ve dağıtım çalışma zamanının operasyon seçicisi olarak ayarlanır.

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

Hizmeti Hayata Geçirme

Bu örnekte uygulanan davranış, hizmet sözleşmesinin bir işlevi olan kablodan gelen iletilerin yorumlanıp dağıtılma şeklini doğrudan etkiler. Sonuç olarak davranış, kullanmayı seçen herhangi bir hizmet uygulamasında hizmet sözleşmesi düzeyinde bildirilmelidir.

Örnek proje hizmeti, DispatchByBodyElementBehaviorAttribute sözleşme davranışını IDispatchedByBody hizmet sözleşmesine uygular ve iki işlemi, OperationForBodyA() ve OperationForBodyB(), bir DispatchBodyElementAttribute işlem davranışıyla etiketler. Bu sözleşmeyi uygulayan bir hizmetin hizmet konağı açıldığında, bu meta veriler daha önce açıklandığı gibi dağıtıcı oluşturucu tarafından toplanır.

İşlem seçicisi yalnızca ileti gövdesi öğesini temel alarak gönderildiğinden ve "Eylem"i yoksaydığından, ReplyAction özelliğine "*" joker karakteri atayarak çalışma zamanına, döndürülen yanıtlarda "Eylem" üst bilgisini denetlememesi gerektiğini söylemek gerekir. Ayrıca, "Action" özelliği "*" joker karakterine ayarlanmış varsayılan bir işlem olması gerekir. Varsayılan işlem, gönderilemeyen ve içermeyen DispatchBodyElementAttributetüm iletileri alır:

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

Örnek hizmet uygulaması basittir. Her yöntem alınan iletiyi bir yanıt iletisine sarmalar ve istemciye geri yankılar.

Örnek Uygulamayı Çalıştırma ve Derleme

Örneği çalıştırdığınızda, işlem yanıtlarının gövde içeriği istemci konsolu penceresinde aşağıdaki (biçimlendirilmiş) çıkışa benzer şekilde görüntülenir.

İstemci, gövde içerik öğesi sırasıyla bodyA, bodyB ve bodyX olan hizmete üç ileti gönderir. Önceki açıklamadan ve gösterilen hizmet sözleşmesinden çıkarılabileceği gibi, bodyA öğesiyle gelen ileti, OperationForBodyA() yöntemine gönderilir. gövde öğesiyle bodyX ileti için açık bir gönderim hedefi olmadığından, ileti adresine DefaultOperation()gönderilir. Hizmet işlemlerinin her biri, alınan ileti gövdesini yönteme özgü bir öğeye sarar ve bu, bu örnek için giriş ve çıkış iletilerini net bir şekilde ilişkilendirmek amacıyla onu döndürür.

<?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>

Örneği ayarlamak, derlemek ve çalıştırmak için

  1. Windows Communication Foundation Örnekleri içinOne-Time Kurulum Yordamını yaptığınızdan emin olun.

  2. Çözümü oluşturmak için Windows Communication Foundation Örnekleri Oluşturma başlığındaki yönergeleri izleyin.

  3. Örneği tek bir makine veya makineler arası bir yapılandırmada çalıştırmak için, Windows Communication Foundation örneklerini çalıştırmayönergelerini izleyin.