使用 SAP UI5 消費 OData 服務的一些常見錯誤和解決方案

注销發表於2022-02-20

錯誤訊息1

Access to XMLHttpRequest at 'http://localhost:8081/https:/...$metadata?sap-language=EN' from origin 'http://localhost:8080' has been blocked by CORS policy: Request header field maxdataserviceversion is not allowed by Access-Control-Allow-Headers in preflight response.

原因是 maxdataserviceversion 這個和 OData 服務版本相關的欄位,沒有出現在伺服器端配置的 Access-Control-Allow-Headers 陣列裡,因此引起了跨域 CORS error.

maxdataserviceversion 這個欄位在 Chrome 開發者工具 network 標籤頁裡能看到:

解決方案:

app.all('*', function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "*");
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
    res.header("X-Powered-By",' 9.0.0');
    next();
  });

Access-Control-Allow-Headers 的值改成 * 即可。錯誤消失:

錯誤2

下面 url 對應的 metadata,無法在瀏覽器里正常顯示。期望的結果是,位址列裡輸入 url 之後,我們能看到 http://localhost:8081/ 後面的 metadata 實際的內容,以 xml 格式正常顯示:

http://localhost:8081/https:/...$metadata?sap-language=EN

正常情況下,請求的 header 欄位是:
Accept: application/xml

根據 express response 物件的 API 說明,如果 send 方法傳入的引數是一個字串,則響應結構的 Content-Type 自動設定為text/html

這一點可以在 Postman 裡觀察到:

我們可以在代理伺服器的實現裡,使用 res.set 方法可以將 Content-Type 手動修改成 application/xml

這樣,在瀏覽器裡就能正常顯示, 透過代理伺服器獲取的 xml 格式的 metadata 了:

錯誤訊息3

The /$batch resource only supports POST method request

header 欄位裡包含了 boundary 值:

對於 $batch 操作來說,Accept 的值為 multipart/mixed

確實就掛起了:

當消費者想要執行多個獨立的 HTTP 呼叫並希望避免多次伺服器往返時,通常會使用 OData 批處理請求。

在 SAP UI5 裡使用 OData Model 傳送 batch 請求的示例程式碼如下:

var tmpModel = new ODataModel("https://xxyyzz.com/sap/opu/odata/<your_service>_SRV/", true);
tmpModel.setDefaultBindingMode(sap.ui.model.BindingMode.TwoWay);
tmpModel.setUseBatch(true);
this.getView().setModel(tmpModel, "tmpModel");
tmpModel.setDeferredGroups(["foo"]);
var mParameters = {groupId:"foo",success:function(odata, resp){ console.log(resp); },error: function(odata, resp) { console.log(resp); }};

for(var m=0; m<oPayload.length; m++) {
    tmpModel.update("/YOUR_ENTITYSet(Key1='Valu1',Key2='Value2')", oPayload[m], mParameters);
}
tmpModel.submitChanges(mParameters);

更多Jerry的原創文章,盡在:"汪子熙":

相關文章