jaydata 1.5 с odata 4 и angularjs - ошибки при сохранении / обновлении данных
Я использую jaydata 1.5.1 с odata 4 и ASP.Net WebAPI OData 4. К сожалению, почти все примеры на веб-сайте jaydata предназначены для более старых версий самих jaydata или протоколов odata < 4.0. Я не смог найти подходящего примера, который бы охватывал jaydata > 1.5 + odata 4 + angularjs, что заставило бы меня хотя бы почувствовать, что этот проект (jaydata) отчасти умирает.
Мне удалось запустить сервис jaydata и запросить данные. Но как только я пытаюсь манипулировать данными (добавление, редактирование, сохранение), я получаю ошибки, которые не могу устранить из-за отсутствия документации. Пожалуйста, найдите здесь код, который у меня есть:
index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Cache-Control" content="no-store" />
<meta charset="utf-8" />
<link href="Content/bootstrap.min.css" rel="stylesheet" />
<link href="css/font-awesome.min.css" rel="stylesheet" />
<script src="Scripts/jquery-1.10.2.min.js"></script>
<script src="Scripts/odatajs-4.0.0/odatajs-4.0.0.min.js"></script>
<script src="Scripts/angular.min.js"></script>
<script src="Scripts/jaydata/jaydata.js"></script>
<script src="Scripts/jaydata/jaydatamodules/angular.min.js"></script>
<!--<script src="Scripts/jaydata/jaydataproviders/oDataProvider.min.js"></script>-->
<!--<script src="app/model.js"></script>-->
<script src="app/app.js"></script>
</head>
<body data-ng-app="app">
<div ng-controller="ItemController">
<ul>
<li ng-repeat="item in Items">
<input id="checkSlave" type="checkbox" ng-model="item .IstAktiv">
{{item .Vorname}} {{item .Name}} ({{item .Klinik}} - {{item .Abteilung}} : {{item .Station}})
</li>
</ul>
<button ng-click="newItem()">add new</button>
<p>
<form ng-if="selectedItem">
<fieldset style="width: 300px; background-color: #0094ff;">
<legend>{{selectedItem.Name}}</legend>
<br />
<label>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<td class="text-center">Aktiv</td>
<td class="text-center">Vorname</td>
<td class="text-center">Name</td>
<td class="text-center">Klinik</td>
<td class="text-center">Abteilung</td>
<td class="text-center">Station</td>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center"><input id="checkSlave" type="checkbox" ng-model="selectedItem.IstAktiv"></td>
<td class="text-center"><input ng-model="selectedItem.Vorname" size="20" /></td>
<td class="text-center"><input ng-model="selectedItem.Name" size="20" /></td>
<td class="text-center"><input ng-model="selectedItem.Klinik" size="20" /></td>
<td class="text-center"><input ng-model="selectedItem.Abteilung" size="20" /></td>
<td class="text-center"><input ng-model="selectedItem.Station" size="20" /></td>
</tr>
</tbody>
</table>
</label>
<button ng-click="save()">Save</button>
<button ng-click="remove()">Remove</button>
</fieldset>
</form>
</p>
</div>
</body>
</html>
app.js:
var app = angular.module('app', ['jaydata']);
app.controller('ItemController', ['$scope', '$data', function ($scope, $data, $q) {
$scope.Items = [];
$scope.selectedItem = null;
$data.initService('http://odata/test/JaydataTest/')
.then(function (context) {
$scope.context = context;
context
.Items
//.map(function (p) { return p.Name })
//.select("{ CategoryObject: it.Category, Name: it.Name }")
//.filter(function (item) { item.Name.startsWith('Kim');})
// .filter(function (product) { return product.Id > idParam }, { idParam: 2 })
//.find(2)
//.orderBy(function (item) {item.Klinik})
.toArray()
.then(function (result) {
$scope.Items = result;
$scope.$apply();
})
})
.catch(function (error) {
alert(error);
});
$scope.save = function () {
if ($scope.selectedItem.ItemId) {
// save existing
$scope.context.Items.attach($scope.selectedItem, true);
$scope.selectedItem.entityState = $data.EntityState.Modified;
}
else {
// save new
$scope.context.Items.add($scope.selectedItem, true);
}
$scope.saveChanges();
};
$scope.saveChanges = function () {
$scope.context.saveChanges()
.then(function (n) {
$scope.selectedItem = null;
$scope.$apply();
})
.fail(function (error) { console.log(error); });
}
$scope.newItem = function () {
var ctx = $scope.context;
$scope.selectedItem = new ctx.Items.elementType({Name: "new Item"})
};
}])
Я получаю следующие ошибки:
1) при сохранении данные правильно сохраняются в базовой базе данных, но я получаю следующую ошибку консоли, и контекст не обновляется, и новый элемент не отображается только после обновления страницы (angular.js = jaydatamodules/angular. JS):
TypeError: n.call(...).then(...).fail is not a function
at Container.a.default.EntityContext.saveChanges (angular.js:266)
at n.$scope.saveChanges (app.js:112)
at n.$scope.save (app.js:91)
at fn (eval at <anonymous> (angular.js:14432), <anonymous>:4:203)
at b (angular.js:15485)
at e (angular.js:25018)
at n.$eval (angular.js:17229)
at n.$apply (angular.js:17329)
at HTMLButtonElement.<anonymous> (angular.js:25023)
at HTMLButtonElement.x.event.dispatch (jquery-1.10.2.min.js:22)
Я пробовал разные синтаксисы (затем / сбой затем / поймать успех / обратный вызов ошибки), но не могу обойти эту ошибку. Есть идеи?
2) Пока сохранение данных работает, обновление не работает. Я получаю следующую ошибку:
PATCH http://odata/test/JaydataTest//Items(21) 400 (Bad Request) @ odatajs-4.0.0.js:4366
Exception {name: "HTTP request failed", message: "The request is invalid.", data: Object} @ jaydata.js:4315
oDataProvider.js:4156 Uncaught (in promise) Exception {name: "HTTP request failed", message: "The request is invalid.", data: Object}
Как решить эту ошибку?
ODataController:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.ModelBinding;
using System.Web.OData;
using System.Web.OData.Query;
using System.Web.OData.Routing;
using Model;
namespace JaydataTest.Controllers.odata
{
/*
The WebApiConfig class may require additional changes to add a route for this controller. Merge these statements into the Register method of the WebApiConfig class as applicable. Note that OData URLs are case sensitive.
using System.Web.OData.Builder;
using System.Web.OData.Extensions;
using Model;
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Item>("Items");
config.MapODataServiceRoute("odata", "odata", builder.GetEdmModel());
*/
public class ItemsController : ODataController
{
private ModelContext db = new ModelContext();
// GET: odata/Items
[EnableQuery]
public IQueryable<Item> GetItems()
{
return db.Items;
}
// GET: odata/Items(5)
[EnableQuery]
public SingleResult<Item> GetItem([FromODataUri] int key)
{
return SingleResult.Create(db.Items.Where(item => item.ItemId == key));
}
// PUT: odata/Items(5)
public IHttpActionResult Put([FromODataUri] int key, Delta<Item> patch)
{
Validate(patch.GetEntity());
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
Item item = db.Items.Find(key);
if (item == null)
{
return NotFound();
}
patch.Put(item);
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!ItemExists(key))
{
return NotFound();
}
else
{
throw;
}
}
return Updated(item);
}
// POST: odata/Items
public IHttpActionResult Post(Item item)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Items.Add(item);
db.SaveChanges();
return Created(item);
}
// PATCH: odata/Items(5)
[AcceptVerbs("PATCH", "MERGE")]
public IHttpActionResult Patch([FromODataUri] int key, Delta<Item> patch)
{
Validate(patch.GetEntity());
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
Item item = db.Items.Find(key);
if (item == null)
{
return NotFound();
}
patch.Patch(item);
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!ItemExists(key))
{
return NotFound();
}
else
{
throw;
}
}
return Updated(item);
}
// DELETE: odata/Items(5)
public IHttpActionResult Delete([FromODataUri] int key)
{
Item item = db.Items.Find(key);
if (item == null)
{
return NotFound();
}
db.Items.Remove(item);
db.SaveChanges();
return StatusCode(HttpStatusCode.NoContent);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool ItemExists(int key)
{
return db.Items.Count(e => e.ItemId == key) > 0;
}
}
}
jaydatamodules / angular.js (отрывок)
var originalSave = $data.Entity.prototype.save;
var originalRemove = $data.Entity.prototype.remove;
var originalSaveChanges = $data.EntityContext.prototype.saveChanges;
$data.EntityContext.prototype.saveChanges = function () {
var _this = this;
var d = $q.defer();
originalSaveChanges.call(_this).then(function (n) {
cache = {};
d.resolve(n);
if (!$rootScope.$$phase) $rootScope.$apply();
}).fail(function (err) {
d.reject(err);
if (!$rootScope.$$phase) $rootScope.$apply();
});
return d.promise;
}
return $data;
}]);
Помощь очень ценится. заранее спасибо
2 ответа
Я рекомендую вам проверить примеры репозиториев JayData angular2 и jaydata odata v4. Оба используют JayData 1.5.5 RC, который больше не нуждается в odatajs, поскольку он уже включает в себя исправленную версию.
Вы должны включить следующий модуль:
<script src="Scripts/jaydatamodules/deferred.js"></script>
http://jaydata.org/blog/how-to-work-with-the-jaydata-promise-interfaces