2015-10-14 32 views
2

當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無效,它永遠不會進入過濾器,並返回相同的錯誤消息。所以看起來這是在之前的某個地方完成的,但是我發現的所有帖子都說這應該是處理這個問題的地方。

任何想法有什麼不對?

回答

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); 
    } 
} 
相關問題