用于SharePoint 2013错误保存更改



对象extraMetadata未定义,并在breeze.labs.dataservice.sharepoint.js的第247行抛出错误

rawEntity.__metadata = { 'type': aspect.extraMetadata.type };

我怀疑这是因为我没有在我的实体定义上为breeze定义__metadata对象中发现的类型。任何关于如何正确定义我的类型的建议将是非常欢迎的!下面是其中一个对象的类型定义。

   models.Project = {
        name: 'Project',
        defaultResourceName: 'getbytitle('Projects')/items',
        dataProperties: {
            ID: {
                type: breeze.DataType.Int32
            },
            Title: {
                nullable: false
            },
            StatusId: {
                type: breeze.DataType.Int32,
                nullable: false
            },
            SelectedApproverId: {
                type: breeze.DataType.Int32,
                nullable: false
            },
            Created: {
                type: breeze.DataType.DateTime
            },
            Modified: {
                type: breeze.DataType.DateTime
            }
        },
        navigationProperties: {
            Status: {
                type: "Status",
                foreignKeyNames: ['StatusId'],
                hasMany: false
            },
            SelectedApprover: {
               type: "User",
               foreignKeyNames: ["SelectedApproverId"]
            }
        }
    };

UPDATE: 11/11/2013

如果我运行以下查询:

    return breeze.EntityQuery
           .from(metadataStore.getEntityType('Project').defaultResourceName)
           .orderBy('Created desc')
           .using(manager)
           .execute()
           .then(function (data) {
                console.log(data.results);
                return data.results;
           });

的结果是一个数组的简单JavaScript对象,而不是微风实体,缺乏__metadata属性。我想弄清楚为什么会这样。

更新日期:11/12/2014

我已经确认,当我在navigationProperties下定义多个实体时,这个问题就会出现。

请确保您使用的是BreezeJS v.1.4.12或更高版本。

要清楚,你所提到的代码是在第147行(不是247)的breeze.labs. datasservice .sharepoint.js文件在我拥有。

它位于_createChangeRequest中,其中准备保存修改的实体。我将假设您已经查询了Product实体,对其进行了更改,并在错误发生时将其保存回来。

我不相信这个问题会被追踪到你如何为你的Product类型定义元数据。

你不应该为类型定义__metadata属性。__metadata属性是我们期望SharePoint(实际上是任何OData数据源)在您查询OData数据源时将其添加到发送给客户端的JSON实体数据中。

__metadata不会为投影返回的结果定义,但您的问题涉及修改的实体,所以我假设您通过正常查询获得了此实体…一个没有select条款的文件

我想知道您是否在检索您正在修改的实体的查询的JSON有效载荷中看到__metadata属性。请检查来自查询请求的网络流量。如果你没有看到它,我们必须找出为什么服务器没有发送它。

的背景

JSON节点上的__metadata属性是与SharePoint OData服务器签订合同的关键部分。这就是Breeze客户端了解实体类型及其etag的方式。

查看jsonResultsAdapter.visitNodeupdateEntityNode方法。您将看到适配器如何使用__metadata来确定该数据的EntityType。您还将看到适配器将__metadata移动到适配器结果的extraMetadata属性。BreezeJS随后移动"额外的元数据"。从结果对象到实体的entityAspect.extraMetadata属性。

这看起来很折磨人吗?它折磨。OData要求实体(特别是etag)携带额外的信息,没有这些信息,服务器将无法更新或删除实体。我们必须将这些信息保存在某个地方,不让你担心,然后在我们向服务器发出保存请求时将其带回来。我们把它放在entityAspect上,以保持该属性作为"实体"的守护者的角色。这与对象的业务目的无关,而与如何持久化有关。

为什么就说这么多了。虫子在哪里?

错误

潜在的bug是来自SharePoint OData数据源的__metadata已经消失了。我们还不知道它是怎么消失的。但是没有它我们就有大麻烦了。

当缺少extraMetadata时,sharepoint适配器应该给出更好的消息。我们会在后面几行找到这个问题;参见adjustUpdateDeleteRequest:

var extraMetadata = aspect.extraMetadata;
if (!extraMetadata) {
    throw new Error("Missing the extra metadata for an update/delete entity");
}

这个测试出现得太晚了。我要做个笔记把测试提前。

但是这样的修复只会导致保存失败,并带有更好的消息。它不会告诉你如何修理它。

所以让我们努力寻找__metadata消失的地方…从它是否出现开始。

我等你的报告。

2014年7月17日更新

我仍在等待听到您是否在响应原始实体查询的有效载荷中看到__metadata属性。

