JSON.当为对象传递无效值时,网络反序列化程序不会生成异常
本文关键字:程序 反序列化 网络 异常 对象 无效 JSON | 更新日期: 2023-09-27 18:12:28
我有以下结构:
public class SampleEntity{
public string Name { get; set; }
public OtherEntity Relation { get; set; }
}
public class OtherEntity {
public string Name { get; set; }
}
当我调用更新web中的对象时。具有以下请求体的API:
"{'Name':'Nome', 'Relation':''}"
反序列化器用空值填充对象,但我认为正确的操作是抛出异常,如"字段关系的无效值",我可以返回状态码400。
我试图使自定义转换器做到这一点,但我不满意的解决方案,我很关心这个性能。
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartObject)
{
var @object = JObject.Load(reader);
var target = Activator.CreateInstance(objectType);
var objectProperties = target.GetType().GetProperties().Where(x => x.PropertyType.IsPrimitive == false && x.PropertyType != typeof(string));
foreach (var prop in objectProperties)
{
var value = @object[prop.Name];
if (value != null && value.ToString() == string.Empty)
throw new Exception();
}
serializer.Populate(@object.CreateReader(), target);
return target;
}
return reader.Value;
}
当验证失败时,Web API不会自动返回错误给客户端。由控制器动作来检查模型状态并作出适当的响应。虽然@loop的答案可以工作,但您可能需要考虑另一个选项,这样您甚至不必输入控制器的动作方法。
为此,您可以创建一个动作过滤器,以便在调用控制器动作之前检查模型状态。
例如:public class ValidateModelAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (actionContext.ModelState.IsValid == false)
{
actionContext.Response = actionContext.Request.CreateErrorResponse(
HttpStatusCode.BadRequest, actionContext.ModelState);
}
}
}
注意,您将仍然需要用描述验证规则的属性来修饰您的模型。这将类似于@loop所建议的。
如果模型验证失败,这个过滤器返回一个包含验证错误的HTTP响应。在这种情况下,控制器动作不会被调用。
要将此过滤器应用于所有Web API控制器,请在HttpConfiguration中添加该过滤器的实例。配置期间的过滤器收集:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Filters.Add(new ValidateModelAttribute());
// ...
}
}
另一个选择是将过滤器设置为单个控制器或控制器动作的属性:
public class EntitiesController : ApiController
{
[ValidateModel]
public HttpResponseMessage Post(SampleEntity entity)
{
// ...
}
}
有关更详细的解释,请查看本文。要了解可以用来定义验证规则的各种模型注释,例如[Required]
等,请查看MSDN页面