2014-09-06 7 views
2

У меня есть сетка интерфейса Kendo, подключенная к сервисам CRD Odata (Web API 2.2 OData V4). Конфигурация dataSource выглядит следующим образом: baseUrl для всех одинакова, только изменения глагола HTTP.Web API 2.2 OData V4 - Kendo Grid - настроить Созданный IHttpActionResult

var dataSource = new kendo.data.DataSource({ 
    type: "odata", 
    transport: { 
     read: { 
      beforeSend: prepareRequest, 
      url: baseUrl, 
      type: "GET", 
      dataType: "json" 
     }, 
     update: { 
      beforeSend: prepareRequest, 
      url: function (data) { 
       return baseUrl + "(" + data.CategoryId + ")"; 
      }, 
      type: "PUT", 
      dataType: "json" 
     }, 
     create: { 
      beforeSend: prepareRequest, 
      url: baseUrl, 
      type: "POST", 
      dataType: "json" 
     }, 
     destroy: { 
      beforeSend: prepareRequest, 
      url: function (data) { 
       return baseUrl + "(" + data.CategoryId + ")"; 
      }, 
      type: "DELETE", 
      dataType: "json" 
     }, 
     parameterMap: function (data, operation) { 
      if (operation == "read") { 
       var paramMap = kendo.data.transports.odata.parameterMap(data); 
       delete paramMap.$format; 
       delete paramMap.$inlinecount; 
       paramMap.$count = true; 
       return paramMap; 
      } else if (operation == "create" || operation == "update") { 
       delete data["__metadata"]; 
       return JSON.stringify(data); 
      } 
     } 
    }, 
    batch: false, 
    pageSize: 10, 
    serverPaging: true, 
    serverSorting: true, 
    serverFiltering: true, 
    sort: { field: "CategoryCode", dir: "asc" }, 
    schema: { 
     data: function (data) { return data.value; }, 
     total: function (data) { return data['@@odata.count']; }, 
     model: { 
      id: "CategoryId", 
      fields: { 
       CategoryId: { editable: false, type: "number" }, 
       CategoryCode: { editable: true, type: "string", required: true, validation: { maxlength: 2 } }, 
       Description: { editable: true, type: "string", required: true, validation: { maxlength: 50 } }, 
       Created: { editable: false, type: "date" }, 
       CreatedBy: { editable: false, type: "string" }, 
       Updated: { editable: false, type: "date" }, 
       UpdatedBy: { editable: false, type: "string" } 
      } 
     } 
    }, 
    error: function (e) {     
     commonNotification.hide(); 
     commonNotification.show(getRequestError(e), "error"); 
    },    
    change: function (e) {     
     commonNotification.hide(); 
     if (e.action == "sync") {         
      commonNotification.show("@SharedResources.Changes_Saved", "success"); 
     }     
    }, 
    requestStart: function (e) {     
     if (e.type == "read" && this.hasChanges()) { 
      if (confirm("@SharedResources.Dirty_Navigation_Confirmation") == false) { 
       e.preventDefault(); 
      } else { 
       this.cancelChanges(); 
      } 
     }     
    } 
}); 

Вообще говоря, все отлично работает. Функция prepareRequest() используется для применения настраиваемого заголовка авторизации, а также для установки заголовка Accept на «application/json; odata = verbose».

При чтении, ответ JSON выглядит примерно так - именно поэтому функция возвращает dataSource.schema.data data.value

{ 
    "@odata.context":"https://localhost:44305/odata/$metadata#Categories", 
    "@odata.count":2, 
    "value":[ 
    { 
     "CategoryId":1, 
     "CategoryCode":"01", 
     "Description":"Something", 
     "Created":"2014-08-01T11:03:30.207Z", 
     "CreatedBy":"DOMAIN\\User", 
     "Updated":"2014-09-05T14:36:22.6323744-06:00", 
     "UpdatedBy":"DOMAIN\\User" 
    },{ 
     "CategoryId":2, 
     "CategoryCode":"02", 
     "Description":"Something Else", 
     "Created":"2014-08-01T11:03:35.61Z", 
     "CreatedBy":"DOMAIN\\User", 
     "Updated":"2014-08-26T16:07:29.198241-06:00", 
     "UpdatedBy":"DOMAIN\\User" 
    } 
    ] 
} 

Однако, когда я создать или обновить объект, то JSON вернулся, выглядит следующим образом:

