このようなシナリオを機能させたい場合は、やるべきことが少しあります。Upshotは、監視可能なアイテムの親エンティティのみをオンにします。したがって、クラスAのjavascript表現のみがノックアウトで観察可能であり、クラスBのjavascript表現はそうではありません。したがって、Upshotは関連するオブジェクトの変更を認識しません。
解決策は、エンティティを手動でマップすることです。私の生活を楽にするために、以下のコードスニペットで「DeliveryTracker」サンプルアプリケーションのコードを使用しました。私のブログ記事では、手動マッピングの例を見ることができます:http: //bartjolling.blogspot.com/2012/04/building-single-page-apps-with-aspnet.htmlしたがって、以下の私の例は、配信に取り組んでいます。 'および'customer'オブジェクト。
サーバー側ドメインモデル
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] //needed to break cyclic reference
public virtual Customer Customer { get; set; }
public virtual int CustomerId { get; set; }
}
public class AppDbContext : DbContext
{
public DbSet<Customer> Customers { get; set; }
public DbSet<Delivery> Deliveries { get; set; }
}
}
データサービスコントローラー
データサービスコントローラーは、「http:// localhost:[yourport] / api / dataservice/GetCustomers」でOData標準に準拠したデータを公開します。顧客と配達の両方を更新できるようにするには、UpdateCustomerとUpdateDelivery関数を定義する必要があります
namespace StackOverflow.q9888839.UploadRelatedEntities.Controllers
{
public class DataServiceController : DbDataController<AppDbContext>
{
//Service interface for Customer
public IQueryable<Customer> GetCustomers()
{
return DbContext.Customers.Include("Deliveries").OrderBy(x => x.CustomerId);
}
public void InsertCustomer(Customer customer) { InsertEntity(customer); }
public void UpdateCustomer(Customer customer) { UpdateEntity(customer); }
public void DeleteCustomer(Customer customer) { DeleteEntity(customer); }
//Service interface for Deliveries
public void InsertDelivery(Delivery delivery) { InsertEntity(delivery); }
public void UpdateDelivery(Delivery delivery) { UpdateEntity(delivery); }
public void DeleteDelivery(Delivery delivery) { DeleteEntity(delivery); }
}
}
クライアント側のドメインモデル
クライアント側モデルを含む新しいJavaScriptファイルを追加します。ここでは、すべてのプロパティをノックアウトオブザーバブルに明示的に変換しています。問題を解決するための鍵は、Customerオブジェクトのコンストラクター内の行で、着信配信を監視可能な配列にマッピングしています。
/// <reference path="_references.js" />
(function (window, undefined) {
var deliveryTracker = window["deliveryTracker"] = {}; //clear namespace
deliveryTracker.DeliveriesViewModel = function () {
// Private
var self = this;
self.dataSource = upshot.dataSources.Customers;
self.dataSource.refresh();
self.customers = self.dataSource.getEntities();
};
deliveryTracker.Customer = function (data) {
var self = this;
self.CustomerId = ko.observable(data.CustomerId);
self.Name = ko.observable(data.Name);
self.Address = ko.observable(data.Address);
self.Latitude = ko.observable(data.Latitude);
self.Longitude = ko.observable(data.Longitude);
self.Deliveries = ko.observableArray(ko.utils.arrayMap(data.Deliveries, function (item) {
return new deliveryTracker.Delivery(item);
}));
upshot.addEntityProperties(self, "Customer:#StackOverflow.q9888839.UploadRelatedEntities.Models");
};
deliveryTracker.Delivery = function (data) {
var self = this;
self.DeliveryId = ko.observable(data.DeliveryId);
self.CustomerId = ko.observable(data.CustomerId);
self.Customer = ko.observable(data.Customer ? new deliveryTracker.Customer(data.Customer) : null);
self.Description = ko.observable(data.Description);
self.IsDelivered = ko.observable(data.IsDelivered);
upshot.addEntityProperties(self, "Delivery:#StackOverflow.q9888839.UploadRelatedEntities.Models");
};
//Expose deliveryTracker to global
window["deliveryTracker"] = deliveryTracker;
})(window);
景色
index.cshtmlで、Upshotを初期化し、カスタムクライアントマッピングを指定して、ビューモデルをバインドします
@(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>
結果
インデックスページに移動すると、顧客と関連する配信のリストが非同期で読み込まれます。すべての配信は顧客ごとにグループ化され、配信の「IsDelivered」プロパティにバインドされているチェックボックスが事前に固定されています。顧客の名前もINPUT要素にバインドされているため、編集可能です。
スクリーンショットを投稿するのに十分な評判がないので、スクリーンショットなしでやらなければなりません
IsDeliveredチェックボックスをオンまたはオフにすると、Upshotは変更を検出し、DataServiceコントローラーに送信します。
[{"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
}
}]
顧客の名前を変更する場合、入力ボックスがフォーカスを失ったときにUpshotが変更を送信します
[{
"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"
}
}]
したがって、上記の手順に従うと、Upshotは親エンティティと子エンティティの両方を更新します。