WCF:MessageContract句柄已序列化事件

WCF:MessageContract句柄已序列化事件,wcf,xml-deserialization,messagecontract,Wcf,Xml Deserialization,Messagecontract,如何使用MessageContract处理OnDeserialized事件 在收到消息后(但在执行方法之前),需要进行一些数据验证和转换 对于DataContract,它是通过声明属性解决的 [ServiceContract] public interface IService1 { [OperationContract] string GetData(int value); [OperationContract]

如何使用MessageContract处理OnDeserialized事件

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

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

[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;
        }
    }
但对于MessageContract来说,它不起作用

有什么方法可以做到这一点吗?

最好使用而不是序列化。特别是IoperationVoker

编辑

例如:

服务和消息定义如下。请注意新的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; }
        }
    }
本质上,我们永远不会调用服务调用,因为由于验证错误,它永远不会到达那里。我们还可以返回发生在客户身上的情况

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

客户:

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

谢谢,Petar,但是序列化回调也是WCF扩展点的一部分。iOperationVoker似乎不适合它。我有基本MessageContract类(必须验证其逻辑)和几个具有派生MessageContracts的服务。MessageContract使用的是XmlSerializer,它不实现序列化回调。