【Power Apps】含淚總結,暴露 Dataverse 查詢接口,通過 token 認證查詢數據

我與 Power Apps 的孽緣

我與 Power Apps 的緣分,大概始於團隊內部培訓的需求,當時負責人找到我,想讓我推薦一個能夠上傳內部培訓視頻及其他資料的平臺。能夠讓編程小白也能夠上手管理使用的平臺,大概也就微軟這種以 Visual 起家的公司才能夠做起來了。小時候剛接觸計算機,首先接觸到的就是微軟的 Office 套件,其中就包括傻瓜建站的 FrontPage,Dreamweaver 是初中微機課才接觸的,因此與 Adobe 的關係疏遠一些。SharePoint 大概是 FrontPage 的繼任者吧,現在已經聽不到 FrontPage 的大名了。SharePoint 還推出了在線版,高大上的風格鼠標點點拖拖就有,能以文件和文件夾的形式管理網頁和網頁素材,視頻能夠在網頁就在線播放(甚至3D模型文件也能夠在線查看,支持文件類型之廣讓我意想不到),即使是編程小白也能夠管理好自家的網站。在這過程中,我註冊了2個團隊,一個用來做各種原型測試,一個是團隊的正式網站。
在測試的過程中,我也發現了 SharePoint 與 Teams 等工具的緊密整合,還有一個 Power Platform,有什麼 Power Agent 智能客服、Power Automate 之類,似乎有各種高大上的功能等着我去探索發現。“亂花漸欲迷人眼”,小小的腦袋還理解不了這麼多工具協同工作的強大,最後像一粒種子,默默地落地、播種、生根發芽。

Power Automate —— 自動化

第二次去挖掘 Power Platform 是出於一個不經意的需求。有些老文件格式,只有一些老軟件才能夠打開,在當時是能有工具用就行,開發者也並沒有考慮到什麼便利性,然而若干年後再同樣一個文件一個文件導出操作就痛苦了,最後發現 Power Automate 出奇好用。Python 的軟件自動操作腳本是基於圖像識別匹配,但是 Power Automate 一出手就不一樣,它檢測的居然是控件!相比於圖像方法,處理速度理論上就產生了很大區別。通過 Power Automate 錄製重複的鍵盤和鼠標操作(點贊“跟我學”功能!),最終解放了我的雙手,加速了舊文件格式的遷移。當然也有不足之處,保存和運行前準備的時間都比較長,不如 Python 馬上就能跑起來。
以上是 Power Automate 的桌面版本,雲端版本 Flow 則對接了多種微軟自家服務以及第三方服務(WordPress、推特等),其中最令人欣喜的還是 RSS,自從 Google 關閉 Reader 服務,微信有了公衆號,Inoreader 於疫情中跌落神壇,RSS 日漸式微,至少還有 Flow 能夠爲我檢查 RSS 更新,然後發送到我的郵箱當中永久保存,隨時查看,不用再擔心遺失。

Low Code - 低代碼

第三次挖掘 Power Platform 時的主旋律則是低代碼。作爲多年程序猿,其實我是不屑於低代碼的。我只是看中低代碼附加的兩點:自動化和服務雲託管。自動化已在上面提到,服務雲託管則是重頭戲,沒有服務器但勝似服務器,Power Platform 就是這樣一個平臺,試想一下:

  • SharePoint 的文件管理,不正是一個雲端的硬盤嗎?
  • Power Automate 的自動化,不正是一個網卡與處理器嗎?
  • Dataverse 及其 OData 查詢接口,不正是數據庫與SQL嗎?

讓 Power Automate 成爲網卡的核心還是它的 HTTP 請求功能,你可以用它在雲端下載文件,存儲到 SharePoint 裏。搭配 Power Agent 怎麼樣?跟 Power Agent 說,幫我下載某個文件,下載完畢以後,放在 SharePoint 裏,Power Agent 通知你下載成功,到 SharePoint 去取。下載 Github Releases 的文件是不是多了一種方法?;-P
隨着低代碼再次深入發展,現在出現了 Retool 這樣的半前端半後端。既能夠有精美的界面,又能夠實現很多隻有在服務器上能,在網頁客戶端難以進行的操作,說的就是 SQL 查詢。說到這是不是摩拳擦掌想要連接一下 Ensembl 等開放了 MySQL/MariaDB 端口的數據庫,做一個船新版本的生信分析工具了?現在 Retool 也在測試自己的 PostgreSQL 數據庫,雲設施正在逐步完善,還需要擔心沒有自己的服務器嗎?
雖然如此,作爲與 Power Platform 其他成員緊密連接的 Dataverse 數據庫也不能忽視,通過 Dataflows 能夠導入網上的 csv 文件,甚至自己的 csv 文件(同時進行託管),通過與 Power Automate 桌面客戶端連接還能夠抓取網頁、PDF 中的表格數據,這是其他低代碼平臺所沒有的功能(MongoDB 也有 Datalake 可以導入 csv,但是不能從網頁和 PDF 抓取表格數據;百度的 Sugar BI 也很正式,只能從正規數據庫導入數據進行分析)。此外,xmljson兩個函數能夠分別輕鬆讀取網絡請求返回的 xml 和 json 數據並能夠快速互轉。

