当Json反序列化失败时,尝试返回正确的错误消息而不是WebAPI默认错误消息{"Message":"The request is invalid.","ModelState"
。
我实现了自定义ActionFilterAttribute:
internal class ValidateModelAttribute : ActionFilterAttribute {
public override void OnActionExecuting(HttpActionContext actionContext) {
if (!actionContext.ModelState.IsValid) {
actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);
}
}
}
}
我用这个属性修饰了我的Controller方法:
[ValidateModelAttribute]
public async Task<HttpResponseMessage> Put(string username, string serviceId, [FromBody] Dictionary<string, string> jsonData)
{
// code
}
如果我在OnActionExecuting
中设置了一个断点,那么只有当jsonData
成功解析为json时它才会中断。如果json无效,它永远不会进入过滤器,并返回相同的错误消息。所以看起来这是在某个地方完成的,但我发现的所有帖子都说这应该是处理这个问题的地方。
知道什么是错的吗?
答案 0 :(得分:1)
由于反序列化在调用方法之前失败,因此永远不会调用该属性,这意味着不会调用修饰方法的属性。您需要一个自定义转换器(处理文化的技术借鉴了this)。
public class Testee {}
public class Tester
{
[JsonConverter(typeof(CustomMesssageConverter<Testee>), "Custom Error Message")]
public Testee Testee { get; set; }
}
public class CustomMesssageConverter<T> : JsonConverter where T : new()
{
private string _customErrorMessage;
public CustomMesssageConverter(string customErrorMessage)
{
_customErrorMessage = customErrorMessage;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
try
{
if (reader.TokenType == JsonToken.Null)
return null;
// Load JObject from stream
JObject jObject = JObject.Load(reader);
// Create target object based on type
var target = new T();
//Create a new reader for this jObject, and set all properties to match the original reader.
JsonReader jObjectReader = jObject.CreateReader();
jObjectReader.Culture = reader.Culture;
jObjectReader.DateParseHandling = reader.DateParseHandling;
jObjectReader.DateTimeZoneHandling = reader.DateTimeZoneHandling;
jObjectReader.FloatParseHandling = reader.FloatParseHandling;
// Populate the object properties
serializer.Populate(jObjectReader, target);
return target;
}
catch(Exception ex)
{
// log ex here
throw new Exception(_customErrorMessage);
}
}
public override bool CanConvert(Type objectType)
{
return typeof(T).IsAssignableFrom(objectType);
}
}