我想将angular.js与对Microsoft Dynamics CRM webapi端点的调用结合起来。
网页显示项目列表作为复选框。选中未选中的复选框应执行关联。取消勾选复选框后,请执行解除关联。
您将在下面的代码中看到关联确实有效,但解除关联不起作用。我无法设置一个plunker,因为代码与Microsoft Dynamics CRM应用程序绑定。
首先,HTML部分
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script src="../../ClientGlobalContext.js.aspx"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.4/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.4/angular-resource.min.js"></script>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script src="crmwebapimodule.js"></script>
<script src="manyrelationshipapp.js"></script>
</head>
<body ng-app="crmApp">
<div ng-controller="AppController" class="col-sm-7 col-md-2">
<div ng-repeat="match in matches">
<input type="checkbox" id="{{match.recordId}}" ng-model="match.checked" ng-click="doAction(match.recordId, match.checked)" />
<span for="{{match.recordId}}">{{match.label}}</span>
</div>
</div>
</body>
</html>
然后是我的CRM模块
// create a module with a dependency on ngResource
var angularMscrm = angular.module('ManyRelationshipAngularMscrm', ['ngResource']);
// define the CrmService factory
angularMscrm.factory('CrmWebApiService', function ($resource) {
var oDataUrl = Xrm.Page.context.getClientUrl() + '/api/data/v8.1/';
var defaultParams = {};
// describe our API actions
var actions = {
GetActiveItems: {
isArray: false,
method: 'GET',
url: oDataUrl + ':entitySet?$select=:primaryField',//&$filter=statecode eq 0',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'OData-MaxVersion': '4.0',
'OData-Version': '4.0'
}
},
GetSelectedItems: {
isArray: false,
method: 'GET',
url: oDataUrl + ':entitySet(:primaryEntityId)?$select=:primaryField&$expand=:entityRelationName($select=:secondaryPrimaryField)',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'OData-MaxVersion': '4.0',
'OData-Version': '4.0'
}
},
Associate: {
method: 'POST',
url: oDataUrl + ':primaryEntitySet(:entityId)/:entityRelationName/$ref',
headers: {
'Accept': 'application/json',
'OData-MaxVersion': '4.0',
'OData-Version': '4.0'
}
},
Disassociate: {
method: 'DELETE ',
url: oDataUrl + ':primaryEntitySet(:primaryEntityId)/:entityRelationName(:secondaryEntityId)/$ref',
headers: {
'Accept': 'application/json',
'OData-MaxVersion': '4.0',
'OData-Version': '4.0'
}
}
};
// create the service
return $resource(oDataUrl, defaultParams, actions);
});
最后,控制器本身
/// <reference path="CrmWebApiModule.js" />
(function () {
// create a module for our Angular app with a dependency on our angularMscrm module
var CrmApp = angular.module('crmApp', ['ManyRelationshipAngularMscrm']);
// create a controller for the page, and inject our CrmService into it
CrmApp.controller('AppController', function ($scope, CrmWebApiService) {
// Data for test purpose
var params =
{
recordId: '{32A33A4B-99A4-E511-80C0-00155D0A061D}',
primaryEntitySet: 'opportunities',
primaryIdAttr: 'opportunityid',
primaryField: 'name',
secondaryEntitySet: 'competitors',
secondaryIdAttr: 'competitorid',
secondaryPrimaryField: 'name',
entityRelationSet: 'opportunitycompetitors_association'
};
if (params.recordId.length == 38) {
params.recordId = params.recordId.substr(1, 36);
}
$scope.matches = new Array();
$scope.doAction = function (id, value) {
if (value === true) {
CrmWebApiService.Associate({
primaryEntitySet: params.primaryEntitySet,
entityId: params.recordId,
entityRelationName: params.entityRelationSet
},
{
"@odata.id": Xrm.Page.context.getClientUrl() + '/API/data/v8.1/' + params.secondaryEntitySet + '('+ id +')'
}, function(response) {
alert(httpResponse);
});
} else {
CrmWebApiService.Disassociate({
primaryEntitySet: params.primaryEntitySet,
primaryEntityId: params.recordId,
entityRelationName: params.entityRelationSet,
secondaryEntityId: id
}, function (response) {
},
function(httpResponse) {
alert(httpResponse);
});
}
}
CrmWebApiService.GetActiveItems({
entitySet: params.secondaryEntitySet,
primaryField: params.secondaryPrimaryField
},
function (response) {
var data = response.value;
for (var i = 0; i < data.length; i++) {
$scope.matches.push({
recordId: data[i][params.secondaryIdAttr].toLowerCase(),
label: data[i][params.secondaryPrimaryField],
checked: false
});
}
});
CrmWebApiService.GetSelectedItems({
entitySet: params.primaryEntitySet,
primaryEntityId: params.recordId,
primaryField: params.primaryField,
entityRelationName: params.entityRelationSet,
secondaryPrimaryField: params.secondaryPrimaryField
},
function (response) {
var data = response[params.entityRelationSet];
for (var i = 0; i < $scope.matches.length; i++) {
for (var j = 0; j < data.length; j++) {
if ($scope.matches[i].recordId === data[j][params.secondaryIdAttr]) {
$scope.matches[i].checked = true;
break;
}
}
}
});
});
}());
Soo,该关联按预期工作,但解除关联会导致以下错误:
Error: The operation is insecure.
hf/<@https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.4/angular.min.js:84:6
s@https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.4/angular.min.js:80:22
m/f<@https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.4/angular.min.js:77:308
f/<@https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.4/angular.min.js:107:349
Ge/this.$get</k.prototype.$eval@https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.4/angular.min.js:121:189
Ge/this.$get</k.prototype.$digest@https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.4/angular.min.js:118:296
Ge/this.$get</k.prototype.$apply@https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.4/angular.min.js:121:458
tc[c]</<.compile/</<@https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.4/angular.min.js:220:167
$e/c@https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.4/angular.min.js:32:253
e/<()angular.min.js (ligne 99)
ye/this.$get</<(a=Object { type="object"}, c=undefined)angular.min.js (ligne 74)
f/<()angular.min.js (ligne 107)
Ge/this.$get</k.prototype.$eval(a=Object { type="object"}, b=undefined)angular.min.js (ligne 121)
Ge/this.$get</k.prototype.$digest()angular.min.js (ligne 118)
Ge/this.$get</k.prototype.$apply(a=Object { type="object"})angular.min.js (ligne 121)
tc[c]</<.compile/</<(d=Object { type="object"})angular.min.js (ligne 220)
$e/c(c=Object { type="object"}, e=undefined)angular.min.js (ligne 32)
我只是不知道什么是不安全的以及如何解决这个问题......
我看到的唯一区别是关联与HTTP POST一起使用并与HTTP DELETE取消关联,但它不会导致我解决问题。
感谢您的帮助