0
votes

I have a number of entity types that use the identical ResourceNames but are different in dataProperties fields and query where clause using 'ContentTypeId' (see code below).

In the last function listed (getCorrespondenceDocuments), if I use the entity type name 'Correspondence' in the from clause, Breeze ignores the defaultResourceName value provided and constructs the OData query using the entity type name as the resourcename string:

/_api/Correspondence?$filter=ContentTypeId%20eq%20'0x01...22'&$select=Id%2CTitle%2CContentTypeId%2CCreated%2CModified%2CCorrespondenceType%2CCorrespondenceDate%2CCorrespondenceAuthor%2CCorrespondenceRecipient%2CCorrespondenceTopic%2CConfidentialFlag%2CFile&

If I use the defaultResourceName in the from clause, Breeze will construct the OData request using the default document entity and the correct resourcename string but it does not include the correct dataProperties fields:

/_api/SP.AppContextSite(@target)/web/lists/getByTitle('Documents')/items?@target='http://my.spserver.com/dev/JDP'&$expand=File&$filter=ContentTypeId%20eq%20'0x01...22'&$select=Id%2CTitle%2CContentTypeId%2CCreated%2CModified%2CFile%2CConfidentialFlag&

I also tried using the .toType('Correspondence') method to the last test. No fields are returned at all:

/_api/SP.AppContextSite(@target)/web/lists/getByTitle('Documents')/items?@target='http://my.spserver.com/dev/JDP'&$expand=File&$filter=ContentTypeId%20eq%20'0x01...22'&


It appears that Breeze is assuming that your resource name will be different for each entity type.

How do I tell Breeze to use the correct entity data properties and resource name?


// Document type (default document type)
function addDocumentType() {
    addType({
          name: 'Document'
        , defaultResourceName: 'SP.AppContextSite(@target)/web/lists/getByTitle(\'Documents\')/items?@target=\'' + spContext.hostWeb.url + '\'&$expand=File'
        , dataProperties: {
              Id: { type: breeze.DataType.Int32 }
            , Title: { nullable: true }
            , ContentTypeId: {}
            , Created: { type: breeze.DataType.DateTime }
            , Modified: { type: breeze.DataType.DateTime }
            , File: { complexType: 'Document:#File' }
            , ConfidentialFlag: { type: breeze.DataType.boolean, nullable: true }
        }
    });
}

// Correspondence type
function addCorrespondenceType() {
    addType({
          name: 'Correspondence'
        , defaultResourceName: 'SP.AppContextSite(@target)/web/lists/getByTitle(\'Documents\')/items?@target=\'' + spContext.hostWeb.url + '\'&$expand=File'
        , dataProperties: {
              Id: { type: breeze.DataType.Int32 }
            , Title: { nullable: true }
            , ContentTypeId: {}
            , Created: { type: breeze.DataType.DateTime }
            , Modified: { type: breeze.DataType.DateTime }
            , CorrespondenceType: { nullable: true }
            , CorrespondenceDate: { type: breeze.DataType.DateTime, nullable: true }
            , CorrespondenceAuthor: { nullable: true }
            , CorrespondenceRecipient: { nullable: true }
            , CorrespondenceTopic: { nullable: true }
            , ConfidentialFlag: { type: breeze.DataType.boolean, nullable: true }
            , File: { complexType: 'Document:#File' }
        }
    });
}

function getDefaultDocuments(page) {
    return breeze.EntityQuery
    .from(documentType.defaultResourceName)
    .orderBy('Id')
    .skip(pageSize * (page - 1))
    .take(pageSize)
    .using(manager)
    .execute()
    .then(function (data) {
        return data.results;
    });
}

function getCorrespondenceDocuments() {
    return breeze.EntityQuery
    .from('Correspondence')
    //.from(correspondenceType.defaultResourceName)
    .where('ContentTypeId', 'eq', breeze.config.contentTypeIds.correspondence)
    .using(manager)
    .execute()
    .then(function (data) {
        return data.results;
    });
}
2

2 Answers

1
votes

Yes, Breeze generally assumes that a given endpoint returns the same type every time. I'm a little surprised that appending .toType to the query before executing it didn't work for you. Maybe I shouldn't be surprised; it has been a while since I was last in this part of the code base.

I think I'd begin diagnosing the situation by debugging through the JsonResultsAdapter.visitNode method, paying close attention to the updateEntityNode helper function. Somehow it is getting confused while determining the value of result.entityType, even when you append .toType.

If you have to fix the type determination here in JsonResultsAdapter.visitNode, you should be looking for a way to disambiguate based on node and context. One obvious (perhaps hacky) way is to look for the existence of anode.CorrespondenceType` property.

You might do that after you're sure that the query targeted this ambiguous endpoint. The mappingContext parameter to the visitNode method can tell you which endpoint you queried; see mappingContext.query.resourceName.

You have complete access to the query here so maybe there's another "telltale" that can help. For example, when you add the .toType('foo') clause to the query before executing it, the mappingContext.query.resultEntityType is the name of the type you specified (e.g., 'foo'). That's a darn good clue, don't you think?

0
votes

You can use the MetadataStore.setEntityTypeForResourceName method:

http://www.breezejs.com/sites/all/apidocs/classes/MetadataStore.html#method_setEntityTypeForResourceName

Also see the "EntityType/ResourceName map" section under http://www.breezejs.com/documentation/querying-locally