1

我指定了一个自定义NonEmptyGuidAttribute扩展ValidationAttribute,如下所示

public class NonEmptyGuidAttribute:ValidationAttribute
{
    public override bool IsValid(object value)
    {
        Guid parsedValue = Guid.Empty;
        if (value != null && Guid.TryParse(value.ToString(), out parsedValue))
        {
            return true;
        }

        return false;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        Guid parsedValue = Guid.Empty;
        if (value != null && Guid.TryParse(value.ToString(), out parsedValue) && parsedValue != Guid.Empty)
        {
            return ValidationResult.Success;
        }

        return new ValidationResult(
            this.ErrorMessage = string.Format("The value of {0} is not valid", validationContext.MemberName),
            new[] { validationContext.MemberName }
            );
    }
}

这样做的目的只是为了确保如果我的模型之一具有Guid属性,则该属性不为空且有效。

下面是正在使用的此属性的示例。我必须创建Guid一个可为空的类型,以便[Required]尊重该属性。

public class SomeNancyRequest
{
    [Required]
    [NonEmptyGuid]
    public Guid? Id { get; set; }

    [Required]
    public string Name { get; set; }

    [Required]
    public string Description { get; set; }

    [Required]
    [DataType(DataType.ImageUrl)]
    public string ImagePath { get; set; }

    [Required]
    public bool Enabled {get;set;}
}

如果我通过如下请求访问我的 API,它不会使用[NonEmptyGuid]验证逻辑。我知道这一点是因为我在其中放置了断点以及构造函数来查看属性是否已初始化。

{
    "id":"Im not a guid",
    "name": "Just a name",
    "description": "Some Description",
    "imagePath": "http://myimage.com",
    "enabled": true
}

我希望这会命中我的验证器并由于id上述请求中的无效属性而失败。它确实失败了,但是因为在尝试转换 Guid 时抛出了如下所示的异常。

Nancy.RequestExecutionException: Oh noes! ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.FormatException: Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
   at System.Guid.GuidResult.SetFailure(ParseFailureKind failure, String failureMessageID, Object failureMessageFormatArgument, String failureArgumentName, Exception innerException)
   at System.Guid.TryParseGuidWithNoStyle(String guidString, GuidResult& result)
   at System.Guid.TryParseGuid(String g, GuidStyles flags, GuidResult& result)
   at System.Guid..ctor(String g)
   at System.ComponentModel.GuidConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
   at System.ComponentModel.NullableConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
   at System.ComponentModel.TypeConverter.ConvertFromInvariantString(String text)
   at Nancy.Json.JavaScriptSerializer.ConvertToType(Type type, Object obj)
   at Nancy.Json.JavaScriptSerializer.ConvertToObject(IDictionary`2 dict, Type type)
   at Nancy.Json.JavaScriptSerializer.ConvertToType(Type type, Object obj)
   at Nancy.Json.JavaScriptSerializer.ConvertToType[T](Object obj)
   at Nancy.Json.JavaScriptSerializer.Deserialize[T](String input)
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at Nancy.ModelBinding.DefaultBodyDeserializers.JsonBodyDeserializer.Deserialize(String contentType, Stream bodyStream, BindingContext context)
   at Nancy.ModelBinding.DefaultBinder.DeserializeRequestBody(BindingContext context)
   at Nancy.ModelBinding.DefaultBinder.Bind(NancyContext context, Type modelType, Object instance, BindingConfig configuration, String[] blackList)
   at Nancy.ModelBinding.DynamicModelBinderAdapter.TryConvert(ConvertBinder binder, Object& result)
   at CallSite.Target(Closure , CallSite , Object )
   at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
   at Nancy.ModelBinding.ModuleExtensions.Bind[TModel](INancyModule module, String[] blacklistedProperties)
   at Nancy.ModelBinding.ModuleExtensions.BindAndValidate[TModel](INancyModule module)
   at Server.Extensibility.NancyModuleExtensions.d__3a`2.MoveNext() in c:\Users\Me\Source\Repos\my-server\.Server\Extensibility\NancyModuleExtensions.cs:line 121
   --- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Server.Extensibility.NancyModuleExtensions.<>c__DisplayClass25`2.<b__24>d__27.MoveNext() in c:\Users\Me\Source\Repos\my-server\Server\Extensibility\NancyModuleExtensions.cs:line 49
   --- End of inner exception stack trace ---
   at Nancy.NancyEngine.InvokeOnErrorHook(NancyContext context, ErrorPipeline pipeline, Exception ex)

为什么这不起作用?

4

1 回答 1

2

绑定完成后进行验证。所以看起来内部 JSON 序列化程序在转换过程中失败了。所以我会把它归类为一个错误。但是,您应该能够通过使用 newtonsoft json 库来解决它。

https://www.nuget.org/packages/Nancy.Serialization.JsonNet/

Install-Package Nancy.Serialization.JsonNet

您无需配置任何东西,安装时它会自动开始使用它。

于 2015-09-15T06:56:30.923 回答