IDispatchMessageInspector:改进BeforeSendReply功能

时间:2011-01-20 16:23:24

标签: c# .net 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);          
    }

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

if (reply.Properties.Any(x => x.Key == "httpResponse"))
    return;

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

更新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>

更新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);          
        }
    }

1 个答案:

答案 0 :(得分:2)

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

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