When Breeze matches JSON property data for entities, it ignores properties that it does not recognize . That is why the subtracted server class property data is discarded, even if you see it in JSON on the wire.
Fortunately, you can teach Breeze to recognize a property by registering it as an unmapped property . I will show you how to do it. Let me tell you about myself first.
Background
Your calculated property would be “known” to the Breeze client if it were calculated by the database. Database properties (regular and calculated) are collected in metadata as display properties.
But in your case (if I understand correctly) the property is defined in the logic of the server class, and not in the database. Therefore, it does not apply to display properties in metadata. It is hidden from metadata. This is an unmapped instance property.
I assume that you are not hiding it from the serializer. If you look at the network traffic for a class request, you can see the property data you received that arrives at the client. The problem is that Breeze ignores him when he “materializes” entities from these query results.
Solution with an example
The solution is to register the computed property with the MetadataStore .
I changed the entityExtensionTests.js object of the DocCode sample to include this script; You can get this code from GitHub or wait for the next release of Breeze.
Or simply follow the code below, starting with this snippet from the Employee class in NorthwindModel.cs:
// Unmapped, server-side calculated property
[NotMapped] // Hidden from Entity Framework; still serialized to the client
public string FullName {
get {return LastName +
(String.IsNullOrWhiteSpace (FirstName)? "": ("," + FirstName)); }
}
And here is an automatic test in entityExtensionTests.js
test ("unmapped property can be set by a calculated property of the server class", 2,
function () {
var store = cloneModuleMetadataStore (); // clones the Northwind MetadataStore
// custom Employee constructor
var employeeCtor = function () {
// 'Fullname' is a server-side calculated property of the Employee class
// This unmapped property will be empty for new entities
// but will be set for existing entities during query materialization
this.FullName = "";
};
// register the custom constructor
store.registerEntityTypeCtor ("Employee", employeeCtor);
var fullProp = store.getEntityType ('Employee'). getProperty ('FullName');
ok (fullProp && fullProp.isUnmapped,
"'FullName' should be an unmapped property after registration");
var em = newEm (store); // helper creates a manager using this MetadataStore
var query = EntityQuery.from ('Employees'). using (em);
stop (); // going async
query.execute (). then (success) .fail (handleFail) .fin (start);
function success (data) {
var first = data.results [0];
var full = first.FullName ();
// passing test confirms that the FulllName property has a value
ok (full, "queried 'Employee' should have a fullname ('Last, First'); it is" + full);
}
});
What you need to do is a small part of the test case:
var yourTypeCtor = function () {
this.calculatedProperty = ""; // "" or instance of whatever type is is supposed to be
};
// register your custom constructor
store.registerEntityTypeCtor ("YourType", yourTypeCtor);