问题描述
我有一个发布路由,可以在请求正文中接受一些JSON负载.
I have a post route that accepts some JSON payload in the request body.
Post["/myroute/}"] = _ =>
{
try
{
var model = this.Bind<MyModel>();
}
catch (ModelBindingException e)
{
//PropertyBindException list is empty here,
//so only the first exception can be handled...
}
}
如果存在多个无效的数据类型(即,如果在MyModel中定义了多个int属性,并且用户为这些属性发布了字符串),我想传回这些错误的详细列表,类似于如何使用ModelState原始ASP.NET MVC应用程序中的字典.
If there are multiple invalid data types (i.e. if there are several int properties defined in MyModel, and a user posts strings for those properties), I would like pass back a nice list of these errors, similar to how would use ModelState dictionary in a vanilla ASP.NET MVC application.
尝试在NancyFX中将请求主体中的JSON有效负载绑定到我的模型时,如何完成这种类型的异常处理?
How can I accomplish this type of exception handling when attempting to bind the JSON payload in the request body to my Model in NancyFX?
更新:
在这里查看Nancy源中的DefaultBinder: https://github.com/sloncho/Nancy/blob /master/src/Nancy/ModelBinding/DefaultBinder.cs
Looking through the DefaultBinder in the Nancy source here:https://github.com/sloncho/Nancy/blob/master/src/Nancy/ModelBinding/DefaultBinder.cs
我看到的问题是在此块中:
The problem I see is that in this block:
try
{
var bodyDeserializedModel = this.DeserializeRequestBody(bindingContext);
if (bodyDeserializedModel != null)
{
UpdateModelWithDeserializedModel(bodyDeserializedModel, bindingContext);
}
}
catch (Exception exception)
{
if (!bindingContext.Configuration.IgnoreErrors)
{
throw new ModelBindingException(modelType, innerException: exception);
}
}
Deserialize调用似乎是全有还是全无",它是由一个普通的Exception处理的,而不是由ModelBindException处理的,因此在这里我也看不到任何PropertyBindExceptions.
The Deserialize call seems to be "all or nothing" and it is handled by a plain Exception, not a ModelBindException, so I cannot see any PropertyBindExceptions here either.
我是否需要为此实现一些自定义...?
Should I be needing to implement something custom for this...?
推荐答案
添加您自己的使用newtonsoft忽略错误的自定义主体序列化程序:
Add your own custom body serializer that uses newtonsoft to ignore errors:
public class CustomBodyDeserializer : IBodyDeserializer
{
private readonly MethodInfo deserializeMethod = typeof(JavaScriptSerializer).GetMethod("Deserialize", BindingFlags.Instance | BindingFlags.Public);
private readonly JsonConfiguration jsonConfiguration;
private readonly GlobalizationConfiguration globalizationConfiguration;
/// <summary>
/// Initializes a new instance of the <see cref="JsonBodyDeserializer"/>,
/// with the provided <paramref name="environment"/>.
/// </summary>
/// <param name="environment">An <see cref="INancyEnvironment"/> instance.</param>
public CustomBodyDeserializer(INancyEnvironment environment)
{
this.jsonConfiguration = environment.GetValue<JsonConfiguration>();
this.globalizationConfiguration = environment.GetValue<GlobalizationConfiguration>();
}
/// <summary>
/// Whether the deserializer can deserialize the content type
/// </summary>
/// <param name="mediaRange">Content type to deserialize</param>
/// <param name="context">Current <see cref="BindingContext"/>.</param>
/// <returns>True if supported, false otherwise</returns>
public bool CanDeserialize(MediaRange mediaRange, BindingContext context)
{
return Json.IsJsonContentType(mediaRange);
}
/// <summary>
/// Deserialize the request body to a model
/// </summary>
/// <param name="mediaRange">Content type to deserialize</param>
/// <param name="bodyStream">Request body stream</param>
/// <param name="context">Current context</param>
/// <returns>Model instance</returns>
public object Deserialize(MediaRange mediaRange, Stream bodyStream, BindingContext context)
{
//var serializer = new JavaScriptSerializer(this.jsonConfiguration, this.globalizationConfiguration);
//serializer.RegisterConverters(this.jsonConfiguration.Converters, this.jsonConfiguration.PrimitiveConverters);
if (bodyStream.CanSeek)
{
bodyStream.Position = 0;
}
string bodyText;
using (var bodyReader = new StreamReader(bodyStream))
{
bodyText = bodyReader.ReadToEnd();
}
// var genericDeserializeMethod = this.deserializeMethod.MakeGenericMethod(context.DestinationType);
// var deserializedObject = genericDeserializeMethod.Invoke(serializer, new object[] { bodyText });
object deserializedObject = JsonConvert.DeserializeObject(bodyText, context.DestinationType, new JsonSerializerSettings
{
Error = HandleDeserializationError
});
return deserializedObject;
}
public void HandleDeserializationError(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs errorArgs)
{
string currentError = errorArgs.ErrorContext.Error.Message;
errorArgs.ErrorContext.Handled = true;
}
}
这篇关于当绑定到Request.Body中的JSON时,处理来自NancyFX中ModelBindingException的多个绑定错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!