首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Xero Accounting API GetContactsAsync未授权+ Contacts不包含'GetEnumerator‘错误的公共实例定义

Xero Accounting API GetContactsAsync未授权+ Contacts不包含'GetEnumerator‘错误的公共实例定义
EN

Stack Overflow用户
提问于 2020-02-29 23:56:40
回答 2查看 615关注 0票数 1

我一直在尝试学习如何使用Account API,并决定下载并使用文档中提供的XeroOAuth2Sample。(https://github.com/XeroAPI/xero-netstandard-oauth2-samples)

因此,在HomeController.cs中,有一个示例HTTPGet方法,用于从Xero文档提供的API检索发票总数。代码如下:

代码语言:javascript
复制
[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);
        }

因此,我一直在尝试通过制作一个最终从API端点调用联系人的页面来练习和探索API。我已经创建了一个Contact.cs模型类,如下所示:

代码语言:javascript
复制
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; }
    }

然后,我用以下代码创建了一个ContactViewModel.cs,它具有我希望稍后在我的Razor View页面上显示的属性:

代码语言:javascript
复制
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; }
    }

然后,我有我的ContactsViewModel,它是来自ContactViewModel的联系人列表:

代码语言:javascript
复制
public class ContactsViewModel
    {
        public List<ContactViewModel> Contacts { get; set; }
    }

因此,当我尝试为我的联系人发出/调用HTTPGet请求时,我的问题出现了,代码如下:

代码语言:javascript
复制
[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);

        }

因此,第一个错误如下:

代码语言:javascript
复制
ApiException: Error calling GetContacts: {"title":"Unauthorized","status":401,"detail":"AuthorizationUnsuccessful","instance":"354ff497-d29f-468b-9e1c-4345e9ce8123"}

它从"GetContactsAsync“方法返回:

代码语言:javascript
复制
var contactList = await _accountingApi.GetContactsAsync(accessToken, tenantId);

我不确定是否有一些我需要传递的特定值导致了这个错误?我在Xero文档中找不到与此相关的任何内容。尽管将鼠标悬停在GetcontactsAsync上会显示以下内容以获取更多信息:

代码语言:javascript
复制
(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])

最后,正如标题所示,contactList似乎抛出了关于"GetEnumerator“的错误,当使用AddRange将联系人添加到contactsList时,将显示此错误

代码语言:javascript
复制
cannot convert from 'Xero.NetStandard.OAuth2.Model.Contacts' to 'System.Collections.Generic.IEnumerable<XeroOAuth2Sample.Models.ContactsViewModel>'

是不是我在GetContactsAsync中明显遗漏了一些应该存在的东西?提前感谢您的阅读和帮助。

EN

回答 2

Stack Overflow用户

发布于 2020-03-01 01:01:31

除了示例中要求的默认作用域之外,contacts端点还需要一个额外的OAuth2.0作用域。您可以在此处查看示例使用的作用域集:https://github.com/XeroAPI/xero-netstandard-oauth2-samples/blob/master/XeroOAuth2Sample/XeroOAuth2Sample/Startup.cs#L105L106

您可以在我们的文档中查看完整的作用域集合:https://developer.xero.com/documentation/oauth2/scopes

对于您的情况,如果最终想要更新/创建联系人,则需要使用accounting.contacts或accounting.contacts.read作用域来读取联系人,或者使用accounting.contacts作用域

编辑:如果您只想读取联系人,则需要请求并让用户同意accounting.contacts.read作用域。如果要更新/创建联系人,则需要请求并让用户授予对accounting.contacts作用域的同意。accounting.contacts作用域将允许读写访问

票数 3
EN

Stack Overflow用户

发布于 2020-03-01 09:17:53

因此,在向startup.cs添加更多选项之后:

代码语言:javascript
复制
options.Scope.Add("accounting.contacts");
options.Scope.Add("accounting.contacts.read");

我按照建议再次通过了xero注册过程,以重新同意新的范围。我想更正了HomeController中Contacts() HTTPGet方法的语法和一些细微的逻辑。

代码语言:javascript
复制
 [HttpGet]
        [Authorize]
        public async Task<IActionResult> Contacts()
        {
            var token = await _tokenStore.GetAccessTokenAsync(User.XeroUserId());

            var connections = await _xeroClient.GetConnectionsAsync(token);

            ContactsViewModel contacts = new ContactsViewModel();
            contacts.Contacts = new List<ContactViewModel>();

            if (!connections.Any())
            {
                return RedirectToAction("NoContacts");
            }   

            foreach (var connection in connections)
            {
                var accessToken = token.AccessToken;
                var tenantId = connection.TenantId.ToString();

                Contacts contactList = await _accountingApi.GetContactsAsync(accessToken, tenantId);
                contacts.Contacts.AddRange(contactList._Contacts.Select(contact => new ContactViewModel()
                {
                    ContactID = contact.ContactID.ToString(),
                    ContactStatus = contact.ContactStatus.ToString(),
                    Name = contact.Name,
                    FirstName = contact.FirstName,
                    LastName = contact.LastName,
                    IsSupplier = contact.IsSupplier.Value,
                    IsCustomer = contact.IsCustomer.Value
                }).ToList());
            }

            return View(contacts);
        }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60466959

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档