【问题标题】:WCF Parameter Validation with Interceptor使用拦截器进行 WCF 参数验证
【发布时间】:2010-12-21 04:42:42
【问题描述】:

我有一个 WCF 服务,其操作都需要 MyServiceRequest 参数(或派生类型) 并返回 MyServiceResponse(或派生类型),即:

    [OperationContract]
    MySeviceResponse FindAppointments(FindAppointmentRequest request);

    [OperationContract]
    MyServiceResponse MakeAnAppointment(MakeAnAppointmentRequest request);

    [OperationContract]
    MyServiceResponse RegisterResource(RegisterResourceRequest request);

FindAppointmentRequest、MakeAnAppointmentRequest 和 RegisterResourceRequest 扩展了 MyServiceRequest,其中包含属性 UserName 和 UserPassword。

如果请求中有错误的用户名/用户密码对,则此方法都不会正确执行。

我想创建一个拦截器,它不仅检查给定的 UserName/UserPassword 对是否正确(使用 IParameterInspector 非常简单),而且还返回扩展 MyServiceResponse 的 ErrorRespone 类型的客户端对象。

IParameterInspector 能否阻止服务执行请求的方法并立即返回 ErrorResponse?

【问题讨论】:

    标签: wcf validation service parameters


    【解决方案1】:

    IParameterInspector 可以通过抛出异常来阻止操作执行。这是一个例子。

    定义自定义故障契约:

    public class DataAccessFaultContract
    {
        public string ErrorMessage { get; set; }
    }
    

    然后是检查员:

    public class InspectorAttribute : Attribute, IParameterInspector, IOperationBehavior
    {
        public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
        {
    
        }
    
        public object BeforeCall(string operationName, object[] inputs)
        {
            MyServiceRequest request = null;
            if (inputs != null && inputs.Length > 0)
            {
                request = inputs[0] as MyServiceRequest;
            }
    
            if (request != null && request.Username != "user" && request.Password != "secret")
            {
                var fc = new DataAccessFaultContract{ ErrorMessage = "Invalid user" };
                throw new FaultException<DataAccessFaultContract>(fc);
            }
            return null;
        }
    
        public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
        {
        }
    
        public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
        {
        }
    
        public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
        {
            dispatchOperation.ParameterInspectors.Add(this);
        }
    
        public void Validate(OperationDescription operationDescription)
        {
        }
    }
    

    最后用适当的属性装饰你的操作:

    [ServiceContract]
    public interface IMyServiceContract
    {
        [Inspector]
        [FaultContract(typeof(DataAccessFaultContract))]
        [OperationContract]
        MySeviceResponse FindAppointments(FindAppointmentRequest request);
    
        ...
    }
    

    调用服务时,客户端可以检查FaultException:

    try
    {
        var response = client.FindAppointments(request);
    }
    catch (FaultException<DataAccessFaultContract> ex)
    {
        string errorMessage = ex.Detail.ErrorMessage;
        // ...
    }
    

    【讨论】:

    • 如何决定MyServiceRequest对象
    • @darindimitrov:正如您所说,客户可以通过您在catch() 块中提供的代码检查 FaultException。但是如果我的客户是 iPhone 怎么办?我的其余 API 由 iPhone 使用,以及它们如何处理我在 iPhone 中的 FaultException 异常。实际上我已经检查了 iPhone,我看不到我的自定义错误消息!!。你知道为什么会这样吗??
    【解决方案2】:

    您可以有一个返回布尔值(真/假)的方法,该方法在上述每个方法的入口处检查您的参数,然后您可以检查它是否返回真或假,并相应地返回或执行该方法.

    所以

    bool paramtest = CheckParams(string username, string passw);
    
    if ( paramtest )
    {
    // Continue method here
    }
    else
    { 
    return false; // or return some string with error 
    }
    

    将其放在上述所有方法中...其中 CheckParams 是 IParameterInspector 中用于验证参数的方法。

    【讨论】:

      猜你喜欢
      • 2015-04-15
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多