You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于WCF中间件/拦截器提前返回自定义响应的实现方案

问题描述

我想管控所有WCF方法的调用,统一添加验证逻辑。当验证失败时,要让方法提前返回和该方法返回类型一致的自定义响应,而且不想在每个方法里都加验证检查,怎么在集中位置实现这个需求?

附上我的WCF服务伪代码:

using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.Text;
using System.Threading;

namespace Microsoft.WCF.Documentation
{
  [ServiceContractAttribute(Namespace="http://microsoft.wcf.documentation")]
  public interface ISampleService
  {
    [OperationContractAttribute(AsyncPattern=true)]
    IAsyncResult BeginGetCustomerInfo(GetCustomerInfoRequest request, AsyncCallback callback, object asyncState);

    GetCustomerInfoResponse EndGetCustomerInfo(IAsyncResult result);

    [OperationContractAttribute(AsyncPattern=true)]
    IAsyncResult BeginGetProductDetails(GetProductDetailsRequest request, AsyncCallback callback, object asyncState);

    GetProductDetailsResponse EndGetProductDetails(IAsyncResult result);
  }

  public class SampleService : ISampleService
  {
    public IAsyncResult BeginGetCustomerInfo(GetCustomerInfoRequest request, AsyncCallback callback, object asyncState)
    {
      Console.WriteLine("BeginGetCustomerInfo called with: \"{0}\"", request);
      // 业务逻辑
    }

    public GetCustomerInfoResponse EndGetCustomerInfo(IAsyncResult r)
    {
        // 业务逻辑
        return new GetCustomerInfoResponse();
    }

    public IAsyncResult BeginGetProductDetails(GetProductDetailsRequest request, AsyncCallback callback, object asyncState)
    {
      Console.WriteLine("BeginGetProductDetails called with: \"{0}\"", request);
      // 业务逻辑
    }

    public GetProductDetailsResponse EndGetProductDetails(IAsyncResult r)
    {
        // 业务逻辑
        return new GetProductDetailsResponse();
    }
  }
}
解决方案:用WCF消息检查器+服务行为实现集中验证

WCF提供的IDispatchMessageInspector接口可在服务端接收请求后、调用业务方法前拦截消息,支持验证失败时直接构造自定义响应返回,无需进入业务方法。配合IServiceBehavior可将检查器应用到整个服务的所有方法,实现集中管控。

步骤1:实现IDispatchMessageInspector

通过AfterReceiveRequest方法执行验证逻辑,失败时构造对应响应并终止后续流程:

using System;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;

public class ValidationMessageInspector : IDispatchMessageInspector
{
    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
    {
        // 获取当前调用的操作信息
        var operationContext = OperationContext.Current;
        var operationDescription = operationContext.EndpointDispatcher.DispatchRuntime.Operations.Find(operationContext.IncomingMessageHeaders.Action);
        if (operationDescription == null) return null;

        // 解析请求参数(适配异步Begin方法)
        object requestParam = null;
        if (operationDescription.SyncMethod != null && operationDescription.SyncMethod.Name.StartsWith("Begin"))
        {
            var requestType = operationDescription.SyncMethod.GetParameters()[0].ParameterType;
            requestParam = request.GetBody(requestType);
        }

        // 执行验证逻辑
        bool isValid = ValidateRequest(requestParam, operationDescription);
        if (isValid) return null;

        // 构造自定义失败响应
        var responseType = GetResponseType(operationDescription);
        var customResponse = CreateCustomFailedResponse(responseType);

        // 返回响应并终止流程
        Message reply = Message.CreateMessage(request.Version, operationDescription.Messages[1].Action, customResponse);
        operationContext.Reply(reply);
        return null;
    }

    public void BeforeSendReply(ref Message reply, object correlationState) { }

    // 获取对应操作的响应类型
    private Type GetResponseType(OperationDescription operation)
    {
        if (operation.IsAsync)
        {
            return operation.EndMethod.ReturnType;
        }
        return operation.Messages[1].Body.ReturnValue.Type;
    }

    // 自定义验证逻辑
    private bool ValidateRequest(object requestParam, OperationDescription operation)
    {
        // 示例:验证GetCustomerInfoRequest的CustomerId非空
        if (requestParam is GetCustomerInfoRequest customerRequest)
        {
            return !string.IsNullOrEmpty(customerRequest.CustomerId);
        }
        // 示例:验证GetProductDetailsRequest的ProductId大于0
        if (requestParam is GetProductDetailsRequest productRequest)
        {
            return productRequest.ProductId > 0;
        }
        return true;
    }

    // 创建验证失败的响应对象
    private object CreateCustomFailedResponse(Type responseType)
    {
        var response = Activator.CreateInstance(responseType);
        // 假设所有响应都有IsSuccess和ErrorMessage属性
        var isSuccessProp = responseType.GetProperty("IsSuccess");
        var errorMsgProp = responseType.GetProperty("ErrorMessage");
        isSuccessProp?.SetValue(response, false);
        errorMsgProp?.SetValue(response, "请求验证失败,请检查参数或权限");
        return response;
    }
}

步骤2:实现IServiceBehavior,全局应用检查器

public class ValidationServiceBehavior : IServiceBehavior
{
    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
        {
            foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)
            {
                endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new ValidationMessageInspector());
            }
        }
    }

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { }
    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { }
}

步骤3:注册服务行为

方式1:配置文件注册(推荐)

在WCF配置文件中添加行为扩展:

<system.serviceModel>
  <extensions>
    <behaviorExtensions>
      <add name="validationBehavior" type="你的命名空间.ValidationServiceBehavior, 你的程序集名称" />
    </behaviorExtensions>
  </extensions>
  <behaviors>
    <serviceBehaviors>
      <behavior name="SampleServiceBehavior">
        <validationBehavior />
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <services>
    <service name="Microsoft.WCF.Documentation.SampleService" behaviorConfiguration="SampleServiceBehavior">
      <endpoint address="" binding="basicHttpBinding" contract="Microsoft.WCF.Documentation.ISampleService" />
    </service>
  </services>
</system.serviceModel>

方式2:代码注册

在服务宿主启动时添加行为:

using System.ServiceModel;

class Program
{
    static void Main()
    {
        using (ServiceHost host = new ServiceHost(typeof(SampleService)))
        {
            host.Description.Behaviors.Add(new ValidationServiceBehavior());
            host.Open();
            Console.WriteLine("Service is running...");
            Console.ReadLine();
            host.Close();
        }
    }
}

关键说明

  • 异步方法兼容:代码已适配AsyncPattern=true的异步方法,自动解析Begin方法参数和End方法返回类型。
  • 响应适配:通过反射创建对应返回类型的响应对象,只要所有响应类型有统一的错误属性(如IsSuccess、ErrorMessage)即可自动设置失败信息。
  • 无侵入性:所有验证逻辑集中在检查器中,业务方法无需修改。

内容的提问来源于stack exchange,提问作者csharpdeveloper1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 21:00:34