从 SAPUI5 使用 OData V4

Consuming OData V4 from SAPUI5

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

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

我在此应用程序中所做的更改:
1. manifest.json 和
2. Page.view.xml 用于表单控件的Context Binding
3. 删除了控制器中对 mockdata 的代码引用和 index.html

但是,我无法获取数据并出现以下错误:

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 中实现任何批处理。

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

{
    "_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

<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

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

<!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">
    <title>Fullscreen – with toolbar</title>

    <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">
    </script>
</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%">
    </div>
</body>
</html>

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

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

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

谢谢你的时间。

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

  • 错误:

    “在阅读之前不得更改 属性”被理解为 CORS 问题。 可以通过配置 web.xml 来在服务器端接受跨源请求。请注意,这应该是 re-evaluated 用于生产。

<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 失败 - 错误:网络错误”通过将 groupId 更改为 $direct 来解决。这意味着我们正在向 odata 服务发送单独的网络调用。


"models": {
            "": {
                "dataSource": "supplierOData",
                "settings" : {
                    "synchronizationMode" : "None",
                    "groupId": "$direct"
                }
            }
        },

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

感谢您的关注。