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

时间:2015-09-04 22:24:11

标签: wcf wcf-security

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

这也适用于安全验证,但不仅仅是。

这与this question不重复,因为我们的意思是不同的,所有相关的答案都有不可用的链接,因此无法得到正确的答案。

(很抱歉,此处未附加任何代码,此问题中没有要指定的代码)。

由于

1 个答案:

答案 0 :(得分:2)

最佳解决方案是创建 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 answer。

编辑:在添加以下配置代码行后,您可能会在应用配置中收到错误消息:

enter image description here

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

enter image description here

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

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