IDispatchMessageInspector:改进BeforeSendReply功能

Igo*_*nko 5 .net c# wcf wcf-extensions


在我的WCF项目中,我需要在响应中使用自定义标头,因此我实现了IDispatchMessageInspector.老实说,一切都很好,但我对一件小事情感到不安.
问题是即使我只是将.svc作为页面打开,或者将服务加载到WCF测试客户端,BeforeSendReply和AfterReceiveRequest都会触发.
所以,第一个问题:这种行为是正常的吗?有没有办法以声明方式处理(可能是一些web.config技巧)?
目前我使用下一个代码:

    public void BeforeSendReply(ref Message reply, object correlationState)
    {
        if (reply.Properties.Any(x => x.Key == "httpResponse"))
            return;

        MessageHeader header = MessageHeader.CreateHeader("Success", "NS", !reply.IsFault);
        reply.Headers.Add(header);          
    }
Run Code Online (Sandbox Code Playgroud)

所以现在我通过使用它来处理所有不是服务调用的调用:

if (reply.Properties.Any(x => x.Key == "httpResponse"))
    return;
Run Code Online (Sandbox Code Playgroud)

但我很确定还有其他一些更好的方法可以解决这个问题.所以我的主要问题是:请建议我一个更好的方法来处理描述的情况.
提前致谢!

更新1
我的system.serviceModel部分

<system.serviceModel>       
    <services>          
        <service behaviorConfiguration="someBehavior" name="serviceName">
            <endpoint address="" binding="basicHttpBinding" contract="my contract" />
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        </service>
    </services>     
    <behaviors>
        <serviceBehaviors>              
            <behavior name="someBehavior">
                <serviceMetadata httpGetEnabled="true" httpGetUrl=""/>                  
                <serviceDebug includeExceptionDetailInFaults="false"/>
                <exceptionInspector/>                   
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <extensions>
        <behaviorExtensions>
            <add name="exceptionInspector" type="class which implements BehaviorExtensionElement" />
        </behaviorExtensions>
    </extensions>

</system.serviceModel>
Run Code Online (Sandbox Code Playgroud)

更新2(接受解决方案)
我花了一些时间调查问题的来源,最后我发现我可以接受解决方案.
所以我发现了什么:
首先Message是一个抽象类.所以BeforeSendReply每次都会收到不同类型的具体消息.
最常用的是:
1)System.ServiceModel.Description.ServiceMetadataExtension.HttpGetImpl.MetadataOnHelpPageMessage- 表示客户端打开svc作为页面.结果=众所周知的html格式页面,其中包含有关svc服务的常见信息.对于这种类型reply.Version.EnvelopeEnvelopeVersion.None.
2)获取元数据请求.这是一个有点棘手的部分,这取决于我们是否使用MEX.因此,如果我们使用MEX然后请求执行到.SVC/MEX端点和其消息类型将是System.ServiceModel.Dispatcher.OperationFormatter.OperationFormatterMessagereply.Version.Envelope等于EnvelopeVersion.Soap12.
如果我们不使用MEX,则客户端执行获取wsdl数据的请求很少.消息类型将是XMLSchemaMessage.
3)执行Web方法请求.这仅对我的请求类型有用.它是System.ServiceModel.Dispatcher.OperationFormatter.OperationFormatterMessagereply.Version.Envelope等于EnvelopeVersion.Soap11.

我正在使用basicHttpBinding,所以SOAP版本是1.1.所以我的最终代码应该检查回复是否有SOAP信封并检查它的版本.如果信封存在且版本为1.1,那么我们可能非常确定我们可以添加Web方法调用并添加自定义标头:

        public void BeforeSendReply(ref Message reply, object correlationState)
    {   
        if(reply.Version.Envelope == EnvelopeVersion.Soap11)
        {               
            MessageHeader header = MessageHeader.CreateHeader("Success", "NS", !reply.IsFault);
            reply.Headers.Add(header);          
        }
    }
Run Code Online (Sandbox Code Playgroud)

tom*_*asr 2

我似乎记得 IDispatchMessageInspector 将为所有消息运行,包括在同一端点公开的元数据 (WSDL) 的 HTTP 请求。您没有提及如何注册检查员,因此这也可能相关。

除了检查之外,您是否尝试过检查消息包含的内容?例如,包含服务 HTML 页面的消息可能具有 MessageVersion == MessageVersion.None。同样,与消息关联的操作也可能有用。