从 SAPUI5 使用 OData V4

Consuming OData V4 from SAPUI5

我正在尝试将 OData V4 与 SAPUI5 一起使用。虽然看起来很简单,但我面临着几个问题。

我正在使用来自 Demokit 的 sap.ui.layout.sample.SimpleFormToolbar 示例。实现了一个 OData V4 服务以简单的形式显示数据。

我在这个应用程序中所做的更改:
1. manifest.json 和
2. 表单控件的Context Binding的Page.view.xml
3.删除了controller和index.html

中mockdata的代码引用

但是,由于以下错误,我无法获取数据:

1
2
3
2019-07-07 08:58:23.736110 Failed to update path /Suppliers(12345)/Country - **Error: Must not change a property before it has been read**

**Uncaught Error: Must not change a property before it has been read**

另一个错误与批处理模式有关。我没有在 Odata impl 中实现任何批处理。

1
2
2019-07-07 08:58:24.279114 **$batch failed** - Error: Network error
2019-07-07 08:58:24.281175 Failed to read path /Suppliers(12345) - Error: **HTTP request was not processed because $batch failed**

我使用的代码是:

//manifest.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
{
   "_version":"1.12.0",
   "sap.app": {
       "id":"sap.ui.layout.sample.SimpleFormToolbar",
       "applicationVersion": {
           "version":"1.0.0"
        },
       "dataSources": {
         "supplierOData": {
           "uri":"https://supplierappp1014576trial.hanatrial.ondemand.com/SupplierApp/SupplierService.svc/",
           "type":"OData",
           "settings": {
             "odataVersion":"4.0"
            }
          }
        }
    },
   "sap.ui5": {
       "rootView": {
           "viewName":"sap.ui.layout.sample.SimpleFormToolbar.Page",
           "type":"XML",
           "async": true
        },
       "dependencies": {
           "libs": {
               "sap.ui.layout": {}
            }
        },
       "models": {
           "": {
               "dataSource":"supplierOData",
               "settings" : {
                   "synchronizationMode" :"None"
                }
            }
        },
       "config": {
           "sample": {
               "files": [
                   "Page.view.xml",
                   "Page.controller.js",
                   "manifest.json"
                ]
            }
        }
    }
}

//Page.view.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<mvc:View
    controllerName="sap.ui.layout.sample.SimpleFormToolbar.Page"
    xmlns:l="sap.ui.layout"
    xmlns:f="sap.ui.layout.form"
    xmlns:mvc="sap.ui.core.mvc"
    xmlns:core="sap.ui.core"
    xmlns="sap.m">
    <VBox class="sapUiSmallMargin">
        <f:SimpleForm id="SimpleFormToolbar"
            binding="{/Suppliers(12345)}"
            editable="true"
            layout="ResponsiveGridLayout"
            labelSpanXL="4"
            labelSpanL="3"
            labelSpanM="4"
            labelSpanS="12"
            adjustLabelSpan="false"
            emptySpanXL="0"
            emptySpanL="4"
            emptySpanM="0"
            emptySpanS="0"
            columnsXL="2"
            columnsL="1"
            columnsM="1"
            singleContainerFullSize="false"
            ariaLabelledBy="Title1">
            <f:toolbar>
                <Toolbar id="TB1">
                    <Title id="Title1" text="Address" level="H4" titleStyle="H4"/>
                    <ToolbarSpacer />
                    <Button icon="sap-icon://settings"/>
                    <Button icon="sap-icon://drop-down-list" />
                </Toolbar>
            </f:toolbar>
            <f:content>
                <Toolbar ariaLabelledBy="Title2">
                    <Title id="Title2" text="Office" level="H5" titleStyle="H5"/>
                    <ToolbarSpacer />
                    <Button icon="sap-icon://settings"/>
                </Toolbar>
                <Label text="Name" />
                <Input value="{SupplierName}" />
                <Label text="Street/No." />
                <Input value="{Street}">
                </Input>
                <Input value="{HouseNumber}">
                    <layoutData>
                        <l:GridData span="XL2 L1 M3 S4" />
                    </layoutData>
                </Input>
                <Label text="ZIP Code/City" />
                <Input value="{ZIPCode}">
                    <layoutData>
                        <l:GridData span="XL2 L1 M3 S4" />
                    </layoutData>
                </Input>
                <Input value="{City}" />
                <Label text="Country" />
                <Select id="country" selectedKey="{Country}">
                    <items>
                        <core:Item text="England" key="England"/>
                        <core:Item text="Germany" key="Germany"/>
                        <core:Item text="USA" key="USA"/>
                    </items>
                </Select>
                <Toolbar ariaLabelledBy="Title3">
                    <Title id="Title3" text="Online" level="H5" titleStyle="H5"/>
                    <ToolbarSpacer />
                    <Button icon="sap-icon://settings"/>
                </Toolbar>
                <Label text="Web" />
                <Input value="{Url}" type="Url" />
                <Label text="Twitter" />
                <Input value="{Twitter}" />
            </f:content>
        </f:SimpleForm>
    </VBox>
