Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
MessageInspectors örneği, istemci ve hizmet iletisi denetçilerini uygulama ve yapılandırmayı gösterir.
İleti denetçisi, hizmet modelinin istemci çalışma zamanında kullanılabilen ve çalışma zamanını program aracılığıyla veya yapılandırma aracılığıyla gönderebilen ve alındıktan sonra veya gönderilmeden önce iletileri inceleyip değiştirebilen bir genişletilebilirlik nesnesidir.
Bu örnek, bir dizi yapılandırılabilir XML Şeması belgesinde gelen iletileri doğrulayan temel bir istemci ve hizmet iletisi doğrulama mekanizmasını uygular. Bu örneğin her işlem için iletileri doğrulamadığını unutmayın. Bu kasıtlı bir basitleştirmedir.
İleti Denetçisi
İstemci ileti denetçileri IClientMessageInspector arabirimini uygular ve hizmet iletisi denetçileri IDispatchMessageInspector arabirimini uygular. Uygulamalar tek bir sınıf halinde birleştirilerek her iki taraf için de çalışan bir ileti denetçisi oluşturulabilir. Bu örnek, böyle bir birleştirilmiş ileti denetçisini kullanır. Denetçi, gelen ve giden iletilerin doğrulandığı bir dizi şema geçirerek oluşturulur ve geliştiricinin gelen veya giden iletilerin doğrulanıp doğrulanmadığını ve denetçinin gönderim veya istemci modunda olup olmadığını belirtmesine olanak tanır. Bu, bu konunun ilerleyen bölümlerinde açıklandığı gibi hata işlemeyi etkiler.
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;
}
Herhangi bir hizmet (dağıtıcı) ileti denetçisi, IDispatchMessageInspector yöntemlerini AfterReceiveRequest ve BeforeSendReply(Message, Object) uygulamalıdır.
AfterReceiveRequest bir ileti alındığında, kanal yığını tarafından işlendiğinde ve bir hizmete atandığında, ancak seri durumdan çıkarılıp bir işleme gönderilmeden önce dağıtıcı tarafından çağrılır. Gelen ileti şifrelendiyse, ileti denetçisine ulaştığında iletinin şifresi zaten çözülür. Yöntem, iletinin incelenmesine, değiştirilmesine veya gerektiğinde yerine başka bir şey konulmasına olanak tanıyan bir başvuru parametresi olarak request iletisinin geçirilmesini sağlar. Dönüş değeri, hizmetin geçerli mesaja yanıt verdiği durumda BeforeSendReply'ye iletilen bir ilişki durumu nesnesi olarak kullanılabilecek herhangi bir nesne olabilir. Bu örnekte, AfterReceiveRequest iletinin incelemesini (doğrulamasını) özel, yerel yönteme ValidateMessageBody atar ve bağıntı durumu nesnesi döndürmez. Bu yöntem, hizmete geçersiz mesajların geçmemesini sağlar.
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) , bir yanıt istemciye geri gönderilmeye hazır olduğunda veya tek yönlü iletiler söz konusu olduğunda gelen ileti işlendiğinde çağrılır. Bu, uzantıların MEP'den bağımsız olarak simetrik biçimde çağrılacaklarına güvenmelerini sağlar.
AfterReceiveRequest ile olduğu gibi, ileti bir başvuru parametresi olarak geçirilir ve incelenebilir, değiştirilebilir veya yerine konabilir. Bu örnekte gerçekleştirilen iletinin doğrulanması yine yöntemine ValidMessageBody devredilir, ancak bu durumda doğrulama hatalarının işlenmesi biraz farklıdır.
Hizmette bir doğrulama hatası oluşursa, ValidateMessageBody yöntemi FaultException türetilmiş istisnalar fırlatır.
AfterReceiveRequest'da bu özel durumlar, otomatik olarak SOAP hatalarına dönüştürüldükleri ve istemciye geçirildikleri servis modeli altyapısına yerleştirilebilir.
BeforeSendReply
FaultException içinde, hizmet tarafından atılan hata özel durumlarının dönüşümü, ileti denetçisi çağrılmadan önce gerçekleştiği için, özel durumlar altyapıya dahil edilmemelidir. Bu nedenle aşağıdaki uygulama bilinen ReplyValidationFault özel durumu yakalar ve yanıt iletisini açık bir hata iletisiyle değiştirir. Bu yöntem, hizmet uygulaması tarafından geçersiz ileti döndürülmemesini sağlar.
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);
}
}
İstemci ileti denetleyicisi oldukça benzer. IClientMessageInspector'dan uygulanması gereken iki yöntem AfterReceiveReply ve BeforeSendRequest'dir.
BeforeSendRequest , ileti istemci uygulaması veya işlem biçimlendiricisi tarafından oluşturulduğunda çağrılır. Dağıtıcı ileti denetçilerinde olduğu gibi, ileti yalnızca incelenebilir veya tamamen değiştirilebilir. Bu örnekte denetçi, dağıtım iletisi denetçileri için de kullanılan aynı yerel ValidateMessageBody yardımcı yönteme görev devreder.
İstemci ve hizmet doğrulaması (oluşturucuda belirtildiği gibi) arasındaki davranışsal fark, istemci doğrulamasının bir hizmet hatası nedeniyle değil yerel olarak gerçekleştiğinden kullanıcı koduna eklenen yerel özel durumlar oluşturmasıdır. Kural genellikle servis yönlendirici denetçilerinin hata oluşturması ve istemci denetçilerinin istisna oluşturmasıdır.
Bu BeforeSendRequest uygulama, hizmete geçersiz ileti gönderilmemesini sağlar.
object IClientMessageInspector.BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
if (validateRequest)
{
ValidateMessageBody(ref request, true);
}
return null;
}
Uygulama, AfterReceiveReply hizmetten alınan geçersiz iletilerin istemci kullanıcı koduna iletilmemesini sağlar.
void IClientMessageInspector.AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
if (validateReply)
{
ValidateMessageBody(ref reply, false);
}
}
Bu özel mesaj denetçisinin kalbi ValidateMessageBody yöntemidir. Çalışmasını gerçekleştirmek için, iletinin aktarılmış içerik alt bölümünü doğrulayan bir XmlReader sarmalar. Okuyucu, ileti denetçisinin barındırdığı şema kümesiyle doldurulur ve doğrulama geri çağırma işlevi, bu yöntemle birlikte tanımlanan InspectionValidationHandler öğesine başvuran bir temsilciye atanır. Doğrulamayı gerçekleştirmek için, ileti okunur ve belleği akışla desteklenen bir XmlDictionaryWriter içine biriktirilir. İşlemde bir doğrulama hatası veya uyarı oluşursa geri çağırma yöntemi çağrılır.
Eğer bir hata oluşmazsa, özellikleri ve başlıkları orijinal mesajdan kopyalanan ve hafıza akışında artık doğrulanmış bilgi kümesini kullanan, bir XmlDictionaryReader ile sarmalanan ve yedek mesaja eklenen yeni bir mesaj oluşturulur.
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;
}
}
Yöntem InspectionValidationHandler , bir şema doğrulama hatası veya uyarısı oluştuğunda doğrulama XmlReader tarafından çağrılır. Aşağıdaki uygulama yalnızca hatalarla çalışır ve tüm uyarıları yoksayar.
İlk bakışta, ileti denetçisiyle mesaja bir doğrulama XmlReader eklemenin ve mesaj işlenirken mesajı arabelleğe almadan doğrudan doğrulamanın gerçekleşmesine izin vermenin mümkün olabileceği düşünülebilir. Ancak bu, geçersiz XML düğümleri algılandığında bu geri çağırmanın doğrulama özel durumlarını hizmet modeli altyapısına veya kullanıcı koduna bir yere atarak öngörülemeyen davranışa neden olduğu anlamına gelir. Arabelleğe alma yaklaşımı, kullanıcı kodunu tamamen geçersiz iletilerden korur.
Daha önce açıklandığı gibi, işleyici tarafından atılan istisnalar istemci ile hizmet arasında farklılık gösterir. Hizmetteki istisnalar FaultException'den türetilmiştir, istemcideki istisnalar ise normal özel istisnalardır.
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);
}
}
}
}
Davranış
İleti denetçileri, istemci çalışma zamanının veya dağıtım çalışma zamanının uzantılarıdır. Bu tür uzantılar davranışlar kullanılarak yapılandırılır. Davranış, varsayılan yapılandırmayı değiştirerek veya uzantılar (ileti denetçileri gibi) ekleyerek hizmet modeli çalışma zamanının davranışını değiştiren bir sınıftır.
Aşağıdaki SchemaValidationBehavior sınıf, bu örneğin ileti denetçisini istemciye veya gönderme çalışma zamanına eklemek için kullanılan davranıştır. Her iki durumda da uygulama oldukça temeldir.
ApplyClientBehavior ve ApplyDispatchBehavior içinde, ileti denetçisi oluşturulur ve ilgili çalışma zamanının MessageInspectors koleksiyonuna eklenir.
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
}
Uyarı
Bu özel davranış, bir öznitelik olarak işlev görmez ve bu nedenle bir hizmet türünün sözleşme türüne bildirimsel olarak eklenemez. Bu, şema koleksiyonu bir öznitelik bildirimine yüklenemediğinden ve bu öznitelikteki ek yapılandırma konumuna (örneğin uygulama ayarlarına) başvurarak hizmet modeli yapılandırmasının geri kalanıyla tutarlı olmayan bir yapılandırma öğesi oluşturma anlamına geldiği için bu, tasarıma göre bir karardır. Bu nedenle, bu davranış yalnızca kod aracılığıyla ve bir hizmet modeli yapılandırma uzantısı aracılığıyla kesin olarak eklenebilir.
yapılandırma aracılığıyla İleti Denetçisi ekleme
Uygulama yapılandırma dosyasındaki bir uç noktada özel bir davranış yapılandırmak için hizmet modeli, uygulayıcıların öğesinden türetilen bir sınıf tarafından temsil edilen bir yapılandırma BehaviorExtensionElement oluşturmasını gerektirir. Bu uzantı daha sonra bu bölümde açıklanan aşağıdaki uzantıda gösterildiği gibi uzantılar için hizmet modelinin yapılandırma bölümüne eklenmelidir.
<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>
Uzantılar, en yaygın seçenek olan uygulama veya ASP.NET yapılandırma dosyasına veya makine yapılandırma dosyasına eklenebilir.
Uzantı bir yapılandırma kapsamına eklendiğinde, davranış aşağıdaki kodda gösterildiği gibi bir davranış yapılandırmasına eklenebilir. Davranış yapılandırmaları, gerektiğinde birden çok uç noktaya uygulanabilen yeniden kullanılabilir öğelerdir. Burada yapılandırılacak belirli davranış uygulandığından IEndpointBehavior, yalnızca yapılandırma dosyasındaki ilgili yapılandırma bölümünde geçerlidir.
<system.serviceModel>
<behaviors>
…
<endpointBehaviors>
<behavior name="HelloServiceEndpointBehavior">
<schemaValidator validateRequest="True" validateReply="True">
<schemas>
<add location="messages.xsd" />
</schemas>
</schemaValidator>
</behavior>
</endpointBehaviors>
…
</behaviors>
</system.serviceModel>
<schemaValidator> İleti denetçisini yapılandıran öğe, SchemaValidationBehaviorExtensionElement sınıfı tarafından desteklenmektedir. Sınıf, ValidateRequest ve ValidateReply adlı iki Boole ortak özelliğini kullanıma sunar. Bunların her ikisi de ile ConfigurationPropertyAttributeişaretlenir. Bu öznitelik, önceki XML yapılandırma öğesinde görülebilen kod özellikleri ve XML öznitelikleri arasındaki bağlantıyı oluşturur. Sınıfın ayrıca, türü Schemas olan ve ConfigurationCollectionAttribute ile de işaretlenen bir SchemaCollection özelliği vardır, bu da bu örneğin bir parçasıdır, ancak kısalık açısından bu belgeye dahil edilmemiştir. Bu özellik, koleksiyon ve koleksiyon öğesi sınıfı SchemaConfigElement ile birlikte önceki yapılandırma kod parçacığındaki <schemas> öğesini destekler ve doğrulama setine bir şema koleksiyonu eklemeye olanak tanır.
Geçersiz kılınan CreateBehavior yöntem, çalışma zamanı bir istemci veya uç nokta oluştururken yapılandırma verilerini değerlendirdiğinde yapılandırma verilerini bir davranış nesnesine dönüştürür.
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;
}
}
}
Mesaj Denetçilerini Emredici Olarak Ekleme
Öznitelikler (daha önce belirtilen nedenle bu örnekte desteklenmeyen) ve yapılandırma dışında, davranışlar kesinlik temelli kod kullanılarak istemci ve hizmet çalışma zamanına kolayca eklenebilir. Bu örnekte, istemci iletisi denetçisini test etmek için istemci uygulamasında bu gerçekleştirilir.
GenericClient sınıfı, uç nokta yapılandırmasını kullanıcı koduna sunan öğesinden ClientBase<TChannel>türetilir. İstemci örtük olarak açılmadan önce, aşağıdaki kodda gösterildiği gibi davranışlar ekleyerek uç nokta yapılandırması değiştirilebilir. Hizmetteki davranışın eklenmesi büyük ölçüde burada gösterilen istemci tekniğine eşdeğerdir ve hizmet konağı açılmadan önce gerçekleştirilmesi gerekir.
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);
}
Örneği ayarlamak, derlemek ve çalıştırmak için
Windows Communication Foundation Örnekleri içinOne-Time Kurulum Yordamını yaptığınızdan emin olun.
Çözümü oluşturmak için Windows Communication Foundation Örnekleri Oluşturma başlığındaki yönergeleri izleyin.
Ö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.