2012-05-12 40 views
2

如何使用MessageContract处理OnDeserialized事件?WCF:MessageContract句柄OnDeserialized事件

收到消息后(但在执行方法之前)需要做一些数据验证和转换。

对于DataContract,它是通过声明属性解决的。

但对于MessageContract它不起作用。

有没有办法做到这一点?

+0

MessageContract使用XmlSerializer的不实现序列化的回调。 –

回答

2

您最好使用WCF extension points而不是序列号。特别是IOperationInvoker。

EDIT

实施例:

服务和消息下面的定义。请注意新的MyValidationBeforeInvokeBehavior属性。

[ServiceContract] 
    public interface IService1 
    { 

     [OperationContract] 
     string GetData(int value); 

     [OperationContract] 
     [MyValidationBeforeInvokeBehavior] 
     AddPatientRecordResponse AddPatientRecord(PatientRecord composite); 
    } 

    [MessageContract(IsWrapped = false, ProtectionLevel = ProtectionLevel.None)] 
    public class AddPatientRecordResponse 
    { 
     [MessageHeader(ProtectionLevel = ProtectionLevel.None)] 
     public Guid recordID; 
     [MessageHeader(ProtectionLevel = ProtectionLevel.None)] 
     public string patientName; 
     [MessageBodyMember(ProtectionLevel = ProtectionLevel.None)] 
     public string status; 

    } 


    [MessageContract(IsWrapped = false, ProtectionLevel = ProtectionLevel.None)] 
    public class PatientRecord 
    { 
     [MessageHeader(ProtectionLevel = ProtectionLevel.None)] 
     public Guid recordID; 
     [MessageHeader(ProtectionLevel = ProtectionLevel.None)] 
     public string patientName; 

     //[MessageHeader(ProtectionLevel = ProtectionLevel.EncryptAndSign)] 
     [MessageHeader(ProtectionLevel = ProtectionLevel.None)] 
     public string SSN; 
     [MessageBodyMember(ProtectionLevel = ProtectionLevel.None)] 
     public string comments; 
     [MessageBodyMember(ProtectionLevel = ProtectionLevel.None)] 
     public string diagnosis; 
     [MessageBodyMember(ProtectionLevel = ProtectionLevel.None)] 
     public string medicalHistory; 
    } 

public class Service1 : IService1 
    { 
     public string GetData(int value) 
     { 
      return string.Format("You entered: {0}", value); 
     } 

     public AddPatientRecordResponse AddPatientRecord(PatientRecord patient) 
     { 
      var response = new AddPatientRecordResponse 
           { 
            patientName = patient.patientName, 
            recordID = patient.recordID, 
            status = "Sucess" 
           }; 

      return response; 
     } 
    } 

挂接到WCF扩展

public class MyValidationBeforeInvokeBehavior : Attribute, IOperationBehavior 
    { 
     public void Validate(OperationDescription operationDescription) 
     { 
     } 

     public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) 
     { 
      dispatchOperation.Invoker = new MyValidationBeforeInvoke(dispatchOperation.Invoker); 
     } 

     public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) 
     { 
     } 

     public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) 
     { 
     } 
    } 

自定义操作调用:

public class MyValidationBeforeInvoke : IOperationInvoker 
    { 
     private readonly IOperationInvoker _original; 

     public MyValidationBeforeInvoke(IOperationInvoker original) 
     { 
      _original = original; 
     } 

     public object[] AllocateInputs() 
     { 
      return _original.AllocateInputs(); 
     } 

     public object Invoke(object instance, object[] inputs, out object[] outputs) 
     { 

      var validator = new ValidatePatientRecord((PatientRecord) inputs[0]); 
      if (validator.IsValid()) 
      { 
       var ret = _original.Invoke(instance, inputs, out outputs); 
       return ret; 
      } 
      else 
      { 
       outputs = new object[] {}; 

       var patientRecord = (PatientRecord) inputs[0]; 

       var returnMessage = new AddPatientRecordResponse 
             { 
              patientName = patientRecord.patientName, 
              recordID = patientRecord.recordID, 
              status = "Validation Failed" 
             }; 
       return returnMessage;  
      } 


     } 

     public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state) 
     { 
      return _original.InvokeBegin(instance, inputs, callback, state); 
     } 

     public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result) 
     { 
      return _original.InvokeEnd(instance, out outputs, result); 
     } 

     public bool IsSynchronous 
     { 
      get { return _original.IsSynchronous; } 
     } 
    } 

本质是,我们从来没有调用服务调用,因为它永远不会到达那里,由于验证错误。我们也可以将发生的事情返还给客户。

验证类和客户端调用(用于完成):

public class ValidatePatientRecord 
    { 
     private readonly PatientRecord _patientRecord; 

     public ValidatePatientRecord(PatientRecord patientRecord) 
     { 
      _patientRecord = patientRecord; 
     } 

     public bool IsValid() 
     { 
      return _patientRecord.patientName != "Stack Overflow"; 
     } 
    } 

客户端:

class Program 
    { 
     static void Main(string[] args) 
     { 
      var patient = new PatientRecord { SSN = "123", recordID = Guid.NewGuid(), patientName = "Stack Overflow" }; 

      var proxy = new ServiceReference1.Service1Client(); 

      var result = proxy.AddPatientRecord(patient); 

      Console.WriteLine(result.status); 
      Console.ReadLine(); 
     } 
    } 
+0

谢谢,Petar,但序列化回调也是WCF扩展点的一部分。 IOperationInvoker似乎没有好处。我有基础MessageContract类(哪个逻辑必须验证)和几个带有派生MessageContracts的服务。 –

+0

非常感谢!有用! –