夢幻聯動,雙廚狂喜 —— Retool + Dataverse

Dataverse 使用的是 OData 規範進行數據查詢,簡單來說就是 OAuth 認證後就能通過 URL 來表達查詢意圖,返回 JSON 數據;Retool 也在完善自己的數據庫連接方法,其中就包括 OAuth。兩者理論上輕而易舉就能實現聯動,Retool 爲前端與半後端負責查詢數據,Dataverse 負責檢索數據,Flow 負責獲取與維護數據。但要想完成這樣的聯動並不容易——資料和用戶都太少,以至於我深深感覺有必要寫本文來吸引更多的人把目光投向 Dataverse,投向 OData,希望後來者能夠少踩坑。
Dataverse 需要 OAuth 認證才允許應用訪問數據,以保持數據安全。需要到 Azure Active Directory (Azure AD) 去創建應用、生成 token。這個過程在《Use OAuth authentication with Microsoft Dataverse》中已經有敘述。但是“心急吃不了熱豆腐”,我忽略了 Dataverse user account bound to the registered app 這部分(也是《Dynamics 365 and Python integration using the Web API》這種用戶名+密碼認證訪問數據試驗成功的後遺症,微軟家的文檔真的是又大又雜啊,沒有耐心認真看),沒有將自己的應用添加爲 Application User,導致 token 認證的方法一直無法獲取到數據,令我一度認爲非訂閱用戶不能夠開啓使用 token 從外部訪問內部數據的功能。
此外一直在掙扎於區分各種術語,什麼clien IDtenant IDresourcescope,我把很多時間浪費在填寫 Azure AD 的Expose an API > Scopes上,一直認爲是這裏填寫不規範導致的授權錯誤,但實際上我們不需要按照操作說明在這裏過多做什麼。
下面這句話令人十分費解。

Add a scope. Set the URI value to your target environment (organization) base address.

什麼是target environment (organization) base address?和resource是否一致?走過以後回頭看,這其實並不重要,因爲這裏不需要自己定義什麼scopescope格式另有模板,下面會說到。
幾個功能入口也是如走迷宮一般跌跌撞撞才找到。

CRM 地址(Environment URL)

也就是自己的團隊地址,一開始以org+數字作爲開頭,API 的URL都不好看,參看《How to Rename a Dynamics 365 Org》進行獲取和修改。resource的URL也是在 environment URL的基礎上修改得到的。

Endpoints

在 Azure AD > App registrations > 你的應用 > Overview > 右邊主欄上方標籤欄的 Endpoints,需要使用OAuth 2.0 authorization endpoint (v2)https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize只是模板,不要天真地複製就粘貼到 Retool 的 OAuth 認證裏,organizations需要改爲tenant ID,在你的 Azure AD 應用的 Overview 裏面找。至於Client ID也是在 Overview 見到。Retool 需要的Client Secret在 Azure AD 應用 > Certificates & secrets > Client secrets,自己生成後,Secret ID沒有什麼用,不需要複製,只需要複製Value作爲Client Secret。Retool 需要的Scopes不需要從 Azure AD 應用 > Expose an API 中生成和複製,參照例子看到的是,Scopes居然是resource+/.default!下面的代碼通過分析文檔,發現是在請求{resource}/WhoAmI,驗證是否已經登錄。這其實也比較重要,因爲 Retool 會緩存 token,即使更新了 token,如果沒有驗證 token 是否失效的機制,即使配置正確也還是獲取不到數據,總會出現401 Unauthorized

var response = client.GetAsync("WhoAmI").Result;

出現401 Unauthorized時注意看 Retool 請求及 Dataverse 返回的信息,如果Bearer OAUTH2_TOKENOAUTH2_TOKEN已經成功替換爲實際的 token,說明自己的 OAuth 部分並沒有填寫錯誤,應該把注意力放到獲取到 token 以後的步驟是否有錯,最可能的就是緩存的 token 無效了。
編寫 OData 查詢時,注意使用Logical name,在表格或字段的屬性面板展開Advanced options可以看到;表格名字除了使用Logical name還需要注意使用複數形式,否則可能提示該表不存在。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章