Breeze.JS for SharePoint 2013 error saving changes

。_饼干妹妹 提交于 2020-01-16 18:48:29

问题


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.


回答1:


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.




回答2:


There hasn't been a post in a while but I am going to share what I found as the problem and how I resolved it for me (because it took me a long time).

Basically the breeze.labs.dataservice.sharepoint adapter has a function serverTypeNameToClientDefault() that expects the SharePoint custom list type as returned by REST/OData in the __metadata "type" field to be in the exact format of:

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

This function does a string regex to extract the Breeze entity name from the SharePoint type and uses that name to look up the entity in the metadata store ("Customer" in the above example). If there is no match, Breeze will not find your entity and will return a basic object instead of a Breeze entity. Therefore your REST JSON result returned from SharePoint, even though it does have the __metadata property is not converted into a Breeze entity that contains the property entityAspect.extraMetadata, among other things. This is what leads to the error "Unable to get property 'type' of undefined or null reference"

For my solution, since in my case I don't care as much what the URL of my custom lists are, I just made sure that when my custom list was provisioned by SharePoint that it resulted in a name according to what Breeze expects. You accomplish this by setting the Url attribute of the ListInstance element like this:

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

The better solution would be to make the serverTypeNameToClientDefault() function more robust or fix it to my needs locally but hopefully this can be addressed in a future version of the adapter.

Note that I have tested this solution with the following configurations (not all dependencies listed): Breeze.Client 1.4.9 with Breeze.DataService.SharePoint 0.2.3
Breeze.Client 1.5.0 with Breeze.DataService.SharePoint 0.3.2

Also note that the 0.3.2 version of the adapter now displays a better error message when this happens as mentioned above -- "Missing the extra metadata for an update/delete entity"; but it doesn't fix the problem.

Hope this helps someone.




回答3:


For breeze v1.4.14 and breeze labs sharepoint 2013 v0.2.3 i am using small fix in file breeze.labs.dataservice.sharepoint.js. At the end of function

function visitNode(node, mappingContext, nodeContext)

just before

return result;

i just set property extraMetadata like this:

result.extraMetadata = node.__metadata;

This seems to fix problem when i try to save modified entity back to sharepoint.




回答4:


Sorry folks for the long overdue aspect of this, but I got the bug with the extra "s" resolved today... FINALLY. You can track the issue here: https://github.com/andrewconnell/breeze.js.labs/issues/6

This all stemmed from a very incorrect assumption I made. It's been fixed in version 0.6.2 of the data service adapter for SharePoint. Note that you MUST use the same name for your entity when creating it in the metadata store as the list where the data is coming from.




回答5:


I resolved my issue with multiple navigationProperties on an entity by editing line 319 of breeze.labs.dataservice.sharepoint.js v.0.10.0

I changed:

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

to:

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

It looks like the _mappedPropertiesCount includes the navigationProperties count too. e.g. dataProperties.length + navigationProperties.length

The query node was then thought to not contain a full set of properties for the entity (it was assumed to be the result of a partial projection).

It therefore wasn't being treated as an entity, its metadata wasn't being set, and it ultimately wasn't being added to the cache.

It worked with only one navigationProperty as there were two extra items in Object.keys(node), __Metadata and ID. So it would still pass the test with one navigationProperty, but not two or more.



来源:https://stackoverflow.com/questions/24782426/breeze-js-for-sharepoint-2013-error-saving-changes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!