Breeze.JS for SharePoint 2013错误保存更改

时间:2014-07-16 13:42:46

标签: breeze sharepoint-2013

对象extraMetadata未定义,并在breeze.labs.dataservice.sharepoint.js

的第247行引发错误
rawEntity.__metadata = { 'type': aspect.extraMetadata.type };

我怀疑是因为我没有在我的实体定义中定义__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"]
            }
        }
    };

更新日期:2013年11月11日

如果我运行以下查询:

    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对象,而不是Breeze Entities,缺少__metadata属性。我试图弄清楚为什么会这样。

更新:2014年11月12日

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

5 个答案:

答案 0 :(得分:3)

  

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

要明确的是,您所引用的代码位于我所拥有的 breeze.labs.dataservice.sharepoint.js 文件的第147行(而不是247) 。

它位于{{1>} 准备保存修改后的实体。我假设您已查询_createChangeRequest实体,对其进行了更改,并在发生错误时将其保存。

我认为问题不会追溯到您为Product类型定义元数据的方式。

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

  

__metadata不会针对投影返回的结果进行定义,但是您的问题涉及已修改的实体,所以我假设您通过普通查询获取了此实体。一个没有__metadata条款的人。

我想知道您是否在检索到您正在修改的实体的查询的JSON有效内容中看到select属性。请检查查询请求中的网络流量。如果您没有在那里看到它,我们必须找出服务器没有发送它的原因。

背景

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

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

这似乎受到了折磨吗? 折磨。 OData需要与实体(特别是etag)一起携带的额外信息,否则服务器不会更新或删除实体。我们必须将这些信息从头发中松散,然后在我们向服务器发出保存请求时将其恢复。我们把它放在entityAspect.extraMetadata上,以保持该属性作为“实体”的守护者的角色,该角色与您的对象的业务目的无关以及与其如何关联坚持不懈。

为什么。错误在哪里?

错误

底层错误是来自SharePoint OData源的entityAspect消失了。我们还不知道它是如何消失的。但如果没有它,我们就会遇到大麻烦。

当缺少__metadata时,sharepoint适配器应该提供更好的消息。我们实际上在几行之后寻找那个问题;见extraMetadata

adjustUpdateDeleteRequest

该测试显得为时已晚。我会做一个注释来推动测试。

但是这样的修复只会导致保存因更好的消息而失败。它不会告诉你如何解决它。

让我们努力找到var extraMetadata = aspect.extraMetadata; if (!extraMetadata) { throw new Error("Missing the extra metadata for an update/delete entity"); } 消失的地方......首先是它是否已经到达。

我在等你的报告。

2014年7月17日更新

我还在等待您是否在原始实体查询的响应中看到__metadata属性。

与此同时,我检查了OData规范(复数)以获取对__metadata属性的引用。似乎__metadata属性始终是可选的。因此,OData提供商不需要发送或尊重etag ......我们知道这是可能的,因为Web API 2 OData不支持etags ......一个很快就会被纠正的缺陷。

  

See the OData v.2 spec where it describes JSON format。搜索术语“__metadata”。

     

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

     

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

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

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

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

答案 1 :(得分:3)

暂时还没有发帖,但我将分享我发现的问题以及我是如何为我解决的(因为我花了很长时间)。

基本上breeze.labs.dataservice.sharepoint适配器有一个函数serverTypeNameToClientDefault(),它需要__metadata"类型"中REST/OData返回的SharePoint自定义列表类型。字段为完全格式:

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

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

对于我的解决方案,因为在我的情况下,我并不关心我的自定义列表的URL是什么,我只是确保当我的自定义列表由SharePoint配置时,它导致了一个名称根据微风所期待的。您可以通过设置Url元素的ListInstance属性来完成此操作:

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

更好的解决方案是使serverTypeNameToClientDefault()函数更强大或在本地修复它的需求,但希望这可以在适配器的未来版本中解决。

请注意,我已使用以下配置(未列出所有依赖项)测试此解决方案: Breeze.Client 1.4.9 with Breeze.DataService.SharePoint 0.2.3
Breeze.Client 1.5.0与Breeze.DataService.SharePoint 0.3.2

另请注意,如上所述,0.3.2版本的适配器现在会显示更好的错误消息 - &#34; 缺少更新/删除实体的额外元数据& #34 ;;但它并没有解决问题。

希望这有助于某人。

答案 2 :(得分:2)

对于breeze v1.4.14和breeze labs sharepoint 2013 v0.2.3我在文件 breeze.labs.dataservice.sharepoint.js 中使用小修补程序。 在功能结束时

function visitNode(node, mappingContext, nodeContext)

之前

return result;

我只是像这样设置属性extraMetadata:

result.extraMetadata = node.__metadata;

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

答案 3 :(得分:2)

对于这个姗姗来迟的方面,我们很抱歉,但是今天解决了额外“s”的错误......最后。您可以在此处跟踪问题:https://github.com/andrewconnell/breeze.js.labs/issues/6

这一切都源于我做出的一个非常不正确的假设。它已在SharePoint数据服务适配器的0.6.2版中得到修复。请注意,在元数据存储中创建实体时,必须使用与实体相同的名称作为数据来源的列表。

答案 4 :(得分:0)

我通过修改navigationProperties

的第319行,在实体上解决了多个breeze.labs.dataservice.sharepoint.js v.0.10.0的问题

我改变了:

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

为:

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

_mappedPropertiesCount似乎也包含navigationProperties计数。例如dataProperties.length + navigationProperties.length

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

因此,它没有被视为一个实体,它的元数据没有被设置,并且它最终没有被添加到缓存中。

由于navigationProperty,__元数据和ID中有两个额外项目,因此只使用了一个Object.keys(node)。所以它仍会通过一个navigationProperty而不是两个或更多的测试通过测试。