{ 
    "@odata.context":"https://localhost:44305/odata/$metadata#Categories/$entity", 
    "CategoryId":3, 
    "CategoryCode":"03", 
    "Description":"Yet Another", 
    "Created":"2014-09-06T07:55:52.4933275-06:00", 
    "CreatedBy":"DOMAIN\\User", 
    "Updated":"2014-09-06T13:55:34.054Z", 
    "UpdatedBy":"" 
} 

Поскольку это не обернуто «значение», сетка Кендо не обновляет источник данных правильно. Контроллер, который делает POST или PUT, в настоящее время возвращает объект следующим образом:

return Created(category); 

ИЛИ

return Updated(category); 

я был в состоянии решить проблему, изменив ответ на JsonResult следующим образом:

return Json(new { value = new[] { category } }); 

С этим все работает по своему желанию ... однако мой HTTP-ответ теперь составляет 200 (кажется, что JsonResult всегда будет отвечать 200). В идеальном мире я мог бы вернуть 201 на создание. Должен ли я просто согласиться с тем, что у меня есть работа и живу с 200, или, есть ли простой способ ответить 201 и по-прежнему форматировать мой JSON по мере необходимости? Кажется, Web API 2 разрешил более настраиваемый HTTP-ответ, но мои действия с контроллером web api 2.2 возвращают IHttpActionResult. Я действительно не хочу создавать пользовательский класс, чтобы иметь специальный тип возврата, и я не могу вернуть анонимный объект с помощью Create().

Таким образом, я действительно склоняюсь к тому, чтобы жить только с тем, что у меня есть. Тем не менее, мне будет интересен способ вернуть мой анонимный объект с помощью 201 или способ принять не-значение «обернутое значение» json в моем источнике данных kendo и обновить данные соответствующим образом.

ответ

2

Это то, что я закончил делать в конце - я создал свой собственный метод «CreatedObject», который будет генерировать ResponseMessageResult. Это приведет к обертыванию объекта анонимным объектом «значение» и сериализации в json. Тогда я мог бы вернуть это с желаемым кодом ответа.

public ResponseMessageResult CreatedObject(string location, object createdObject) 
{ 
    JavaScriptSerializer serializer = new JavaScriptSerializer(); 
    string json = serializer.Serialize(new { value = new[] { createdObject } }); 

    // Create the response and add the 201 response code 
    HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Created);    
    response.Headers.Add("Location", location); 
    response.Content = new System.Net.Http.StringContent(json); 

    // return the result 
    return ResponseMessage(response); 
} 

Это решило проблему для источника данных Kendo как клиента. Однако мне не понравилась идея манипулирования откликом odata для конкретного клиента. Таким образом, вместо того, я изменил клиент для обработки нормального Web API ответа OData следующим образом:

schema: { 
    data: function (data) {      
     if (data.value) { 
      return data.value; 
     } else { 
      delete data["@@odata.context"]; 
      return data; 
     } 
    }, 
    total: function (data) { return data['@@odata.count']; }, 
    model: { 
     etc... 

Теперь, schema.data() проверяет, чтобы увидеть, если объект (ы), завернутые в «значение «или нет, прежде чем возвращать соответствующие данные. При возврате созданного объекта мне пришлось удалить атрибут @ odata.context, поскольку kendo ему это не понравилось.

0

Мне нравится решение манипулировать этим в клиенте намного лучше. Одна вещь, которую я должен был добавить не является нулевой PK как мой OData конечной точки не будет, за исключением нулевой идентификатор:

    parameterMap: function (data, operation) { 
         if (operation == "read") { 
          var paramMap = kendo.data.transports.odata.parameterMap(data); 
          delete paramMap.$format; 
          delete paramMap.$inlinecount; 
          paramMap.$count = true; 
          return paramMap; 
         } else if (operation == "create" || operation == "update") { 
          //delete data["__metadata"]; 
          if (data.Id==null) { 
           data.Id = 1; 
          } 
          return JSON.stringify(data); 
         } 
        }, 
5

Update Поскольку Kendo now supports ODATA V4 больше нет никакой необходимости ухищрений, чтобы сделать его работу.

Изменение типа набора данных из

type: 'odata'

в

type: 'odata-v4'

Если сделать трюк. Пример исходного кода: here

+1

Очень круто. Благодаря! –

Смежные вопросы