Jaydata更新无法正常使用webapi v2 odata

时间:2014-01-17 21:51:50

标签: asp.net-web-api odata jaydata asp.net-web-api-odata

我已经初始化了一个jaydata上下文:

$data.initService('/odata/$metadata', { dataServiceVersion: '3.0' }).then(function (context) {
    if (!mycontext)
        mycontext= context;

   //this is a hack
    mycontext.prepareRequest = function (r) {
        if (r[0].method == "PATCH") {
            r[0].method = 'PUT';
            r[0].headers['X-HTTP-METHOD'] = 'UPDATE';
        }
    };

    vm.roles = mycontext.Role.toLiveArray();
    vm.users = mycontext.User.toLiveArray();
});

mycontext.prepareRequest的解决方法是在找到this issue on github

后完成的

初始化角色和用户列表成功显示。但是我仍然在更新实体时遇到问题:

vm.updateRole = function (r) {
    r.Name = 'NewUpdatedName';
    zivacontext.Role.attach(r);
    r.entityState = $data.EntityState.Modified;
    zivacontext.saveChanges().then(function (result) {
        debugger;
    });

};

请求被重定向到下面提供的控制器的UpdateEntity方法,但是只设置了实体的Id属性。其他属性为NULL,如果请求被重定向到PatchEntity方法(当未应用变通方法时),则更改的字段不会传递给增量。在两种情况下的请求有效负载中(有或没有黑客攻击),只有Id被传递给服务器。

控制器:

public class BaseODataController:EntitySetController         TEntity:class         其中TEntityDto:class         其中TIdentityType:class         其中TService:ICrudService { // ...

protected override TEntityDto UpdateEntity(TIdentityType key,TEntityDto update)         {             _service.Update(更新);             return base.UpdateEntity(key,update);         }

    protected override TEntityDto PatchEntity(TIdentityType key, Delta<TEntityDto> patch)
    {
        return base.PatchEntity(key, patch);
    }

// ... }

同样在调试时我可以看到实体已跟踪更改:

r: RoleDto
  $$hashKey: "00I"
  Description: (...)
  Id: (...)
  Name: (...)
  ValidationErrors: (...)
  _ValidationErrors: Array[0]
  _changedProperties: Array[2]
    0: MemberDefinition
    1: MemberDefinition
       configurable: true
       dataType: function String() { [native code] }
       definedBy: function RoleDto(){
       enumerable: true
       kind: "property"
       name: "Name"
       originalType: "Edm.String"
       type: function String() { [native code] }
       __proto__: MemberDefinition
       length: 2
       __proto__: Array[0]
_entityState: 30
_isDirty: true
_isNew: false

我唯一不理解的是为什么ValidationErrors在_changedProperties中:

_changedProperties: Array[2]
  0: MemberDefinition
    configurable: true
    dataType: function Array() { [native code] }
    definedBy: function Entity(){
    elementType: function ValidationError(){
    enumerable: false
    kind: "property"
    monitorChanges: true
    name: "ValidationErrors"
    notMapped: true
    originalElementType: function ValidationError(){
    originalType: function Array() { [native code] }
    storeOnObject: true
    type: function Array() { [native code] }
    __proto__: MemberDefinition

所以这里的问题是为什么更改没有在Request Payload中传递给服务器?

提前致谢!

1 个答案:

答案 0 :(得分:3)

在初始化时,使用maxDataServiceVersion代替dataServiceVersion

我不确定为什么你需要上述黑客攻击,尤其是在使用UPDATE http://msdn.microsoft.com/en-us/library/dd541276.aspx之类的未知动词时。在OData中,V2有两个允许的HTTP动词MERGE,V3有PATCH。设置maxDataServiceVersion: 3.0后,JayData将发送正确的PATCH个请求。

您正在使用的 hack 应该应用于不同的情况,其中客户端,代理,路由器不支持这两个动词。在这种情况下,您将发送POST请求,并将所需的动词设置为X-HTTP-Method。这种方法通常被称为动词隧道,参见例如http://msdn.microsoft.com/en-us/library/dd541471.aspx

$data.initService('/odata', { maxDataServiceVersion: '3.0' }).then(function (context) {
    if (!mycontext)
        mycontext= context;

   //this hack shouldn't be used here
   // mycontext.prepareRequest = function (r) {
   //     if (r[0].method == "PATCH") {
   //         r[0].method = 'PUT';
   //         r[0].headers['X-HTTP-METHOD'] = 'UPDATE';
   //     }
   // };


    vm.roles = mycontext.Role.toLiveArray();
    vm.users = mycontext.User.toLiveArray();
});
根据评论

更新

我会通过控制台检查上下文。确保ctx全球可用,例如

window.ctx = context;

通过ID附加内容,例如

var role = ctx.Role.attachOrGet({ID: 'GUID or Int'});

role.将授予您访问实体属性的权限,例如假设Status属性接受Int

role.Status = 1; //Set role.Status to 1

上次运行ctx.saveChanges()。如果一切设置正确,JayData将向/odata/Role/GUID端点发送PATCH请求,并将更改作为JSON有效负载。