There is little work if you want this scenario to work. The result only rotates the parent objects into observable elements. Thus, only the javascript view of class A is an observable knockout, the javascript view of class B is not. Therefore, Upshot is not aware of any changes to related objects.
The solution is to display objects manually. To make my life easier, I used the code from my sample DeliveryTracker application in the code snippets below. In my blog article, you can see an example of manual matching: http://bartjolling.blogspot.com/2012/04/building-single-page-apps-with-aspnet.html , so my examples below work on βdeliveryβ and "customer" objects.
Server Side Domain Model
namespace StackOverflow.q9888839.UploadRelatedEntities.Models { public class Customer { [Key] public int CustomerId { get; set; } public string Name { get; set; } public string Address { get; set; } public double Latitude { get; set; } public double Longitude { get; set; } public virtual ICollection<Delivery> Deliveries { get; set; } } public class Delivery { [Key] public int DeliveryId { get; set; } public string Description { get; set; } public bool IsDelivered { get; set; } [IgnoreDataMember]
Data service controller
The data service controller provides data that conforms to OData standards to "HTTP: // local: [yourport] / api / DataService / GetCustomers". To be able to update both customers and deliveries, you need to define the UpdateCustomer AND UpdateDelivery function
namespace StackOverflow.q9888839.UploadRelatedEntities.Controllers { public class DataServiceController : DbDataController<AppDbContext> {
Client Side Model
Add a new javascript file containing your client model. Here, I explicitly turn each property into an observable knockout. The key to solving your problem is the line inside the constructor of the Customer object, where I map the incoming deliveries to the observed array
View
In index.cshtml, you initialize Upshot, set up custom client mapping, and bind viewmodel
@(Html.UpshotContext(bufferChanges: false) .DataSource<StackOverflow.q9888839.UploadRelatedEntities.Controllers.DataServiceController>(x => x.GetCustomers()) .ClientMapping<StackOverflow.q9888839.UploadRelatedEntities.Models.Customer>("deliveryTracker.Customer") .ClientMapping<StackOverflow.q9888839.UploadRelatedEntities.Models.Delivery>("deliveryTracker.Delivery") ) <script type="text/javascript"> $(function () { var model = new deliveryTracker.DeliveriesViewModel(); ko.applyBindings(model); }); </script> <section> <h3>Customers</h3> <ol data-bind="foreach: customers"> <input data-bind="value: Name" /> <ol data-bind="foreach: Deliveries"> <li> <input type="checkbox" data-bind="checked: IsDelivered" > <span data-bind="text: Description" /> </input> </li> </ol> </ol> </section>
results
When you go to the index page, the list of customers and related deliveries will be loaded asynchronously. All deliveries are grouped by customer and pre-installed using the flag associated with the IsDelivered delivery property. The client name is also being edited because it is associated with the INPUT element
I don't have enough reputation to post a screenshot, so you have to do without it
When you check or uncheck IsDelivered Upshot will detect the change and send it to the DataService controller
[{"Id":"0", "Operation":2, "Entity":{ "__type":"Delivery:#StackOverflow.q9888839.UploadRelatedEntities.Models", "CustomerId":1, "DeliveryId":1, "Description":"NanoCircuit Analyzer", "IsDelivered":true }, "OriginalEntity":{ "__type":"Delivery:#StackOverflow.q9888839.UploadRelatedEntities.Models", "CustomerId":1, "DeliveryId":1, "Description":"NanoCircuit Analyzer", "IsDelivered":false } }]
When changing the client name, Upshot will send the changes when the input field loses focus
[{ "Id": "0", "Operation": 2, "Entity": { "__type": "Customer:#StackOverflow.q9888839.UploadRelatedEntities.Models", "Address": "Address 2", "CustomerId": 2, "Latitude": 51.229248, "Longitude": 4.404831, "Name": "Richie Rich" }, "OriginalEntity": { "__type": "Customer:#StackOverflow.q9888839.UploadRelatedEntities.Models", "Address": "Address 2", "CustomerId": 2, "Latitude": 51.229248, "Longitude": 4.404831, "Name": "Rich Feynmann" } }]
So, if you follow the above procedure, Upshot will update the parent and child objects for you.