I have an ASP.NET application that uses the Azure AD Graph API. Often, when an invalid operation is performed against the Graph API, an exception is thrown.
The following code shows an invalid Graph API call that would trigger an exception:
// Query the Azure AD User
var userToUpdate = await activeDirectoryClient.Users.GetByObjectId("[email protected]").ExecuteAsync();
// Set given name to an empty string (not allowed)
userToUpdate.GivenName = "";
try
{
// Update the user in Azure AD
await userToUpdate.UpdateAsync();
}
catch (Exception e)
{
// Return exception message
}
The message of the inner exception is a JSON string with forward slashes before each quotation mark. It looks something like this:
"{\"odata.error\":{\"code\":\"Request_BadRequest\",\"message\":{\"lang\":\"en\",\"value\":\"Invalid value specified for property 'givenName' of resource 'User'.\"},\"values\":[{\"item\":\"PropertyName\",\"value\":\"givenName\"},{\"item\":\"PropertyErrorCode\",\"value\":\"InvalidValue\"}]}}"
Attaching a screenshot of the Locals window where the exception message is found:
I would like to convert this JSON to a .NET object to return informative error details. I am using the JSON.NET library for this, and I am assuming that the JSON will deserialize to an ODataError
object:
var error = Newtonsoft.Json.JsonConvert.DeserializeObject<ODataError>(e.InnerException.Message);
However, the deserialized object always has a value of null
, which means that the conversion is not working as expected.
That being said, what class should the above JSON string map to? Also, should I be removing the forward slashes from the string for proper deserialization?
The reason you've got null after deserialization is your JSON object properties names differs from Microsoft.Azure.ActiveDirectory.GraphClient.ODataError
class properties names - "odata.error" property can not be deserialized to Error property of Microsoft.Azure.ActiveDirectory.GraphClient.ODataError
As workaround I've added my own types for correct deserialization:
internal class ODataError
{
[JsonProperty("odata.error")]
public ODataErrorCodeMessage Error { get; set; }
}
internal class ODataErrorCodeMessage
{
public string Code { get; set; }
public ODataErrorMessage Message { get; set; }
public List<ExtendedErrorValue> Values { get; set; }
}
internal class ExtendedErrorValue
{
public string Item { get; set; }
public string Value { get; set; }
}
internal class ODataErrorMessage
{
public string Lang { get; set; }
public string Value { get; set; }
}
After that JSON message was properly deserialized:
...
try
{
await ADClient.Users.AddUserAsync(newUser);
return Result.Ok();
}
catch (DataServiceRequestException ex)
{
var innerException = ex.InnerException;
var error = JsonConvert.DeserializeObject<ODataError>(innerException.Message);
return Result.Fail(new Error(error.Error.Message.Value, error.Error.Code, ex));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With