I've been trying to learn how to use the Account API and decided to download and use the XeroOAuth2Sample that's provided on the docs. (https://github.com/XeroAPI/xero-netstandard-oauth2-samples)
So within the HomeController.cs, there is an example HTTPGet method used to retrieve the total number of Invoices from the API which is provided by the Xero docs. The code is as follows:
[HttpGet]
[Authorize]
public async Task<IActionResult> OutstandingInvoices()
{
var token = await _tokenStore.GetAccessTokenAsync(User.XeroUserId());
var connections = await _xeroClient.GetConnectionsAsync(token);
if (!connections.Any())
{
return RedirectToAction("NoTenants");
}
var data = new Dictionary<string, int>();
foreach (var connection in connections)
{
var accessToken = token.AccessToken;
var tenantId = connection.TenantId.ToString();
var organisations = await _accountingApi.GetOrganisationsAsync(accessToken, tenantId);
var organisationName = organisations._Organisations[0].Name;
var outstandingInvoices = await _accountingApi.GetInvoicesAsync(accessToken, tenantId, statuses: new List<string>{"AUTHORISED"}, where: "Type == \"ACCREC\"");
data[organisationName] = outstandingInvoices._Invoices.Count;
}
var model = new OutstandingInvoicesViewModel
{
Name = $"{User.FindFirstValue(ClaimTypes.GivenName)} {User.FindFirstValue(ClaimTypes.Surname)}",
Data = data
};
return View(model);
}
So I have been trying to practice and explore the API by making a page that would eventually call the Contacts from the API endpoint. I have created a Contact.cs Model class that looks like so:
public class Contact
{
public string ContactID { get; set; }
public string ContactStatus { get; set; }
public string Name { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
public string SkypeUserName { get; set; }
public string BankAccountDetails { get; set; }
public string TaxNumber { get; set; }
public string AccountsReceivableTaxType { get; set; }
public string AccountsPayableTaxType { get; set; }
public List<Address> Addresses { get; set; }
public List<Phone> Phones { get; set; }
public DateTime UpdatedDateUTC { get; set; }
public bool IsSupplier { get; set; }
public bool IsCustomer { get; set; }
public string DefaultCurrency { get; set; }
}
I have then created a ContactViewModel.cs which has the properties that I want to later on display on my Razor View page with the following code:
public class ContactViewModel
{
public string ContactID { get; set; }
public string ContactStatus { get; set; }
public string Name { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool IsSupplier { get; set; }
public bool IsCustomer { get; set; }
public string DefaultCurrency { get; set; }
}
And then, I have my ContactsViewModel which is a list of Contacts from the ContactViewModel:
public class ContactsViewModel
{
public List<ContactViewModel> Contacts { get; set; }
}
So my issue(s) arrise when I try and make / call the HTTPGet request for my Contacts, the code is as follows:
[HttpGet]
[Authorize]
public async Task<IActionResult> Contacts()
{
var token = await _tokenStore.GetAccessTokenAsync(User.XeroUserId());
var connections = await _xeroClient.GetConnectionsAsync(token);
if (!connections.Any())
{
return RedirectToAction("NoContacts");
}
foreach (var connection in connections)
{
var accessToken = token.AccessToken;
var tenantId = connection.TenantId.ToString();
var contactList = await _accountingApi.GetContactsAsync(accessToken, tenantId);
List<ContactsViewModel> contacts = new List<ContactsViewModel>();
foreach (var contact in contactList)
{
contacts.Add(new ContactViewModel
{
ContactID = contact.ContactID,
ContactStatus = contact.ContactStatus,
Name = contact.Name,
FirstName = contact.FirstName,
LastName = contact.LastName,
IsSupplier = contact.IsSupplier,
IsCustomer = contact.IsCustomer
});
}
contacts.AddRange(contactList);
}
var model = new ContactsViewModel()
{
// Contacts = contacts
};
return View(model);
}
So the first error is as follows:
ApiException: Error calling GetContacts: {"title":"Unauthorized","status":401,"detail":"AuthorizationUnsuccessful","instance":"354ff497-d29f-468b-9e1c-4345e9ce8123"}
Which is returned from the "GetContactsAsync" method:
var contactList = await _accountingApi.GetContactsAsync(accessToken, tenantId);
Im unsure if there's specific values that I'm missing which I also need to pass that's causing this error? I couldn't find anything regarding this on the Xero documentation. Although hovering over the GetcontactsAsync displays this for the further info:
(awaitable) Task<Xero.NetStandard.OAuth2.Model.Contacts> IAccountingApiAsync.GetContactsAsync(string accessToken, stringXeroTenantId, [System.DateTime? ifModifiedSince = null], [string where = null], [string order = null], [List<System.Guid> iDs = null], [int? page = null], [bool? includeArchived = null])
And lastly, contactList seems to throw errors as the title suggests regarding the "GetEnumerator" and when the contacts is added to the contactsList using the AddRange, this error is displayed
cannot convert from 'Xero.NetStandard.OAuth2.Model.Contacts' to 'System.Collections.Generic.IEnumerable<XeroOAuth2Sample.Models.ContactsViewModel>'
Is there something that I'm clearly missing out from the GetContactsAsync that should be there? Thank you in advance for reading and helping.