Capture exception during request deserialization in WebAPI C#

只愿长相守 提交于 2019-12-18 03:10:15

问题


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] attribute on an internal method, like this:

[OnDeserialized]
internal void OnDeserialisedMethod(StreamingContext context) {
    // my method code
}

I know for a fact there is a problem with the code inside this method, I've stepped through it and found it. The problem for me is that I get no exception at all. What happens is this method gets jumped out of and the exception seems to be ignored. My controller action gets called and my target object is not properly populated because this serialisation method has not been correctly executed.

My question is; how can I capture an exception that occurs during deserialisation in WebAPI?


回答1:


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.




回答2:


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));
    }
}



回答3:


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.



来源:https://stackoverflow.com/questions/28835869/capture-exception-during-request-deserialization-in-webapi-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!