当JSON负载无效时,自定义ActionFilterAttribute不会被调用

问题描述:

当Json反序列化失败时,尝试返回正确的错误消息而不是WebAPI默认的错误消息{"Message":"The request is invalid.","ModelState"当JSON负载无效时,自定义ActionFilterAttribute不会被调用

我实现我的自定义ActionFilterAttribute:

internal class ValidateModelAttribute : ActionFilterAttribute { 
    public override void OnActionExecuting(HttpActionContext actionContext)  { 
     if (!actionContext.ModelState.IsValid) { 
      actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState); 
     } 
    } 
} 

}

我饰我的控制器方法与此属性:

[ValidateModelAttribute] 
    public async Task<HttpResponseMessage> Put(string username, string serviceId, [FromBody] Dictionary<string, string> jsonData) 
    { 
     // code 
    } 

如果我在OnActionExecuting设置断点只休息时jsonData作为json被成功解析。如果json无效,它永远不会进入过滤器,并返回相同的错误消息。所以看起来这是在之前的某个地方完成的,但是我发现的所有帖子都说这应该是处理这个问题的地方。

任何想法有什么不对?

该属性将永远不会被调用,因为反序列化在该方法被调用之前失败,这意味着装饰该方法的属性不会被调用。你需要一个自定义的转换器(处理文化的技术是从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); 
    } 
}