Пользовательский атрибут валидации в NancyFX не распознается и не используется
Я указал обычай 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)
Почему это не работает?
1 ответ
Проверка происходит после выполнения привязки. Похоже, что внутренний преобразователь JSON не работает во время преобразования. Поэтому я бы отнес это к ошибке. Однако вы должны быть в состоянии обойти это, используя библиотеку jtons newtonsoft.
https://www.nuget.org/packages/Nancy.Serialization.JsonNet/
Install-Package Nancy.Serialization.JsonNet
Вам не нужно ничего настраивать, он автоматически начнет использовать его при установке.