如何上传通过MVC4结果相关的实体 [英] How to upload related entities via MVC4 upshot

查看:150
本文介绍了如何上传通过MVC4结果相关的实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我得到一个简单的DTO实体A装入我的结果视图模型是通过Knockoutjs愉快地观看。

I get a simple DTO entity A loaded into my upshot viewmodel which is happily viewable via Knockoutjs.

我的DTO A包含一个列表的实体。所以,我可以通过内部的元素的foreach。

My DTO A contains a List entities. So I can foreach over the elements inside A.

又说:

class A
    {
       someprop;
        List<B> childB;
    }
Class B
{
   somepropB;
}

到目前为止好。我可以遍历数据没有问题。
但是,如果我改变somepropA的一个实例内部和白水回收服务器将不会作出响应。
的updateData controlle方法,甚至没有被调用。
如果我将其发送给客户端之前清除childB.Clear(),一切都很好。

So far so good. I can iterated over the data with no problem. But if I change "someprop" inside an instance of A and SaveAll the server will not respond at all. The updateData controlle method is not even invoked. If I clear the childB.Clear() before transmitting it to the client, all is fine.

看来结果是无法与集合更新实体?

It seems the upshot is not able to update entities with collections?

推荐答案

有一个工作位,如果你想这样的情况下工作要做。结果只能轮流在可观测项目父实体。因此,只有JavaScript的重新$ A级的对$ psentation是观察到淘汰赛,B类的JavaScript的重新presentation不是。因此,结果是不知道的相关对象的任何更改。

There is a bit of work to do if you want such a scenario to work. Upshot only turns the parent entities in observable items. So only the javascript representation of class A is a knockout observable, the javascript representation of class B is not. Therefore Upshot is not aware of any changes in associated objects.

的解决方案是将实体手动映射。为了使我的生活更轻松,我从下面的code段我的'DeliveryTracker示例应用程序中使用code。在我的博客文章中,你可以看到手动映射的一个例子:的http://bartjolling.blogspot.com/2012/04/building-single-page-apps-with-aspnet.html所以我的例子如下工作的'输送'和'客户'的对象。

The solution is to map the entities manually. To make my life easier, I've used code from my 'DeliveryTracker' sample application in the code snippets below. In my blog article you can see an example of manual mapping: http://bartjolling.blogspot.com/2012/04/building-single-page-apps-with-aspnet.html so my examples below are working on the 'delivery' and 'customer' objects.

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; }
    }
}

数据服务控制器

的数据服务控制器暴露符合的OData标准上的数据
HTTP://本地主机:[yourport] / API / DataService的/ GetCustomers的。为了能够更新,你需要定义一个UpdateCustomer和UpdateDelivery功能客户和交付

The data service controller

The data service controller exposes the data conforming to OData standards on "http://localhost:[yourport]/api/dataservice/GetCustomers". In order to be able to update both customers and deliveries you need to define an UpdateCustomer AND UpdateDelivery function

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文件。在这里,我明确地把每财产到淘汰赛观察到。解决你的问题的关键是在那里我映射传入交付到一个可观察到的阵列

Client-side domain model

Add a new javascript file containing your client-side model. Here I'm explicitly turning every property into an knockout observable. The key for solving your problem is the line inside the constructor of the Customer object where I'm mapping the incoming deliveries into an observable array

/// <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,指定自定义客户端映射和绑定视图模型

The View

In the index.cshtml you initialize Upshot, specify custom client mapping and bind the 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>

的结果

当导航到索引页,客户和相关交货的名单将异步加载。所有的运送是由客户分组,并且$ P $对固定绑定到输送的'IsDelivered'属性的复选框。因为它绑定到一个输入元素的客户的名称是可编辑的太

The Results

When navigating to the index page, the list of customers and related deliveries will be loaded asynchronously. All the deliveries are grouped by customer and are pre-fixed with a checkbox that is bound to the 'IsDelivered' property of a delivery. The customer's name is editable too since it's bound to an INPUT element

我没有足够的声誉张贴的截图,所以你将有没有做一

选中或取消选中现在的IsDelivered复选框后,结果将探测到这一变化,并张贴到DataService的控制器

When checking or unchecking the IsDelivered checkbox now, Upshot will detect the change and post 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 modifying the customer's name, Upshot will submit the changes when the input box 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 above procedure, Upshot will both update parent and child entities for you.

这篇关于如何上传通过MVC4结果相关的实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