对象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.visitNode
和updateEntityNode
方法。您将看到适配器如何使用__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
的测试,但不是两个或更多。