Capture exception during request deserialization in WebAPI C#

前端 未结 3 1712
-上瘾入骨i
-上瘾入骨i 2020-12-09 17:32

I\'m using WebAPI v2.2 and I am getting WebAPI to deserialise JSON onto an object using [FromBody] attribute. The target class of the deserialisation has a [OnDeserialized]

相关标签:
3条回答
  • 2020-12-09 17:51

    You can check ModelState.IsValid inside your controller. If "OnDeserialisedMethod" throws an exception (or any other model validation fails) it will be false, if everything succeed it will be true.

    0 讨论(0)
  • 2020-12-09 17:53

    I had exactly the same problem and bookmarked your question in hope that someone would provide a solution. I thought using ModelState implied rewriting some validations in the JSON model, but it just works, in fact it's simple and very well done. I didn't have to modify the model, just the controllers.

    My code from one of my controllers, StdResponse being the class used to provide the response with details if needed (in this case, for instance) :

    [HttpPost]
    public StdResponse Test([FromBody]StdRequest request)
    {
        if (ModelState.IsValid)
        {
            //Work on the data from the request...
        }
        else
        {
            //Retrieve the exceptions raised during deserialization
            var errors = ModelState.SelectMany(v => v.Value.Errors.Select(e => e.Exception));
    
            List<String> messages = new List<string>();
    
            foreach (Exception e in errors)
            {
                messages.Add(e.GetType().ToString() + ": " + e.Message);
            }
    
            return new StdResponse(exchangeVersion, "null", ExecutionResponse.WithError("StdRequest invalid", messages));
        }
    }
    
    0 讨论(0)
  • 2020-12-09 18:07

    I've written up a filter (as suggested in various comments) that checks the ModelState and throws an exception if serialization errors did occur. Beware though, that this may not contain only serialization exceptions - that could be adjusted by specifing the concrete exception type in the Select statement.

    public class ValidModelsOnlyFilter : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            if (actionContext.ModelState.IsValid)
            {
                base.OnActionExecuting(actionContext);
            }
            else
            {
                var exceptions = new List<Exception>();
    
                foreach (var state in actionContext.ModelState)
                {
                    if (state.Value.Errors.Count != 0)
                    {
                        exceptions.AddRange(state.Value.Errors.Select(error => error.Exception));
                    }
                }
    
                if (exceptions.Count > 0)
                    throw new AggregateException(exceptions);
            }
        }
    }
    

    I suggest binding this filter on a global scope. I really can't fathom why it should be ok to ignore deserialization exceptions.

    0 讨论(0)
提交回复
热议问题