验证WCF和Web Service方法参数值的最佳方法

时间:2012-08-04 09:40:09

标签: c# wcf web-services validation postsharp

我将编写一个验证组件,以便在不同的项目中使用它。我并不熟悉任何验证框架,如企业库VABFluentCuttingEdge.Conditions以及其他许多验证框架,但是我没有时间与所有验证框架一起工作看哪个更适合我的目的。

我希望这个组件为我提供两种不同的功能:

首先,我想要一些验证器,如EmailValidator,StringLengthValidator,MyCustomValidator等,我可以随时在代码中使用它们,如下所示:

public class EmailValidator : RegexValidator // or StringValidator or whatever!
{
    public EmailValidator() : base("emailRegexHere")
    {
    }
public bool override DoValidate(string value)
    {
        return base.DoValidate(value);
    }
}
...

public void MyMethod(string email)
{
    EmailValidator validator = new EmailValidator();
    if(!validator.Validate(email))
        throw new NotValidatedException("email is invalid.");
    ...
}

第二次,我需要通过将DataAnnotations等应用到我想要的任何方法参数来验证参数,而无需任何额外的编码。我知道的一种可能的方法是使用PostSharp编写Aspects以在方法启动时注入代码(OnMethodEntry)。我用Postsharp完成了Logging,它运行得很好。

Microsoft也向Perform Input Validation in WCF引入了IParameterInspector,它提供了2种方法BeforCall和AfterCall,但我认为它只适用于WCF。

总结一下,我需要在我的WCF或WebService中进行验证,如下所示:

[System.Web.Script.Services.ScriptService]
public class MyServiceClass : System.Web.Services.WebService
{
    [Aspects.Validate]
    [WebMethod(EnableSession = true)]
    public string SubmitComment([Validation.Required]string content,[Validation.Guid] string userId,[Validation.Required] [Validation.Name]string name, [Validation.Email]string email, string ipAddress)
    {
        ...
    }
}

注意:这只是一个示例代码,用于演示我需要的行为,其他任何建议都非常受欢迎。验证。*注释是否也可以更改为一个注释,如ValidateParam(typeof(EmailValidator))?

提前致谢

1 个答案:

答案 0 :(得分:3)

是的,我只想看看PostSharp。 OnMethodBoundaryAspectMethodInterceptionAspect检查方法的参数(对于说明如何验证的属性)和参数(您要验证的值)。

由于您之前使用过OnMethodBoundaryAspect,请查看MethodExecutionArgs的文档。您可以使用args.Method获取方法信息(返回MethodBase,它位于System.Reflection中)。在其上调用GetParameters(),返回ParameterInfo数组。在每个ParameterInfo对象上,您可以使用Attributes属性获取有关属性的信息。

一旦了解了属性,就可以知道要使用哪些验证方法(或者如果您要创建自己的属性,验证方法可以在这些属性类本身中)。然后你只需要使用args.Arguments来获取参数的值。

这是一些(假的)代码:

public interface IValidator
{
    void Validate(object value);
}
public class ValidationEmailAttribute : Attribute, IValidator
{
    public Validate(string emailAddress)
    {
        // throw exception or whatever if invalid
    }
}

public class ValidateParametersAspect : OnMethodBoundaryAspect
{
    public override OnEntry(args)
    {
        foreach(i = 0 to args.Method.GetParameters().Count)
        {
            var parameter = args.Method.GetParameters()[i];
            var argument = args.Argument[i]; // get the corresponding argument value
            foreach(attribute in parameter.Attributes)
            {
                var attributeInstance = Activator.CreateType(attribute.Type);
                var validator = (IValidator)attributeInstance;
                validator.Validate(argument);
            }
        }
     }
}

public class MyClass
{
    [ValidateParametersAspect]
    public void SaveEmail([ValidationEmail] string email)
    {
        // ...
    }
}

这不是真正的代码:你必须自己解决的细节。

我喜欢将验证代码放在属性本身中,因为您不必更改方面以添加其他验证类型。