In the default implementation of the JsonValueProviderFactory, JavaScriptSerializer.DeserializeObject() method is used. This method throws an exception if the json string is ill-formed. The server then throws a 500 yellow page to the browser. I want to suppress the exception and show a custom error message through my controller action.
This is what I tried. I removed the default JsonValueProviderFactory and introduced a custom JsonValueProviderFactory with essentially the same code. The only difference is in the GetDeserializedObject method where I have introduced a try-catch block.
private static object GetDeserializedObject(ControllerContext controllerContext)
{
if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
{
// not JSON request
return null;
}
StreamReader reader = new StreamReader(controllerContext.HttpContext.Request.InputStream);
string bodyText = reader.ReadToEnd();
if (String.IsNullOrEmpty(bodyText))
{
// no JSON data
return null;
}
JavaScriptSerializer serializer = new JavaScriptSerializer();
object jsonData = null;
try
{
jsonData = serializer.DeserializeObject(bodyText);
}
catch (Exception ex) {
ex.Data["jsonString"] = bodyText;
throw;
}
return jsonData;
}
Instead of simply throwing the exception, I want to pass the exception error message to the modelbinder and eventually set it in the modelstate dictionary. Then I can read the modelstate dictionary in controller action and customize the error message sent to browser. Can this be done ?
If it can’t be done, is there an alternative way to achieve the same goal ?
I finally found the right way of doing it. I am documenting it for future reference by others.
This is exactly how the modelstate in modelbindingContext of modelbinder is set. I copying the relevant snippent of code from MVC3 sources. The method is present in ControllerActionInvoker.cs.