Я указал пользовательский 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
типом, допускающим значение NULL, чтобы уважался атрибут [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)
Почему это не работает?