</mvc:View>

//Page.controller.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
sap.ui.define([
        'jquery.sap.global',
        'sap/ui/core/mvc/Controller',
        'sap/ui/model/json/JSONModel',
        'sap/ui/model/odata/v4/ODataModel'
    ], function(jQuery, Controller, JSONModel, ODataModel) {
   "use strict";

    var PageController = Controller.extend("sap.ui.layout.sample.SimpleFormToolbar.Page", {

        onInit: function (oEvent) {
            console.log("hello");

            jQuery.get({
                url:"/SupplierService/SupplierService.svc/Suppliers(12345)",
                success: function(data) {
                    console.log("Recieved data:" + data);
                },
                error: function(error) {
                    // your error logic
                    console.log("Error while requesting odata:" + error);
                }
            });


        }

    });


    return PageController;

});

//index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="expires" content="0">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    Fullscreen –with toolbar

    <script id="sap-ui-bootstrap"
        src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js"
        data-sap-ui-theme="sap_belize"
        data-sap-ui-resourceroots='{
           "sap.ui.layout.sample.SimpleFormToolbar":"./",
           "sap.ui.demo.mock":"mockdata"
        }'
        data-sap-ui-compatVersion="edge"
        data-sap-ui-async="true"
        data-sap-ui-preload=""
        data-sap-ui-frameOptions="trusted"
        data-sap-ui-oninit="module:sap/ui/core/ComponentSupport">
   
</head>

<body class="sapUiBody" id="content">
    <div data-sap-ui-component
        data-name="sap.ui.layout.sample.SimpleFormToolbar"
        data-height="100%"
        data-id="container"
        data-settings='{"id" :"sap.ui.layout.sample.SimpleFormToolbar"}'
        style="height: 100%">
   
</body>
</html>

我添加了 jquery 调用只是为了查看 odata 是否正常工作。

用于 CORS 问题的命令:"C:\\\\\\\\Program Files (x86)\\\\\\\\Google\\\\\\\\Chrome\\\\\\\\Application\\\\\\\\chrome.exe" --disable-网络安全 --disable-gpu --user-data-dir=~/chromeTemp

我实际上指向的是同一个项目中的 odata 服务。同样部署在 Sap Cloud 上:https://supplierappp1014576trial.hanatrial.ondemand.com/SupplierApp/SupplierService.svc/

感谢您的宝贵时间。

  • 编辑:

在下面添加了解决方案作为答案。


  • 错误:

    "在读取之前不得更改属性" 被理解为 CORS 问题。
    在服务器端接受跨域请求可以通过配置 web.xml 来完成。请注意,这应该重新评估以供生产使用。

1
2
3
4
5
6
7
8
<filter>
          <filter-name>CorsFilter</filter-name>
          <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>CorsFilter</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>
  • 错误:

    "$batch failed - Error: Network error" 可以通过将 groupId 更改为 $direct 来解决。这意味着我们正在向 odata 服务发送单独的网络调用。

1
2
3
4
5
6
7
8
9
"models": {
           "": {
               "dataSource":"supplierOData",
               "settings" : {
                   "synchronizationMode" :"None",
                   "groupId":"$direct"
                }
            }
        },

这消除了这些错误,我看到数据被呈现到表单字段中。

感谢您的关注。