Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
848 views
in Technique[技术] by (71.8m points)

Breeze.JS for SharePoint 2013 error saving changes

The object extraMetadata is undefined and throwing an error on line 247 of breeze.labs.dataservice.sharepoint.js

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

I suspect it is because I have not defined the type found in __metadata object on my entity definitions for breeze. Any suggestions on how to define my type correctly would be very welcome! Here is my type definition for one of the objects.

   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

If I run the following query:

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

the results are an array of simple JavaScript objects, not Breeze Entities, that lack an __metadata properties. I'm trying to figure out why this is the case.

Update: 11/12/2014

I have confirmed that this issue presents itself when I have multiple entities defined under navigationProperties.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Please be sure you are using BreezeJS v.1.4.12 or later.

To be clear, the code to which you refer is on line 147 (not 247) of the breeze.labs.dataservice.sharepoint.js file in my possession.

It's located within the _createChangeRequest where it is preparing to save a modified entity. I'll assume that you have queried a Product entity, made changes to it, and are saving it back when the error occurs.

I don't believe the problem will be traced to how you defined the metadata for your Product type.

You should NOT define a __metadata property for your type. The __metadata property is something we expect SharePoint (any OData source in fact) to add to the JSON entity data that it sends to the client when you query that OData source for entities.

__metadata wouldn't be defined for results returned by a projection but then your issue concerns a modified entity so I'm assuming that you acquired this entity through a normal query ... one that did not have a select clause.

I'd like to know if you see the __metadata property in the JSON payload of a query that retrieved the entity you were modifying. Please examine the network traffic from the query request. If you don't see it there, we have to find out why the server didn't send it.

Background

The __metadata property on the JSON node is a crucial part of the contract with the SharePoint OData server. That's how the Breeze client learns about the entity's type and its etag.

Look at the jsonResultsAdapter.visitNode and updateEntityNode methods. You'll see how the adapter uses __metadata to determine the EntityType for that data. You'll also see that the adapter moves the __metadata to the adapter result's extraMetadata property. BreezeJS subsequently moves that "extra metadata" from this result object to the entity's entityAspect.extraMetadata property.

Does this seem tortured? It is tortured. OData requires extra information to be carried around with the entity (specifically the etag) without which the server simply will not update or delete the entity. We have to squirrel that info away somewhere, out of your hair, and then bring it back when we make save requests to the server. We put it on the entityAspect in keeping with that property's role as the keeper of the "entity-ness" that has nothing to do with your object's business purpose and everything to do with how it is persisted.

So much for the why. Where is the bug?

The bug

The underlying bug is that this __metadata from the SharePoint OData source has disappeared. We don't know how it disappeared yet. But we're in big trouble without it.

The sharepoint adapter should give a better message when extraMetadata is missing. We actually look for that problem a few lines later; see adjustUpdateDeleteRequest:

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

That test appears too late. I'll make a note to move the test up.

But such a fix will only cause the save to fail with a better message. It won't tell you how to fix it.

So let's work on finding where the __metadata disappeared ... starting with whether it ever arrived in the first place.

I await your report.

Update 17 July 2014

I'm still waiting to hear if you are seeing the __metadata property in the payload of the response to the original entity query.

Meanwhile, I checked the OData specs (plural) for references to the __metadata property. It appears that the __metadata property has always been optional. It follows that an OData provider need not send or honor the etag ... and we know that this is possible because Web API 2 OData didn't support etags ... a defect soon to be corrected.

See the OData v.2 spec where it describes JSON format. Search for the term "__metadata".

The OData v.3 spec also calls for the __metadata property in a JSON response (at least a JSON verbose response).

But ... heavy sigh ... it appears that the __metadata property is gone from the v.4 spec and that the metadata information is supplied entirely through JSON annotations. The DataJS library (used by many but not all BreezeJS OData adapters) may map those annotations into the node's __metadata property but I can't confirm it yet. We have some work to do coping with all of these variations.

In the meanwhile, I think all BreezeJS OData dataservice adapters should take a more defensive position regarding extra metadata and should simply ignore the omission rather than throw exceptions.

We'll make these defensive changes very soon.

Of course the server will reject your update or delete request if the OData service actually requires an etag or other metadata. I don't know what we can do about that just yet.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...