同时,我检查了OData规范(复数)对__metadata属性的引用。看起来__metadata属性一直是可选的。因此,OData提供者不需要发送或尊重etag…我们知道这是可能的,因为Web API 2.0 data不支持标签……一个很快就会被纠正的缺陷。

请参阅OData v.2规范,其中描述了JSON格式。搜索术语"__metadata"。

OData v.3规范还在JSON响应(至少是JSON详细响应)中调用__metadata属性。

但是…沉重的叹息……似乎__metadata属性从v.4规范中消失了,元数据信息完全通过JSON注释提供。DataJS库(由许多但不是所有的BreezeJS OData适配器使用)可能会将这些注释映射到节点的__metadata属性,但我还不能确认。我们有一些工作要做,以应对所有这些变化。

同时,我认为所有BreezeJS OData数据服务适配器应该对额外的元数据采取更防御性的立场,应该简单地忽略遗漏,而不是抛出异常

我们很快就会做出这些防御的改变。

当然,如果OData服务实际上需要etag或其他元数据,服务器将拒绝您的更新或删除请求。我还不知道该怎么做

有一段时间没有帖子了,但我要分享我发现的问题以及我如何为我解决它(因为它花了我很长时间)。

基本上breeze.labs.dataservice.sharepoint适配器有一个函数serverTypeNameToClientDefault(),它期望由REST/OData在__metadata "type"字段中返回的SharePoint自定义列表类型以精确的格式:

SP.Data.**mylistname**sListItem**  (notice the "sListItem" suffix; ;  Ex. SP.Data.CustomersListItem)

这个函数执行一个字符串正则表达式,从SharePoint类型中提取Breeze实体名称,并使用该名称在元数据存储中查找实体(在上面的示例中为"Customer")。如果没有匹配,Breeze将不会找到您的实体,并将返回一个基本对象而不是一个Breeze实体。因此,你的REST JSON结果从SharePoint返回,即使它确实有__metadata属性,也不会转换成包含属性entityAspect.extraMetadata的Breeze实体。这就是导致错误的原因"无法获得未定义或null引用的属性'type' ""

对于我的解决方案,因为在我的情况下,我不关心我的自定义列表的URL是什么,我只是确保当我的自定义列表由SharePoint提供时,它会根据Breeze的期望产生一个名称。可以这样设置ListInstance元素的Url属性:

<ListInstance 
      Title="My Customers" 
      OnQuickLaunch="TRUE" 
      TemplateType="10000" 
      Url="Lists/Customers"    <!-- List/Customer will not work -->
      Description="My List Instance">
      ...

更好的解决方案是使serverTypeNameToClientDefault()功能更健壮,或者根据我的本地需求修复它,但希望这可以在适配器的未来版本中解决。

请注意,我已经用以下配置测试了这个解决方案(没有列出所有依赖项):微风。Client 1.4.9 with Breeze.DataService.SharePoint 0.2.3
微风。Client 1.5.0 with Breeze.DataService.SharePoint 0.3.2

还请注意,0.3.2版本的适配器现在显示一个更好的错误消息,当这种情况发生时,如上所述——"缺少更新/删除实体的额外元数据";但这并不能解决问题。

希望这能帮助到别人。

对于breeze v1.4.14和breeze labs sharepoint 2013 v0.2.3,我正在使用文件breeze.labs. datasservice .sharepoint.js中的小修复。在函数的末尾

function visitNode(node, mappingContext, nodeContext)

前面
return result;

我只是像这样设置属性:

result.extraMetadata = node.__metadata;

这似乎解决了问题,当我试图保存修改的实体回sharepoint。

很抱歉,今天我解决了额外的"s"的问题。最后。您可以在这里跟踪问题:https://github.com/andrewconnell/breeze.js.labs/issues/6

这一切都源于我做的一个非常错误的假设。在SharePoint的0.6.2版数据服务适配器中已经修复了这个问题。注意,在元数据存储中创建实体时,必须使用与数据来源列表相同的名称。

我通过编辑breeze.labs.dataservice.sharepoint.js v.0.10.0的第319行解决了实体上多个navigationProperties的问题

我改变了

:

if (entityType._mappedPropertiesCount <= Object.keys(node).length - 1)

:

if (entityType.dataProperties.length <= Object.keys(node).length - 1)

看起来_mappedPropertiesCount也包括navigationProperties计数。例:dataProperties.length + navigationProperties.length

然后认为查询节点不包含实体的完整属性集(假定它是部分投影的结果)。

因此,它没有被当作一个实体来对待,它的元数据没有被设置,最终也没有被添加到缓存中。

它只与一个navigationProperty工作,因为在Object.keys(node)中有两个额外的项目,__Metadata和ID。所以它仍然会通过一个navigationProperty的测试,但不是两个或更多。

最新更新