Validation in .NET Standard
We are using OAuth2 v3.1 and OAuth2Client 1.3.3
I am in the process of upgrading to OAuth2.0. In older framework we did validation in way similar to this.
try
{
xeroInvoice = api.Create(xeroInvoice);
}
catch (ValidationException ex)
{
ex.ValidationErrors.ForEach(error =>
{
LogError(error.Message, ex);
});
};
In OAuth2.0 the ValidationException no longer exists. So we have code similar to this.
try
{
var xeroInvoices = new Xr.Invoices();
xeroInvoices._Invoices = new List<Xr.Invoice>() {
xeroInvoice
};
api.CreateInvoicesAsync(_accessToken, _xeroTenantId, xeroInvoices, true);
}
catch (Exception ex)
{
// How do I capture validation errors
}
Is there any way to capture the validation issues easily in the new framework?
Is this a dup' of https://github.com/XeroAPI/Xero-NetStandard/issues/346 ?
I've found that if I catch an ApiException, I get this object returned in the ErrorContent property (in json format) Then it's just a case of parsing that to get similar to the previous SDK (also currently migrating some code)
Xero.NetStandard.OAuth2.Client.ApiException: Xero API 400 error calling CreatePayment :{ "ErrorNumber": 10, "Type": "ValidationException", "Message": "A validation exception occurred", "Elements": [ { "Date": "\/Date(1626912000000)\/", "Amount": 5000.00, "Reference": "TestReference", "Status": "AUTHORISED", "HasAccount": true, "Account": { "AccountID": "d1ebb97b-d207-4ccb-9ab6-8a466a8b4d39", "Code": "200", "Name": "Sales", "Status": "ACTIVE", "Type": "REVENUE", "TaxType": "OUTPUT", "Description": "Income from any normal business activity", "Class": "REVENUE", "SystemAccount": "", "EnablePaymentsToAccount": false, "ShowInExpenseClaims": false, "BankAccountType": "NONE", "ReportingCode": "REV.TRA.GOO", "ReportingCodeName": "Sale of goods", "UpdatedDateUTC": "\/Date(1625138692100+0000)\/", "AddToWatchlist": true }, "Invoice": { "InvoiceID": "a3d09691-15f3-47f4-8ab9-241e7120e230", "Payments": [], "CreditNotes": [], "Prepayments": [], "Overpayments": [], "IsDiscounted": false, "HasErrors": false, "LineItems": [], "ValidationErrors": [] }, "HasValidationErrors": true, "ValidationErrors": [ { "Message": "Account type is invalid for making a payment to/from" } ] } ] }
Is there an upgrade path document somewhere? Having to deal with OAuth2 and a client migration has been pretty difficult and Xero docs don't seem to explain anything except the bare minimum
I'd like to second @nganbread's question on if there is anything documented for this. I'm trying to catch ApiException like @bryanallott stated but I don't seem to get that exception type returned back to me when trying to intentionally induce an error.
Here is our utility to extract error messages from Xero Exceptions:
private IEnumerable<string> GetErrors(ApiException apiException) {
if (apiException.ErrorContent == null)
return new List<string>(){"Xero failed with no specific error code"};
try {
string errorContent = Convert.ToString(apiException.ErrorContent);
if (errorContent.Contains("504 Gateway Time-out") ||
errorContent.Contains("Internal Server Error") ||
errorContent.Contains("An error occurred in Xero") ||
errorContent.Contains("An error occurred while processing your request") ||
errorContent.Contains("An error has occurred during the authentication process") ||
errorContent.Contains("NoDataProcessedException") ||
errorContent.Contains("consumer_key_unknown")) {
return new List<string>() { "An error occurred in Xero. Check the <a target='_blank' href='http://status.developer.xero.com '>API Status page</a> for current service status. Contact the API support team at [email protected] for more assistance" };
}
if (errorContent.Contains("Forbidden") || errorContent.Contains("Unauthorized")) {
return new List<string>() { "API access is forbidden. You might want to reinstall your Xero integration"};
}
var json = JsonConvert.DeserializeObject<ErrorResponse>(errorContent);
var messages = json.Elements.SelectMany(e => e.ValidationErrors.Select(v => v.Message)).Distinct();
return messages;
} catch (Exception e) {
return new List<string>(){$"Error parsing ApiException {apiException.ErrorContent}"};
}
}
@TOuhrouche thanks for posting this code for parsing out xero api exceptions, what is the "ErrorResponse" type which you deserialize the errorContent to here?
var json = JsonConvert.DeserializeObject<ErrorResponse>(errorContent);
I ended up parsing out the validation error like this:
if (ex is not ApiException apiException) throw;
var deserializedObject = JObject.Parse(apiException.ErrorContent) as JObject;
var type = (string)deserializedObject["Type"];
if (type is not "ValidationException") throw;
var message = (string)deserializedObject.SelectToken("Elements[0].ValidationErrors[0].Message");
@pellet ErrorResponse is an object we use to deserialize the dynamic content.
public class ErrorResponse { public Element[] Elements { get; set; } }
public class Element { public ValidationError[] ValidationErrors { get; set; } }
public class ValidationError { public string Message { get; set; } }