使用拦截器进行 WCF 参数验证
Posted
技术标签:
【中文标题】使用拦截器进行 WCF 参数验证【英文标题】:WCF Parameter Validation with Interceptor 【发布时间】: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?
【问题讨论】:
【参考方案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您可以有一个返回布尔值(真/假)的方法,该方法在上述每个方法的入口处检查您的参数,然后您可以检查它是否返回真或假,并相应地返回或执行该方法.
所以
bool paramtest = CheckParams(string username, string passw);
if ( paramtest )
// Continue method here
else
return false; // or return some string with error
将其放在上述所有方法中...其中 CheckParams 是 IParameterInspector 中用于验证参数的方法。
【讨论】:
以上是关于使用拦截器进行 WCF 参数验证的主要内容,如果未能解决你的问题,请参考以下文章
如何在spring-servlet.xml内设置拦截器不对上传控制器进行验证