WCF 使用 MessageInspector 拦截消息

问题描述 投票:0回答:1

我正在编写一个 WCF 服务(.NET Framework),该服务应该充当向其发送消息的客户端的提供者(仅限单向通信)。服务必须使用SOAP 协议进行通信。对服务提供商的要求之一是创建自定义 HTTP 响应,其正文将包含 SOAP 错误,如 w3c 标准中所述。 我想我会尝试使用MessageInspector类来达到这个目的,但是我无法达到预期的效果。我尝试根据文档(

https://learn.microsoft.com/en-us/dotnet/framework/wcf/samples/message-inspectors?redirectedfrom=MSDN

)实现必要的方法和配置,但到目前为止没有效果。 目前,该服务由 .NET Framework 控制台应用程序托管。以下是最重要元素的实现和项目结构:

结构:

MyService DTO -- CompositeType.cs Utils -- SchemaValidationBehavior.cs -- SchemaValidationBehaviorExtensionElement.cs -- SchemaValidationMessageInspector.cs -- ValidationFault.cs App.config IMyService MyService

实施:

[ServiceContract] public interface IMyService { [OperationContract(IsOneWay = true)] void SendData(CompositeType composite); }

    public class MyService : IMyService
    {
        public void SendData(CompositeType composite)
        {
            System.Diagnostics.Debugger.Break();
            Console.WriteLine(composite.BoolValue.ToString() + " " + composite.StringValue);
        }
    }
    class SchemaValidationMessageInspector : IClientMessageInspector, IDispatchMessageInspector
    {
        XmlSchemaSet schemaSet;
        bool validateRequest;
        bool validateReply;
        bool isClientSide;
        [ThreadStatic] // Wskazuje, że wartość pola statycznego jest unikalna dla każdego wątku
        bool isRequest;

        public SchemaValidationMessageInspector()
        {
        }

        public SchemaValidationMessageInspector(XmlSchemaSet schemaSet, bool validateRequest, bool validateReply, bool isClientSide)
        {
            this.schemaSet = schemaSet;
            this.validateRequest = validateRequest;
            this.validateReply = validateReply;
            this.isClientSide = isClientSide;
        }

        // IClientMessageInspector Interfaces -- Client message inspector
        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
            Console.WriteLine("I am inside AfterReceiveReply");
        }

        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            Console.WriteLine("I am inside BeforeSendRequest");
            return null;
        }

        // IDispatchMessageInspector Interfaces -- Service message inspector
        public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        {
            Console.WriteLine("I am inside AfterReceiveRequest");
            return null;
        }

        public void BeforeSendReply(ref Message reply, object correlationState)
        {
            Console.WriteLine("I am inside BeforeSendReply");
        }
    }
    class SchemaValidationBehavior : IEndpointBehavior
    {
        XmlSchemaSet schemaSet;
        bool validateRequest;
        bool validateReply;

        public SchemaValidationBehavior(){}

        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, BindingParameterCollection bindingParameters){}

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            Console.WriteLine("I am inside ApplyClientBehavior");
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            Console.WriteLine("I am inside ApplyDispatchBehavior");
            SchemaValidationMessageInspector inspector = new SchemaValidationMessageInspector();
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
        }

        public void Validate(ServiceEndpoint endpoint){}

        #endregion
    }
    public class SchemaValidationBehaviorExtensionElement : BehaviorExtensionElement
    {
        public SchemaValidationBehaviorExtensionElement(){}

        public override Type BehaviorType
        {
            get
            {
                return typeof(SchemaValidationBehavior);
            }
        }

        protected override object CreateBehavior()
        {
            Console.WriteLine("I am inside ApplyClientBehavior");
            return new SchemaValidationBehavior();
        }

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

    }
配置:

<configuration> <appSettings> <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> </appSettings> <system.web> <compilation debug="true" /> </system.web> <system.serviceModel> <!-- SERVICES --> <services> <service name="MyService.MyService" behaviorConfiguration="MyServiceBehavior"> <endpoint address="" binding="basicHttpBinding" contract="MyService.IMyService" behaviorConfiguration="MyEndpointBehavior"> <identity> <dns value="localhost" /> </identity> </endpoint> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> <host> <baseAddresses> <add baseAddress="http://localhost:9000/MyService/" /> </baseAddresses> </host> </service> </services> <!-- SERVICES --> <!-- BEHAVIORS --> <behaviors> <endpointBehaviors> <behavior name="MyEndpointBehavior"> <schemaValidator validateRequest="true" validateReply="true"/> </behavior> </endpointBehaviors> <serviceBehaviors> <behavior name="MyServiceBehavior"> <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="true" /> <!-- Add the behavior extension here --> </behavior> </serviceBehaviors> </behaviors> <!-- BEHAVIORS --> <!-- EXTENSIONS --> <extensions> <behaviorExtensions> <add name="schemaValidator" type="MyService.Utils.SchemaValidationBehaviorExtensionElement, MyService" /> </behaviorExtensions> </extensions> <!-- EXTENSIONS --> </system.serviceModel> </configuration>

我一定缺少一些配置,或者可能配置错误,但从客户端发送的消息直接发送到 MyService 类的 SendData() 方法。

附注我想这并不重要,但这是 Host App 的代码:

internal class Program { static void Main(string[] args) { ServiceHost host = null; try { host = new ServiceHost(typeof(MyService.MyService)); host.Open(); Console.WriteLine($"Host for MyService started @ {DateTime.Now} {Environment.NewLine}Service hosted on http://localhost:9000"); Console.ReadLine(); } catch (Exception ex) { Console.WriteLine(ex.ToString()); Console.ReadLine(); } finally { host?.Close(); } } }


c# wcf soap httpresponse idispatchmessageinspector
1个回答
0
投票

我尝试在主机的 App.config 文件中添加所有必要的配置 - 它发挥了作用 - 所有消息检查器方法都在消息到达目标方法之前被调用!

© www.soinside.com 2019 - 2024. All rights reserved.