在每个服务方法调用之前执行的 WCF 一种方法

WCF One method to execute before every service method's call

我正在寻找一种在服务器端针对每个请求方法的调用执行特定方法的方法。

这不仅是为了安全验证。

这与 this question 不重复,因为我们指的是完全不同的东西。另外,那里所有的相关答案都有不可用的链接,所以不可能得到正确的答案。

(抱歉我这里没有附上任何代码,本期没有代码可以说明)

最佳解决方案是创建 WCF 自定义行为

以下是您如何通过几个简单的步骤完成此操作:

客户端:

public class FillHeaderDataBehaviourExtension : BehaviorExtensionElement, IEndpointBehavior
{
    #region BehaviorExtensionElement Implementation
    public override Type BehaviorType
    {
        get
        {
            return typeof(FillHeaderDataBehaviourExtension);
        }
    }
    protected override object CreateBehavior()
    {
        return this;
    }
    #endregion

    #region IServiceBehaviour Implementation
    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {
    }
    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {

    }
    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }

    public void Validate(ServiceEndpoint endpoint)
    {
    }
    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {
    }
    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
    }
    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        clientRuntime.ClientMessageInspectors.Add(new MessageInspector());
    }
    #endregion
}

public class MessageInspector : IClientMessageInspector
{
    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        MessageHeader header = MessageHeader.CreateHeader("HeaderData", String.Empty, HeaderDataVM.GetInstance().GetBaseInstance());
        request.Headers.Add(header); // There is no need for checking if exist before adding. Every request has it's own headers.

        return null;
    }
    public void AfterReceiveReply(ref Message reply, object correlationState)
    {
    }
}

服务器端:

public class ExtractHeadersBehaviourExtension : BehaviorExtensionElement, IServiceBehavior
{
    #region BehaviorExtensionElement Implementation
    public override Type BehaviorType
    {
        get
        {
            return typeof(ExtractHeadersBehaviourExtension);
        }
    }
    protected override object CreateBehavior()
    {
        return this;
    }
    #endregion

    #region IServiceBehavior Implementation
    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {
    }
    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        for (int i = 0; i < serviceHostBase.ChannelDispatchers.Count; i++)
        {
            ChannelDispatcher channelDispatcher = serviceHostBase.ChannelDispatchers[i] as ChannelDispatcher;
            if (channelDispatcher != null)
            {
                foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)
                {
                    MessageInspector inspector = new MessageInspector();
                    endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
                }
            }
        }
    }
    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }
    #endregion
}

public class MessageInspector : IDispatchMessageInspector
{
    public void BeforeSendReply(ref Message reply, object correlationState)
    {
    }
    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
    {
        HeaderData headerData = request.Headers.GetHeader<HeaderData>("HeaderData", String.Empty);

        if(headerData != null)
        {
            OperationContext.Current.IncomingMessageProperties.Add("HeaderData", headerData);
        }

        return null;
    }
}

最后,不要忘记在 app.config 文件(客户端和服务器端)中进行如下配置:

<behaviors>
  <endpointBehaviors>
    <behavior name="NewBehavior">
      <fillHeaderDataBehaviourExtension/>
    </behavior>
  </endpointBehaviors>
</behaviors>
<bindings>

您还可以通过 WCF 配置编辑器添加这些行。为此,请查看 this 答案。

编辑: 添加这些行配置代码后,您可能会在应用程序配置中遇到错误:

别担心,您的应用程序会 运行 没问题。这是因为 GAC(全局程序集缓存)文件夹不包含此行为(因为它是自定义行为)。您可以通过手动将此行为添加到计算机上的 GAC 文件夹来修复它。 但是,此错误可能会阻止您更新服务引用。如果您尝试这样做,您将收到此错误消息:

因此,当您更新服务参考时,只需注释掉这一行 (<extractHeadersBehaviourExtension/>)(在客户端和服务器端)。

资料来源:How to add behavior on a specific endpoint?& Adding Custom Message Headers to a WCF Service