Gövde Öğesine göre Dağıt
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 Adresleme "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 genişletilebilirlik arabirimini DispatchByBodyElementOperationSelector
uygularIDispatchOperationSelector. Bu sınıf, ileti gövdesinin ilk öğesine göre işlemleri seçer.
Sınıf oluşturucu, ve dize çiftleriyle XmlQualifiedName
doldurulmuş bir sözlük bekler; burada nitelenmiş adlar SOAP gövdesinin ilk alt öğesinin adını, dizeler de eşleşen işlem adını gösterir. 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 kullanarak GetReaderAtBodyContentsgelen iletinin gövdesi için bir XmlDictionaryReader alır. Bu yöntem, okuyucuyu ileti gövdesinin ilk alt öğesine zaten konumlandırır, böylece geçerli öğenin adını ve ad alanı URI'sini almak ve bunları işlem seçicisi tarafından tutulan sözlükten ilgili işlemi aramak için kullanılan bir XmlQualifiedName
içinde birleştirmek yeterli olur.
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 uygulamak için uygun davranış şeklindedir IContractBehavior. 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 gönderme çalışma zamanı oluşturulduğunda, sözleşmeler, işlemler ve hizmet uygulamalarındaki öznitelikler veya hizmet yapılandırmasındaki öğe olarak bulunan tüm davranışlar otomatik olarak eklenir ve daha sonra 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 hizmet uç noktasının ContractDescriptionöğeleri üzerinde OperationDescription yineleme yaparak işlem seçicisi için arama sözlüğü ayarlar. Ardından her işlem açıklaması, bu örnekte de tanımlanan bir uygulama IOperationBehavior olan davranışın varlığı DispatchBodyElementAttribute
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öntemleri, 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 (özellik) ve işlem adından (QName
Name
özellik) oluşturulan bir değer çifti sözlüğe eklenir.
Sözlük doldurulduktan sonra, bu bilgilerle yeni bir yeni DispatchByBodyElementOperationSelector
oluşturulur ve dağıtım çalışma zamanının işlem 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 Uygulama
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, sözleşme davranışını hizmet sözleşmesine uygular DispatchByBodyElementBehaviorAttribute
ve iki işlemin OperationForBodyA()
her birini bir DispatchBodyElementAttribute
OperationForBodyB()
işlem davranışıyla IDispatchedByBody
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şturucusu tarafından alınır.
İşlem seçicisi yalnızca ileti gövdesi öğesini temel alarak gönderildiğinden ve "Eylem"i yoksaydığından, özelliğine "*" joker karakteri atayarak çalışma zamanına döndürülen yanıtlarda "Eylem" ReplyAction
OperationContractAttributeü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 DispatchBodyElementAttribute
tü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.
Örneği Ç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 , bodyB
ve bodyX
adlı bodyA
hizmete üç ileti gönderir. Önceki açıklamadan ve gösterilen hizmet sözleşmesinden ertelenebileceği gibi, öğesiyle bodyA
gelen ileti yöntemine OperationForBodyA()
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öntemine özgü bir öğeye sarmalar ve bu örnek için giriş ve çıkış iletilerini net bir şekilde ilişkilendirmek için yapılan bu öğeyi 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
Windows Communication Foundation Örnekleri için Tek Seferlik Kurulum Yordamı'nı gerçekleştirdiğinizden emin olun.
Çözümü oluşturmak için Windows Communication Foundation Örnekleri Oluşturma başlığındaki yönergeleri izleyin.
Örneği tek veya makineler arası bir yapılandırmada çalıştırmak için Windows Communication Foundation Örneklerini Çalıştırma başlığındaki yönergeleri izleyin.