├── .gitignore ├── JS ├── Examples │ ├── RecordCountWebResource │ │ ├── CRMSolutions │ │ │ ├── XrmToolsCRMWebAPIRecordCountExample_1_0_0_0.zip │ │ │ └── XrmToolsCRMWebAPIRecordCountExample_1_0_0_0_managed.zip │ │ ├── RecordCount.html │ │ └── scripts │ │ │ └── RecordCount.js │ ├── SimpleCRMWebResource │ │ ├── README.md │ │ └── SimpleCRMWebResource.html │ ├── SimpleMetaDataWebResource │ │ └── SimpleMetaDataWebResource.html │ └── SinglePage │ │ └── app │ │ ├── index.html │ │ ├── scripts │ │ ├── app.js │ │ └── controllers │ │ │ ├── accountListController.js │ │ │ ├── homeController.js │ │ │ └── userDataController.js │ │ ├── styles │ │ └── app.css │ │ └── views │ │ ├── Home.html │ │ ├── accountList.html │ │ └── userData.html ├── README.md ├── lib │ ├── CRMWebAPI.js │ ├── CRMWebAPIMetadata.js │ └── Releases │ │ ├── CRMWebAPI-1.0.0.js │ │ ├── CRMWebAPI-1.1.0.js │ │ ├── CRMWebAPI-1.2.0.js │ │ ├── CRMWebAPI-1.2.1.js │ │ ├── CRMWebAPI-1.3.0.js │ │ ├── CRMWebAPI-1.3.1.js │ │ ├── CRMWebAPI-1.3.2.js │ │ ├── CRMWebAPI-1.3.3.js │ │ ├── CRMWebAPI-1.3.4.js │ │ ├── CRMWebAPI-1.3.5.js │ │ ├── CRMWebAPIMetadata-1.0.0.js │ │ ├── CRMWebAPIMetadata-1.1.0.js │ │ ├── CRMWebAPIMetadata-1.1.1.js │ │ ├── CRMWebAPIMetadata-1.1.2.js │ │ ├── CRMWebAPIMetadata-1.1.3.js │ │ ├── CRMWebAPIMetadata-1.2.0.js │ │ ├── CRMWebAPIMetadata-1.2.1.js │ │ ├── CRMWebAPIMetadata-1.3.0.js │ │ ├── CRMWebAPIMetadata-1.3.1.js │ │ ├── CRMWebAPIMetadata-1.3.2.js │ │ ├── CRMWebAPIMetadata-1.3.5.js │ │ └── README.md └── tests │ ├── test.browser.js │ ├── test.html │ └── test.node.js ├── LICENSE ├── README.md ├── bower.json ├── dotnet ├── ReadMe.md ├── Xrm.Tools.WebAPI.Core │ ├── Xrm.Tools.WebAPI.Core.csproj │ ├── Xrm.Tools.WebAPI.Core.sln │ ├── bin │ │ └── Debug │ │ │ └── netcoreapp1.0 │ │ │ └── Xrm.Tools.WebAPI.deps.json │ └── xt.snk ├── Xrm.Tools.WebAPI.NuGet │ ├── NuGet.config │ ├── NuGet.exe │ ├── NuGet.log │ ├── NuGetPackage.ps1 │ ├── NuGetSetup.ps1 │ ├── Package.nuspec │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Xrm.Tools.CRMWebAPI.1.0.0.nupkg.bak │ ├── Xrm.Tools.CRMWebAPI.1.0.1.nupkg.bak │ ├── Xrm.Tools.CRMWebAPI.1.0.2.nupkg.bak │ ├── Xrm.Tools.CRMWebAPI.1.0.24.nupkg │ ├── Xrm.Tools.CRMWebAPI.1.0.3.nupkg.bak │ ├── Xrm.Tools.CRMWebAPI.1.0.4.nupkg.bak │ ├── Xrm.Tools.CRMWebAPI.1.0.5.nupkg.bak │ ├── Xrm.Tools.WebAPI.NuGet.csproj │ ├── packages.config │ └── tools │ │ ├── init.ps1 │ │ ├── install.ps1 │ │ └── uninstall.ps1 ├── Xrm.Tools.WebAPI.Portable │ ├── CRMOptionDisplayValue.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Xrm.Tools.WebAPI.Portable.csproj │ ├── project.json │ └── project.lock.json ├── Xrm.Tools.WebAPI.Standard │ ├── Xrm.Tools.WebAPI.Standard.csproj │ └── xt.snk ├── Xrm.Tools.WebAPI.Test │ ├── ActionTests.cs │ ├── BasicCRUDTests.cs │ ├── BasicChangeTrackingTests.cs │ ├── BasicMetadataTests.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── UnitTestBaseClass.cs │ ├── Xrm.Tools.WebAPI.Test.csproj │ ├── app.config │ └── packages.config ├── Xrm.Tools.WebAPI.sln └── Xrm.Tools.WebAPI │ ├── CRMWebAPI.cs │ ├── Metadata │ └── CRMWebAPIMetadata.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── Requests │ ├── CRMExpandOptions.cs │ ├── CRMGetListOptions.cs │ ├── CRMWebAPIConfig.cs │ └── CRMWebAPILoggingOptions.cs │ ├── Results │ ├── CRMAttributeDisplayName.cs │ ├── CRMBatchResult.cs │ ├── CRMEntityDisplayName.cs │ ├── CRMGetListResult.cs │ ├── CRMMultipleOperationResultItem.cs │ ├── CRMOptionDisplayValue.cs │ ├── CRMUpdateResult.cs │ └── CRMWebAPIException.cs │ ├── Xrm.Tools.WebAPI.csproj │ ├── app.config │ ├── packages.config │ └── xt.snk ├── nodejs ├── README.md ├── examples │ └── callactionclientcreds │ │ ├── index.js │ │ ├── package.json │ │ └── readme.md ├── lib │ ├── CRMWebAPI.d.ts │ └── CRMWebAPI.js └── package.json ├── php ├── .gitignore ├── README.md ├── composer.json ├── composer.lock └── lib │ └── CRMWebAPI.php └── python ├── .gitignore ├── Makefile ├── README.md ├── README.rst ├── crmwebapi ├── __init__.py └── crmwebapi.py ├── setup.cfg └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | dotnet/.vs 2 | dotnet/packages 3 | dotnet/Xrm.Tools.WebAPI/packages 4 | dotnet/Xrm.Tools.WebAPI/obj 5 | dotnet/Xrm.Tools.WebAPI/bin 6 | dotnet/Xrm.Tools.WebAPI.Test/bin 7 | dotnet/Xrm.Tools.WebAPI.Test/obj 8 | dotnet/Xrm.Tools.WebAPI.Portable/bin 9 | dotnet/Xrm.Tools.WebAPI.Portable/obj 10 | dotnet/Xrm.Tools.WebAPI.Portable/packages 11 | dotnet/Xrm.Tools.WebAPI.Standard/bin 12 | dotnet/Xrm.Tools.WebAPI.Standard/obj 13 | dotnet/Xrm.Tools.WebAPI.Standard/packages 14 | dotnet/Xrm.Tools.SeverCommonTest/obj 15 | dotnet/Xrm.Tools.WebAPI.NuGet/bin/ 16 | dotnet/Xrm.Tools.WebAPI.NuGet/obj 17 | dotnet/Xrm.Tools.WebAPI.NuGet/obj/Debug/** 18 | dotnet/Xrm.Tools.WebAPI.Core/obj/ 19 | 20 | .vs 21 | .nuget 22 | node_modules 23 | *.dll 24 | *.pdb 25 | .idea 26 | *.bak 27 | *.iml 28 | nodejs/test.js 29 | nodejs/node_modules -------------------------------------------------------------------------------- /JS/Examples/RecordCountWebResource/CRMSolutions/XrmToolsCRMWebAPIRecordCountExample_1_0_0_0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidyack/Xrm.Tools.CRMWebAPI/1d89792291b435cf659932bdc8e54662c7ddf4b7/JS/Examples/RecordCountWebResource/CRMSolutions/XrmToolsCRMWebAPIRecordCountExample_1_0_0_0.zip -------------------------------------------------------------------------------- /JS/Examples/RecordCountWebResource/CRMSolutions/XrmToolsCRMWebAPIRecordCountExample_1_0_0_0_managed.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidyack/Xrm.Tools.CRMWebAPI/1d89792291b435cf659932bdc8e54662c7ddf4b7/JS/Examples/RecordCountWebResource/CRMSolutions/XrmToolsCRMWebAPIRecordCountExample_1_0_0_0_managed.zip -------------------------------------------------------------------------------- /JS/Examples/RecordCountWebResource/RecordCount.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Entity Record Counts 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 17 |
18 |
19 |
20 |
21 | 22 |
23 |
24 | 25 |
26 |
27 | 28 |
29 |
30 |
31 | 32 |
33 |
34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |
Entity NameRecord CountStatus
{{item.EntityName}}{{item.RecordCount}}{{item.Status}}
51 |
52 |
53 |
54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /JS/Examples/RecordCountWebResource/scripts/RecordCount.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | var rcApp = angular.module('recordCountApp', []); 4 | 5 | rcApp.controller('recordCountController', ['$scope', function ($scope) { 6 | 7 | $scope.showResultsTable = false; 8 | $scope.loading = false; 9 | $scope.recordCounts = new Array(); 10 | 11 | 12 | $scope.getcount = function () { 13 | $scope.loading = true; 14 | 15 | var recordCount = new Object(); 16 | recordCount.EntityName = entityName.value; 17 | recordCount.RecordCount = 0; 18 | recordCount.Status = "In Progress"; 19 | $scope.recordCounts.push(recordCount); 20 | $scope.showResultsTable = true; 21 | 22 | //Setup query options to retrieve only statecode which all entities have, also setup a PageAction function that will be called with each page of records 23 | //increment the count each time and show the user progress 24 | 25 | var queryOptions = {Select:["statecode"], PageAction:function(page){recordCount.RecordCount += page.length;$scope.$apply();}}; 26 | // you might be wondering why we are't using the oData $count...with CRM it only works to 5,000 records 27 | crmAPI.GetList(entityName.value,queryOptions).then(function (queryResult){ 28 | recordCount.Status = "Done"; 29 | $scope.$apply(); 30 | $scope.loading = false; 31 | }, 32 | function(error) 33 | { 34 | if (error.status == 404) 35 | recordCount.Status = "Entity Not Found"; 36 | else if (error.status == 401) 37 | recordCount.Status = "Not Authorized"; 38 | else 39 | recordCount.Status = "Error"; 40 | $scope.$apply(); 41 | console.log('error on get count query' + JSON.stringify(error)) 42 | }); 43 | 44 | }; 45 | 46 | 47 | }]); 48 | 49 | //Use the following line if you are running this standalone and get a access token manually 50 | //var apiconfig = { APIUrl: 'https://orgname.crm.dynamics.com/api/data/v8.0/', AccessToken: '' }; 51 | 52 | //use the following line if you are running this as a web resource in CRM 53 | var apiconfig = { APIUrl: window.parent.Xrm.Page.context.getClientUrl() + '/api/data/v9.0/'}; 54 | 55 | 56 | var crmAPI = new CRMWebAPI(apiconfig); 57 | -------------------------------------------------------------------------------- /JS/Examples/SimpleCRMWebResource/README.md: -------------------------------------------------------------------------------- 1 | This is a very simple example of a Dynamics CRM Web Resource using the CRMWebAPI helper class 2 | 3 | Currently this is all inline, but obviously for a real web resource we recommend splitting out the JavaScript 4 | 5 | The sample does a call to the function Who Am I, takes the User ID of the current user and retrieves the users detailed data and displays it. 6 | 7 | To try this sample upload it to CRM as a Web Resource and then click on the Preview Page 8 | 9 | The page can be run external to CRM by commenting out the current appconfig objct, and uncommenting the one for runnign outside of CRM. 10 | 11 | When running outside of CRM you will also need to provide an Access token for testing, or integrate with adal.js -------------------------------------------------------------------------------- /JS/Examples/SimpleCRMWebResource/SimpleCRMWebResource.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Simple Single Page 6 | 7 | 8 | 9 | 10 |
11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
LabelValue
26 |
27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 94 | 95 | -------------------------------------------------------------------------------- /JS/Examples/SimpleMetaDataWebResource/SimpleMetaDataWebResource.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Simple Single Page 5 | 6 | 7 | 8 | 9 | 10 |
11 |
12 |
13 |
14 |
From
15 |
16 | 17 |
18 |
19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
Display Name:{{currentEDM.DisplayName}}
Display Collection Name:{{currentEDM.DisplayCollectionName}}
Logical Collection Name:{{currentEDM.LogicalCollectionName}}
Logical Name:{{currentEDM.LogicalName}}
38 |
39 |
40 |
To
41 |
42 | 43 |
44 |
45 | 46 |
47 |
attribute
48 |
49 | 50 |
51 |
52 |
53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
Display Name:{{currentAttr.DisplayName}}
Display Collection Name:{{currentAttr.AttributeType}}
63 |
64 | 65 |
66 |
67 |
68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 140 | 141 | -------------------------------------------------------------------------------- /JS/Examples/SinglePage/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Simple Single Page 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 40 |
41 |
42 |
43 |
44 | 47 |

This sample demonstrates how to take advantage of CRM Web API inyour single page apps.

48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /JS/Examples/SinglePage/app/scripts/app.js: -------------------------------------------------------------------------------- 1 | //Originalted from adal.js example here - https://github.com/Azure-Samples/active-directory-javascript-singlepageapp-dotnet-webapi/blob/master/TodoSPA/App/Scripts/app.js 2 | //tailored to work with Dynamics CRM 3 | 4 | (function () { 5 | 6 | // Enter Global Config Values & Instantiate ADAL AuthenticationContext 7 | window.config = { 8 | instance: 'https://login.microsoftonline.com/', 9 | tenant: 'orgname.onmicrosoft.com', 10 | clientId: '', 11 | postLogoutRedirectUri: window.location.origin, 12 | endpoints: { orgUri: "https://orgname.api.crm.dynamics.com" }, 13 | cacheLocation: 'localStorage', // enable this for IE, as sessionStorage does not work for localhost. 14 | }; 15 | 16 | window.apiconfig = { APIUrl: config.endpoints.orgUri + '/api/data/v8.0/' }; 17 | 18 | var authContext = new AuthenticationContext(config); 19 | 20 | // Get UI jQuery Objects 21 | var $panel = $(".panel-body"); 22 | var $userDisplay = $(".app-user"); 23 | var $signInButton = $(".app-login"); 24 | var $signOutButton = $(".app-logout"); 25 | var $errorMessage = $(".app-error"); 26 | 27 | // Check For & Handle Redirect From AAD After Login 28 | var isCallback = authContext.isCallback(window.location.hash); 29 | authContext.handleWindowCallback(); 30 | $errorMessage.html(authContext.getLoginError()); 31 | 32 | if (isCallback && !authContext.getLoginError()) { 33 | window.location = authContext._getItem(authContext.CONSTANTS.STORAGE.LOGIN_REQUEST); 34 | } 35 | 36 | // Check Login Status, Update UI 37 | var user = authContext.getCachedUser(); 38 | if (user) { 39 | $userDisplay.html(user.userName); 40 | $userDisplay.show(); 41 | $signInButton.hide(); 42 | $signOutButton.show(); 43 | } else { 44 | $userDisplay.empty(); 45 | $userDisplay.hide(); 46 | $signInButton.show(); 47 | $signOutButton.hide(); 48 | } 49 | 50 | // Handle Navigation Directly to View 51 | window.onhashchange = function () { 52 | loadView(stripHash(window.location.hash)); 53 | }; 54 | window.onload = function () { 55 | $(window).trigger("hashchange"); 56 | }; 57 | 58 | // Register NavBar Click Handlers 59 | $signOutButton.click(function () { 60 | authContext.logOut(); 61 | }); 62 | $signInButton.click(function () { 63 | authContext.login(); 64 | }); 65 | 66 | // Route View Requests To Appropriate Controller 67 | function loadCtrl(view) { 68 | switch (view.toLowerCase()) { 69 | case 'home': 70 | return homeController; 71 | case 'accountlist': 72 | return accountListController; 73 | case 'userdata': 74 | return userDataController; 75 | } 76 | } 77 | 78 | // Show a View 79 | function loadView(view) { 80 | 81 | $errorMessage.empty(); 82 | var ctrl = loadCtrl(view); 83 | 84 | if (!ctrl) 85 | return; 86 | 87 | // Check if View Requires Authentication 88 | if (ctrl.requireADLogin && !authContext.getCachedUser()) { 89 | authContext.config.redirectUri = window.location.href; 90 | authContext.login(); 91 | return; 92 | } 93 | 94 | // Load View HTML 95 | $.ajax({ 96 | type: "GET", 97 | url: "views/" + view + '.html', 98 | dataType: "html", 99 | }).done(function (html) { 100 | 101 | // Show HTML Skeleton (Without Data) 102 | var $html = $(html); 103 | $html.find(".data-container").empty(); 104 | $panel.html($html.html()); 105 | ctrl.postProcess(html); 106 | 107 | }).fail(function () { 108 | $errorMessage.html('Error loading page.'); 109 | }).always(function () { 110 | 111 | }); 112 | }; 113 | 114 | function stripHash(view) { 115 | return view.substr(view.indexOf('#') + 1); 116 | } 117 | 118 | }()); 119 | -------------------------------------------------------------------------------- /JS/Examples/SinglePage/app/scripts/controllers/accountListController.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | // The HTML for this View 4 | var viewHTML; 5 | // Instantiate the ADAL AuthenticationContext 6 | var authContext = new AuthenticationContext(config); 7 | 8 | function refreshViewData() { 9 | 10 | 11 | // Empty Old View Contents 12 | var $dataContainer = $(".data-container"); 13 | $dataContainer.empty(); 14 | var $loading = $(".view-loading"); 15 | 16 | 17 | // Acquire Token for Backend 18 | authContext.acquireToken(config.endpoints.orgUri, function (error, token) { 19 | 20 | // Handle ADAL Error 21 | if (error || !token) { 22 | alert('ADAL Error Occurred: ' + error); 23 | return; 24 | } 25 | 26 | apiconfig.AccessToken = token; 27 | 28 | var crmAPI = new CRMWebAPI(apiconfig); 29 | 30 | //crmAPI.ExecuteFunction("WhoAmI").then(function(response){ alert(response.userid)}); 31 | 32 | //var timeZone = { LocalizedStandardName: 'Pacfic Standard Time', LocaleId:1033 }; 33 | //crmAPI.ExecuteFunction("GetTimeZoneCodeByLocalizedName",timeZone).then(function(response){ alert(response.timezone)}); 34 | var data = new Object() 35 | data.name = "test " + new Date().toString(); 36 | var createdID = null; 37 | crmAPI.Create("accounts", data).then(function(result) 38 | { 39 | createdID = result; 40 | console.log('id created is ' + createdID); 41 | crmAPI.Get("accounts", createdID).then(function(result){ 42 | 43 | console.log('account get: ' + JSON.stringify(result)); 44 | 45 | },function(error){console.log('error on get' + JSON.stringify(error))}) 46 | data.name = "new Account name"; 47 | crmAPI.Update("accounts",createdID, data).then(function(result) 48 | { 49 | 50 | console.log('update results' + JSON.stringify(result)); 51 | 52 | crmAPI.Delete("accounts", createdID).then(function(result){ 53 | 54 | console.log('account delete:'); 55 | 56 | },function(error){console.log('error on delete' + JSON.stringify(error))}) 57 | 58 | },function(error) {console.log('error updating record' + JSON.stringify(error))}); 59 | },function(error) {console.log('error creating record' + JSON.stringify(error))}); 60 | 61 | 62 | crmAPI.GetCount("accounts").then(function(result){ 63 | 64 | console.log('account getcount: ' + result); 65 | 66 | },function(error){console.log('error on get count' + JSON.stringify(error))}) 67 | 68 | var queryOptions = { Top:10 , FormattedValues:true}; 69 | 70 | crmAPI.GetList("accounts",queryOptions).then ( 71 | function (response){ 72 | 73 | PopulateOutput(response); 74 | 75 | }, 76 | function(error){}); 77 | 78 | }); 79 | 80 | }; 81 | function PopulateOutput(response) 82 | { 83 | var $html = $(viewHTML); 84 | var $template = $html.find(".data-container"); 85 | 86 | // For Each Todo Item Returned, Append a Table Row 87 | var output = response.List.reduce(function (rows, todoItem, index, todos) { 88 | var $entry = $template; 89 | var $description = $entry.find(".view-data-description").html(todoItem.name); 90 | $entry.find(".data-template").attr('data-todo-id', todoItem.accountid); 91 | return rows + $entry.html(); 92 | }, ''); 93 | 94 | // Update the UI 95 | var $loading = $(".view-loading"); 96 | $loading.hide(); 97 | var $dataContainer = $(".data-container"); 98 | $dataContainer.html(output); 99 | } 100 | 101 | // Module 102 | window.accountListController = { 103 | requireADLogin: true, 104 | preProcess: function (html) { 105 | 106 | }, 107 | postProcess: function (html) { 108 | viewHTML = html; 109 | refreshViewData(); 110 | }, 111 | }; 112 | }()); -------------------------------------------------------------------------------- /JS/Examples/SinglePage/app/scripts/controllers/homeController.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | window.homeController = { 3 | preProcess: function (html) { 4 | // This function is only declared as a placeholder for future improvements. 5 | }, 6 | postProcess: function (html) { 7 | // This view does not need to load any data, it is blank. 8 | }, 9 | }; 10 | }()); 11 | -------------------------------------------------------------------------------- /JS/Examples/SinglePage/app/scripts/controllers/userDataController.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | // The HTML for this View 4 | var viewHTML; 5 | // Instantiate the ADAL AuthenticationContext 6 | var authContext = new AuthenticationContext(config); 7 | 8 | function refreshViewData() { 9 | 10 | // Empty Old View Contents 11 | var $dataContainer = $(".data-container"); 12 | $dataContainer.empty(); 13 | var $loading = $(".view-loading"); 14 | 15 | var user = authContext.getCachedUser(); 16 | 17 | var $html = $(viewHTML); 18 | var $template = $html.find(".data-container"); 19 | var output = ''; 20 | 21 | for (var property in user.profile) { 22 | if (user.profile.hasOwnProperty(property)) { 23 | var $entry = $template; 24 | $entry.find(".view-data-claim").html(property); 25 | $entry.find(".view-data-value").html(user.profile[property]); 26 | output += $entry.html(); 27 | } 28 | } 29 | 30 | // Update the UI 31 | $loading.hide(); 32 | $dataContainer.html(output); 33 | }; 34 | 35 | // Module 36 | window.userDataController = { 37 | requireADLogin: true, 38 | preProcess: function (html) { 39 | 40 | }, 41 | postProcess: function (html) { 42 | viewHTML = html; 43 | refreshViewData(); 44 | }, 45 | }; 46 | }()); -------------------------------------------------------------------------------- /JS/Examples/SinglePage/app/styles/app.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidyack/Xrm.Tools.CRMWebAPI/1d89792291b435cf659932bdc8e54662c7ddf4b7/JS/Examples/SinglePage/app/styles/app.css -------------------------------------------------------------------------------- /JS/Examples/SinglePage/app/views/Home.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /JS/Examples/SinglePage/app/views/accountList.html: -------------------------------------------------------------------------------- 1 |
2 |

Loading...

3 |
4 |
5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 17 | 27 | 28 | 29 |
14 |

15 | 16 |
18 |

19 | Edit | 20 | Delete 21 |

22 | 26 |
30 |
-------------------------------------------------------------------------------- /JS/Examples/SinglePage/app/views/userData.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
ClaimValue
16 |
17 | -------------------------------------------------------------------------------- /JS/README.md: -------------------------------------------------------------------------------- 1 | 2 | Current Version CDN - https://xrmtoolscode.azureedge.net/CRMWebAPI.js 3 | 4 | You can find more query example information [here]( https://github.com/davidyack/Xrm.Tools.CRMWebAPI/wiki/Query-Examples ) 5 | 6 | # Usage example 7 | 8 | ```javascript 9 | 10 | 11 | var apiconfig = { APIUrl: 'https://orgname.crm.dynamics.com/api/data/v8.0/', AccessToken: "" }; 12 | 13 | var crmAPI = new CRMWebAPI(apiconfig); 14 | 15 | crmAPI 16 | .Create("accounts", { "name": "test2" }) 17 | .then( 18 | function(r){ 19 | console.log('Created: ' + r); 20 | return crmAPI.Update('accounts', r, { "name": "test2updated"}); 21 | }, 22 | function(e){ 23 | console.log(e); 24 | }) 25 | .then( 26 | function(r){ 27 | console.log('Updated: ' + r.EntityID); 28 | return crmAPI.Delete('accounts', r.EntityID); 29 | }, 30 | function(e){ 31 | console.log(e); 32 | }) 33 | .then( 34 | function(r){ 35 | console.log('Deleted'); 36 | }, function(e){ 37 | console.log(e); 38 | }) 39 | ``` 40 | Working with Metadata - include CRMWebAPIMetadata.js 41 | 42 | Current Version CDN - https://xrmtoolscode.azureedge.net/CRMWebAPIMetadata.js 43 | 44 | Methods 45 | - GetOptionSetByName 46 | - GetOptionSetUserLabels - returns Label/Value array 47 | - GetEntityDisplayNameList(LCID) - returns object with DisplayName,DisplayCollectionName,LogicalName,LogicalCollectionName for LCID - or pass null for default LCID 48 | 49 | #Metadata Usage example 50 | ```javascript 51 | 52 | crmAPI 53 | .GetOptionSetUserLabels("my_optionsetname") 54 | .then( 55 | function(r){ 56 | console.log('Display Labels: ' + r); 57 | 58 | }, 59 | function(e){ 60 | console.log(e); 61 | }) 62 | 63 | 64 | crmAPI.GetEntityDisplayNameList(1033).then(function(result) 65 | { 66 | //do stuff here... 67 | 68 | }); 69 | 70 | ``` 71 | -------------------------------------------------------------------------------- /JS/lib/Releases/CRMWebAPIMetadata-1.0.0.js: -------------------------------------------------------------------------------- 1 | CRMWebAPI.prototype.GetOptionSetByName = function (optionSetName) { 2 | var self = this; 3 | return new Promise(function (resolve, reject) { 4 | 5 | self.GetList('GlobalOptionSetDefinitions', 6 | {Select:['Name']}).then( 7 | function (r) 8 | { 9 | r.List.forEach(function(set) 10 | { 11 | if (set.Name == optionSetName) 12 | { 13 | self.Get('GlobalOptionSetDefinitions',set.MetadataId).then( 14 | function(res){ 15 | resolve(res); 16 | },function(err){console.log(err)} 17 | ) 18 | } 19 | } 20 | ) 21 | }, 22 | function(e){ 23 | console.log(e) 24 | reject(e) 25 | }) 26 | }); 27 | }; 28 | 29 | CRMWebAPI.prototype.GetOptionSetUserLabels = function (optionSetName) { 30 | var self = this; 31 | return new Promise(function (resolve, reject) { 32 | 33 | self.GetOptionSetByName(optionSetName).then( 34 | function (result) 35 | { 36 | var displayList = new Array(); 37 | result.Options.forEach(function (option) 38 | { 39 | var displayOption = new Object; 40 | displayOption.Value = option.Value; 41 | displayOption.Label = option.Label.UserLocalizedLabel.Label; 42 | displayList.push(displayOption); 43 | }); 44 | resolve(displayList); 45 | } 46 | , 47 | function (err) 48 | { 49 | console.log(err) 50 | reject(err); 51 | } 52 | ); 53 | }); 54 | 55 | } -------------------------------------------------------------------------------- /JS/lib/Releases/CRMWebAPIMetadata-1.1.0.js: -------------------------------------------------------------------------------- 1 | CRMWebAPI.prototype.GetOptionSetByName = function (optionSetName) { 2 | var self = this; 3 | return new Promise(function (resolve, reject) { 4 | 5 | self.GetList('GlobalOptionSetDefinitions', 6 | {Select:['Name']}).then( 7 | function (r) 8 | { 9 | r.List.forEach(function(set) 10 | { 11 | if (set.Name == optionSetName) 12 | { 13 | self.Get('GlobalOptionSetDefinitions',set.MetadataId).then( 14 | function(res){ 15 | resolve(res); 16 | },function(err){console.log(err)} 17 | ) 18 | } 19 | } 20 | ) 21 | }, 22 | function(e){ 23 | console.log(e) 24 | reject(e) 25 | }) 26 | }); 27 | }; 28 | 29 | CRMWebAPI.prototype.GetOptionSetUserLabels = function (optionSetName) { 30 | var self = this; 31 | return new Promise(function (resolve, reject) { 32 | 33 | self.GetOptionSetByName(optionSetName).then( 34 | function (result) 35 | { 36 | var displayList = new Array(); 37 | result.Options.forEach(function (option) 38 | { 39 | var displayOption = new Object; 40 | displayOption.Value = option.Value; 41 | displayOption.Label = option.Label.UserLocalizedLabel.Label; 42 | displayList.push(displayOption); 43 | }); 44 | resolve(displayList); 45 | } 46 | , 47 | function (err) 48 | { 49 | console.log(err) 50 | reject(err); 51 | } 52 | ); 53 | }); 54 | 55 | } 56 | 57 | CRMWebAPI.prototype.GetEntityDisplayNameList = function (LCID) { 58 | var self = this; 59 | return new Promise(function (resolve, reject) { 60 | 61 | 62 | self.GetList('EntityDefinitions', 63 | {Select:['DisplayName','DisplayCollectionName','LogicalName','LogicalCollectionName']}).then( 64 | function (r) 65 | { 66 | var list = new Array(); 67 | r.List.forEach(function(entity) 68 | { 69 | var edm = new Object(); 70 | edm.LogicalName = entity.LogicalName; 71 | edm.LogicalCollectionName = entity.LogicalCollectionName; 72 | if ((entity.DisplayName.LocalizedLabels != null) && (entity.DisplayName.LocalizedLabels.length > 0)) 73 | { 74 | edm.DisplayName = entity.DisplayName.LocalizedLabels[0].Label; 75 | if (LCID != null) 76 | entity.DisplayName.LocalizedLabels.forEach(function (label) { if (label.LanguageCode == LCID) edm.DisplayName = label.Label}); 77 | } 78 | else 79 | edm.DisplayName = edm.LogicalName; 80 | if ((entity.DisplayCollectionName.LocalizedLabels != null) && (entity.DisplayCollectionName.LocalizedLabels.length > 0)) 81 | { 82 | edm.DisplayCollectionName = entity.DisplayCollectionName.LocalizedLabels[0].Label; 83 | if (LCID != null) 84 | entity.DisplayCollectionName.LocalizedLabels.forEach(function (label) { if (label.LanguageCode == LCID) edm.DisplayCollectionName = label.Label}); 85 | } 86 | else 87 | edm.DisplayCollectionName = entity.LogicalCollectionName; 88 | list.push(edm); 89 | } 90 | ) 91 | resolve(list); 92 | }, 93 | function(e){ 94 | console.log(e) 95 | reject(e) 96 | }) 97 | }); 98 | }; -------------------------------------------------------------------------------- /JS/lib/Releases/CRMWebAPIMetadata-1.1.1.js: -------------------------------------------------------------------------------- 1 | CRMWebAPI.prototype.GetOptionSetByName = function (optionSetName) { 2 | var self = this; 3 | return new Promise(function (resolve, reject) { 4 | 5 | self.GetList('GlobalOptionSetDefinitions', 6 | {Select:['Name']}).then( 7 | function (r) 8 | { 9 | r.List.forEach(function(set) 10 | { 11 | if (set.Name == optionSetName) 12 | { 13 | self.Get('GlobalOptionSetDefinitions',set.MetadataId).then( 14 | function(res){ 15 | resolve(res); 16 | },function(err){console.log(err)} 17 | ) 18 | } 19 | } 20 | ) 21 | }, 22 | function(e){ 23 | console.log(e) 24 | reject(e) 25 | }) 26 | }); 27 | }; 28 | 29 | CRMWebAPI.prototype.GetOptionSetUserLabels = function (optionSetName) { 30 | var self = this; 31 | return new Promise(function (resolve, reject) { 32 | 33 | self.GetOptionSetByName(optionSetName).then( 34 | function (result) 35 | { 36 | var displayList = new Array(); 37 | result.Options.forEach(function (option) 38 | { 39 | var displayOption = new Object; 40 | displayOption.Value = option.Value; 41 | displayOption.Label = option.Label.UserLocalizedLabel.Label; 42 | displayList.push(displayOption); 43 | }); 44 | resolve(displayList); 45 | } 46 | , 47 | function (err) 48 | { 49 | console.log(err) 50 | reject(err); 51 | } 52 | ); 53 | }); 54 | 55 | } 56 | 57 | CRMWebAPI.prototype.GetEntityDisplayNameList = function (LCID) { 58 | var self = this; 59 | return new Promise(function (resolve, reject) { 60 | 61 | 62 | self.GetList('EntityDefinitions', 63 | {Select:['MetadataId','DisplayName','DisplayCollectionName','LogicalName','LogicalCollectionName','PrimaryIdAttribute']}).then( 64 | function (r) 65 | { 66 | var list = new Array(); 67 | r.List.forEach(function(entity) 68 | { 69 | var edm = new Object(); 70 | edm.MetadataId = entity.MetadataId; 71 | edm.LogicalName = entity.LogicalName; 72 | edm.LogicalCollectionName = entity.LogicalCollectionName; 73 | edm.PrimaryIdAttribute = entity.PrimaryIdAttribute; 74 | if ((entity.DisplayName.LocalizedLabels != null) && (entity.DisplayName.LocalizedLabels.length > 0)) 75 | { 76 | edm.DisplayName = entity.DisplayName.LocalizedLabels[0].Label; 77 | if (LCID != null) 78 | entity.DisplayName.LocalizedLabels.forEach(function (label) { if (label.LanguageCode == LCID) edm.DisplayName = label.Label}); 79 | } 80 | else 81 | edm.DisplayName = edm.LogicalName; 82 | if ((entity.DisplayCollectionName.LocalizedLabels != null) && (entity.DisplayCollectionName.LocalizedLabels.length > 0)) 83 | { 84 | edm.DisplayCollectionName = entity.DisplayCollectionName.LocalizedLabels[0].Label; 85 | if (LCID != null) 86 | entity.DisplayCollectionName.LocalizedLabels.forEach(function (label) { if (label.LanguageCode == LCID) edm.DisplayCollectionName = label.Label}); 87 | } 88 | else 89 | edm.DisplayCollectionName = entity.LogicalCollectionName; 90 | list.push(edm); 91 | } 92 | ) 93 | resolve(list); 94 | }, 95 | function(e){ 96 | console.log(e) 97 | reject(e) 98 | }) 99 | }); 100 | }; -------------------------------------------------------------------------------- /JS/lib/Releases/CRMWebAPIMetadata-1.1.2.js: -------------------------------------------------------------------------------- 1 | CRMWebAPI.prototype.GetOptionSetByName = function (optionSetName) { 2 | var self = this; 3 | return new Promise(function (resolve, reject) { 4 | 5 | self.GetList('GlobalOptionSetDefinitions', 6 | {Select:['Name']}).then( 7 | function (r) 8 | { 9 | r.List.forEach(function(set) 10 | { 11 | if (set.Name == optionSetName) 12 | { 13 | self.Get('GlobalOptionSetDefinitions',set.MetadataId).then( 14 | function(res){ 15 | resolve(res); 16 | },function(err){console.log(err)} 17 | ) 18 | } 19 | } 20 | ) 21 | }, 22 | function(e){ 23 | console.log(e) 24 | reject(e) 25 | }) 26 | }); 27 | }; 28 | 29 | CRMWebAPI.prototype.GetOptionSetUserLabels = function (optionSetName) { 30 | var self = this; 31 | return new Promise(function (resolve, reject) { 32 | 33 | self.GetOptionSetByName(optionSetName).then( 34 | function (result) 35 | { 36 | var displayList = new Array(); 37 | result.Options.forEach(function (option) 38 | { 39 | var displayOption = new Object; 40 | displayOption.Value = option.Value; 41 | displayOption.Label = option.Label.UserLocalizedLabel.Label; 42 | displayList.push(displayOption); 43 | }); 44 | resolve(displayList); 45 | } 46 | , 47 | function (err) 48 | { 49 | console.log(err) 50 | reject(err); 51 | } 52 | ); 53 | }); 54 | 55 | } 56 | 57 | CRMWebAPI.prototype.GetEntityDisplayNameList = function (LCID) { 58 | var self = this; 59 | return new Promise(function (resolve, reject) { 60 | 61 | 62 | self.GetList('EntityDefinitions', 63 | {Filter:'IsPrivate eq false',Select:['MetadataId','DisplayName','DisplayCollectionName','LogicalName','LogicalCollectionName','PrimaryIdAttribute']}).then( 64 | function (r) 65 | { 66 | var list = new Array(); 67 | r.List.forEach(function(entity) 68 | { 69 | var edm = new Object(); 70 | edm.MetadataId = entity.MetadataId; 71 | edm.LogicalName = entity.LogicalName; 72 | edm.LogicalCollectionName = entity.LogicalCollectionName; 73 | edm.PrimaryIdAttribute = entity.PrimaryIdAttribute; 74 | if ((entity.DisplayName.LocalizedLabels != null) && (entity.DisplayName.LocalizedLabels.length > 0)) 75 | { 76 | edm.DisplayName = entity.DisplayName.LocalizedLabels[0].Label; 77 | if (LCID != null) 78 | entity.DisplayName.LocalizedLabels.forEach(function (label) { if (label.LanguageCode == LCID) edm.DisplayName = label.Label}); 79 | } 80 | else 81 | edm.DisplayName = edm.LogicalName; 82 | if ((entity.DisplayCollectionName.LocalizedLabels != null) && (entity.DisplayCollectionName.LocalizedLabels.length > 0)) 83 | { 84 | edm.DisplayCollectionName = entity.DisplayCollectionName.LocalizedLabels[0].Label; 85 | if (LCID != null) 86 | entity.DisplayCollectionName.LocalizedLabels.forEach(function (label) { if (label.LanguageCode == LCID) edm.DisplayCollectionName = label.Label}); 87 | } 88 | else 89 | edm.DisplayCollectionName = entity.LogicalCollectionName; 90 | edm.LogicalDisplayName = edm.DisplayName +'(' + edm.LogicalName + ')' 91 | edm.LogicalDisplayCollectionName = edm.DisplayCollectionName +'(' + edm.LogicalCollectionName + ')' 92 | list.push(edm); 93 | } 94 | ) 95 | resolve(list); 96 | }, 97 | function(e){ 98 | console.log(e) 99 | reject(e) 100 | }) 101 | }); 102 | }; -------------------------------------------------------------------------------- /JS/lib/Releases/CRMWebAPIMetadata-1.1.3.js: -------------------------------------------------------------------------------- 1 | CRMWebAPI.prototype.GetOptionSetByName = function (optionSetName) { 2 | var self = this; 3 | return new Promise(function (resolve, reject) { 4 | 5 | self.GetList('GlobalOptionSetDefinitions', 6 | {Select:['Name']}).then( 7 | function (r) 8 | { 9 | r.List.forEach(function(set) 10 | { 11 | if (set.Name == optionSetName) 12 | { 13 | self.Get('GlobalOptionSetDefinitions',set.MetadataId).then( 14 | function(res){ 15 | resolve(res); 16 | },function(err){console.log(err)} 17 | ) 18 | } 19 | } 20 | ) 21 | }, 22 | function(e){ 23 | console.log(e) 24 | reject(e) 25 | }) 26 | }); 27 | }; 28 | 29 | CRMWebAPI.prototype.GetOptionSetUserLabels = function (optionSetName) { 30 | var self = this; 31 | return new Promise(function (resolve, reject) { 32 | 33 | self.GetOptionSetByName(optionSetName).then( 34 | function (result) 35 | { 36 | var displayList = new Array(); 37 | result.Options.forEach(function (option) 38 | { 39 | var displayOption = new Object; 40 | displayOption.Value = option.Value; 41 | displayOption.Label = option.Label.UserLocalizedLabel.Label; 42 | displayList.push(displayOption); 43 | }); 44 | resolve(displayList); 45 | } 46 | , 47 | function (err) 48 | { 49 | console.log(err) 50 | reject(err); 51 | } 52 | ); 53 | }); 54 | 55 | } 56 | 57 | CRMWebAPI.prototype.GetEntityDisplayNameList = function (LCID) { 58 | var self = this; 59 | return new Promise(function (resolve, reject) { 60 | 61 | 62 | self.GetList('EntityDefinitions', 63 | {Filter:'IsPrivate eq false',Select:['MetadataId','EntitySetName','DisplayName', 64 | 'DisplayCollectionName','LogicalName','LogicalCollectionName','PrimaryIdAttribute']}).then( 65 | function (r) 66 | { 67 | var list = new Array(); 68 | r.List.forEach(function(entity) 69 | { 70 | var edm = new Object(); 71 | edm.MetadataId = entity.MetadataId; 72 | edm.EntitySetName = entity.EntitySetName; 73 | edm.LogicalName = entity.LogicalName; 74 | edm.LogicalCollectionName = entity.LogicalCollectionName; 75 | edm.PrimaryIdAttribute = entity.PrimaryIdAttribute; 76 | if ((entity.DisplayName.LocalizedLabels != null) && (entity.DisplayName.LocalizedLabels.length > 0)) 77 | { 78 | edm.DisplayName = entity.DisplayName.LocalizedLabels[0].Label; 79 | if (LCID != null) 80 | entity.DisplayName.LocalizedLabels.forEach(function (label) { if (label.LanguageCode == LCID) edm.DisplayName = label.Label}); 81 | } 82 | else 83 | edm.DisplayName = edm.LogicalName; 84 | if ((entity.DisplayCollectionName.LocalizedLabels != null) && (entity.DisplayCollectionName.LocalizedLabels.length > 0)) 85 | { 86 | edm.DisplayCollectionName = entity.DisplayCollectionName.LocalizedLabels[0].Label; 87 | if (LCID != null) 88 | entity.DisplayCollectionName.LocalizedLabels.forEach(function (label) { if (label.LanguageCode == LCID) edm.DisplayCollectionName = label.Label}); 89 | } 90 | else 91 | edm.DisplayCollectionName = entity.LogicalCollectionName; 92 | edm.LogicalDisplayName = edm.DisplayName +'(' + edm.LogicalName + ')' 93 | edm.LogicalDisplayCollectionName = edm.DisplayCollectionName +'(' + edm.LogicalCollectionName + ')' 94 | list.push(edm); 95 | } 96 | ) 97 | resolve(list); 98 | }, 99 | function(e){ 100 | console.log(e) 101 | reject(e) 102 | }) 103 | }); 104 | }; -------------------------------------------------------------------------------- /JS/lib/Releases/CRMWebAPIMetadata-1.2.0.js: -------------------------------------------------------------------------------- 1 | CRMWebAPI.prototype.GetOptionSetByName = function (optionSetName) { 2 | var self = this; 3 | return new Promise(function (resolve, reject) { 4 | 5 | self.GetList('GlobalOptionSetDefinitions', 6 | {Select:['Name']}).then( 7 | function (r) 8 | { 9 | r.List.forEach(function(set) 10 | { 11 | if (set.Name == optionSetName) 12 | { 13 | self.Get('GlobalOptionSetDefinitions',set.MetadataId).then( 14 | function(res){ 15 | resolve(res); 16 | },function(err){console.log(err)} 17 | ) 18 | } 19 | } 20 | ) 21 | }, 22 | function(e){ 23 | console.log(e) 24 | reject(e) 25 | }) 26 | }); 27 | }; 28 | 29 | CRMWebAPI.prototype.GetOptionSetUserLabels = function (optionSetName) { 30 | var self = this; 31 | return new Promise(function (resolve, reject) { 32 | 33 | self.GetOptionSetByName(optionSetName).then( 34 | function (result) 35 | { 36 | var displayList = new Array(); 37 | result.Options.forEach(function (option) 38 | { 39 | var displayOption = new Object; 40 | displayOption.Value = option.Value; 41 | displayOption.Label = option.Label.UserLocalizedLabel.Label; 42 | displayList.push(displayOption); 43 | }); 44 | resolve(displayList); 45 | } 46 | , 47 | function (err) 48 | { 49 | console.log(err) 50 | reject(err); 51 | } 52 | ); 53 | }); 54 | 55 | } 56 | 57 | CRMWebAPI.prototype.GetEntityDisplayNameList = function (LCID) { 58 | var self = this; 59 | return new Promise(function (resolve, reject) { 60 | 61 | 62 | self.GetList('EntityDefinitions', 63 | {Filter:'IsPrivate eq false',Select:['MetadataId','EntitySetName','DisplayName', 64 | 'DisplayCollectionName','LogicalName','LogicalCollectionName','PrimaryIdAttribute']}).then( 65 | function (r) 66 | { 67 | var list = new Array(); 68 | r.List.forEach(function(entity) 69 | { 70 | var edm = new Object(); 71 | edm.MetadataId = entity.MetadataId; 72 | edm.EntitySetName = entity.EntitySetName; 73 | edm.LogicalName = entity.LogicalName; 74 | edm.LogicalCollectionName = entity.LogicalCollectionName; 75 | edm.PrimaryIdAttribute = entity.PrimaryIdAttribute; 76 | if ((entity.DisplayName.LocalizedLabels != null) && (entity.DisplayName.LocalizedLabels.length > 0)) 77 | { 78 | edm.DisplayName = entity.DisplayName.LocalizedLabels[0].Label; 79 | if (LCID != null) 80 | entity.DisplayName.LocalizedLabels.forEach(function (label) { if (label.LanguageCode == LCID) edm.DisplayName = label.Label}); 81 | } 82 | else 83 | edm.DisplayName = edm.LogicalName; 84 | if ((entity.DisplayCollectionName.LocalizedLabels != null) && (entity.DisplayCollectionName.LocalizedLabels.length > 0)) 85 | { 86 | edm.DisplayCollectionName = entity.DisplayCollectionName.LocalizedLabels[0].Label; 87 | if (LCID != null) 88 | entity.DisplayCollectionName.LocalizedLabels.forEach(function (label) { if (label.LanguageCode == LCID) edm.DisplayCollectionName = label.Label}); 89 | } 90 | else 91 | edm.DisplayCollectionName = entity.LogicalCollectionName; 92 | edm.LogicalDisplayName = edm.DisplayName +'(' + edm.LogicalName + ')' 93 | edm.LogicalDisplayCollectionName = edm.DisplayCollectionName +'(' + edm.LogicalCollectionName + ')' 94 | list.push(edm); 95 | } 96 | ) 97 | resolve(list); 98 | }, 99 | function(e){ 100 | console.log(e) 101 | reject(e) 102 | }) 103 | }); 104 | }; 105 | 106 | 107 | CRMWebAPI.prototype.GetAttributeDisplayNameList = function (entityID,LCID) { 108 | var self = this; 109 | return new Promise(function (resolve, reject) { 110 | 111 | 112 | self.GetList('EntityDefinitions('+ entityID.toString() + ')/Attributes', 113 | {Select:['MetadataId','DisplayName','LogicalName','AttributeType','IsPrimaryId']}).then( 114 | function (r) 115 | { 116 | var list = new Array(); 117 | r.List.forEach(function(attrib) 118 | { 119 | var edm = new Object(); 120 | edm.MetadataId = attrib.MetadataId; 121 | edm.LogicalName = attrib.LogicalName; 122 | edm.IsPrimaryId = attrib.IsPrimaryId; 123 | if ((attrib.DisplayName.LocalizedLabels != null) && (attrib.DisplayName.LocalizedLabels.length > 0)) 124 | { 125 | edm.DisplayName = attrib.DisplayName.LocalizedLabels[0].Label; 126 | if (LCID != null) 127 | attrib.DisplayName.LocalizedLabels.forEach(function (label) { if (label.LanguageCode == LCID) edm.DisplayName = label.Label}); 128 | } 129 | else 130 | edm.DisplayName = edm.LogicalName; 131 | edm.LogicalDisplayName = edm.DisplayName +'(' + edm.LogicalName + ')' 132 | list.push(edm); 133 | } 134 | ) 135 | resolve(list); 136 | }, 137 | function(e){ 138 | console.log(e) 139 | reject(e) 140 | }) 141 | }); 142 | }; -------------------------------------------------------------------------------- /JS/lib/Releases/CRMWebAPIMetadata-1.2.1.js: -------------------------------------------------------------------------------- 1 | CRMWebAPI.prototype.GetOptionSetByName = function (optionSetName) { 2 | var self = this; 3 | return new Promise(function (resolve, reject) { 4 | 5 | self.GetList('GlobalOptionSetDefinitions', 6 | {Select:['Name']}).then( 7 | function (r) 8 | { 9 | r.List.forEach(function(set) 10 | { 11 | if (set.Name == optionSetName) 12 | { 13 | self.Get('GlobalOptionSetDefinitions',set.MetadataId).then( 14 | function(res){ 15 | resolve(res); 16 | },function(err){console.log(err)} 17 | ) 18 | } 19 | } 20 | ) 21 | }, 22 | function(e){ 23 | console.log(e) 24 | reject(e) 25 | }) 26 | }); 27 | }; 28 | 29 | CRMWebAPI.prototype.GetOptionSetUserLabels = function (optionSetName) { 30 | var self = this; 31 | return new Promise(function (resolve, reject) { 32 | 33 | self.GetOptionSetByName(optionSetName).then( 34 | function (result) 35 | { 36 | var displayList = new Array(); 37 | result.Options.forEach(function (option) 38 | { 39 | var displayOption = new Object; 40 | displayOption.Value = option.Value; 41 | displayOption.Label = option.Label.UserLocalizedLabel.Label; 42 | displayList.push(displayOption); 43 | }); 44 | resolve(displayList); 45 | } 46 | , 47 | function (err) 48 | { 49 | console.log(err) 50 | reject(err); 51 | } 52 | ); 53 | }); 54 | 55 | } 56 | 57 | CRMWebAPI.prototype.GetEntityDisplayNameList = function (LCID) { 58 | var self = this; 59 | return new Promise(function (resolve, reject) { 60 | 61 | 62 | self.GetList('EntityDefinitions', 63 | {Filter:'IsPrivate eq false',Select:['MetadataId','EntitySetName','DisplayName', 64 | 'DisplayCollectionName','LogicalName','LogicalCollectionName','PrimaryIdAttribute']}).then( 65 | function (r) 66 | { 67 | var list = new Array(); 68 | r.List.forEach(function(entity) 69 | { 70 | var edm = new Object(); 71 | edm.MetadataId = entity.MetadataId; 72 | edm.EntitySetName = entity.EntitySetName; 73 | edm.LogicalName = entity.LogicalName; 74 | edm.LogicalCollectionName = entity.LogicalCollectionName; 75 | edm.PrimaryIdAttribute = entity.PrimaryIdAttribute; 76 | if ((entity.DisplayName.LocalizedLabels != null) && (entity.DisplayName.LocalizedLabels.length > 0)) 77 | { 78 | edm.DisplayName = entity.DisplayName.LocalizedLabels[0].Label; 79 | if (LCID != null) 80 | entity.DisplayName.LocalizedLabels.forEach(function (label) { if (label.LanguageCode == LCID) edm.DisplayName = label.Label}); 81 | } 82 | else 83 | edm.DisplayName = edm.LogicalName; 84 | if ((entity.DisplayCollectionName.LocalizedLabels != null) && (entity.DisplayCollectionName.LocalizedLabels.length > 0)) 85 | { 86 | edm.DisplayCollectionName = entity.DisplayCollectionName.LocalizedLabels[0].Label; 87 | if (LCID != null) 88 | entity.DisplayCollectionName.LocalizedLabels.forEach(function (label) { if (label.LanguageCode == LCID) edm.DisplayCollectionName = label.Label}); 89 | } 90 | else 91 | edm.DisplayCollectionName = entity.LogicalCollectionName; 92 | edm.LogicalDisplayName = edm.DisplayName +'(' + edm.LogicalName + ')' 93 | edm.LogicalDisplayCollectionName = edm.DisplayCollectionName +'(' + edm.LogicalCollectionName + ')' 94 | list.push(edm); 95 | } 96 | ) 97 | resolve(list); 98 | }, 99 | function(e){ 100 | console.log(e) 101 | reject(e) 102 | }) 103 | }); 104 | }; 105 | 106 | 107 | CRMWebAPI.prototype.GetAttributeDisplayNameList = function (entityID,LCID) { 108 | var self = this; 109 | return new Promise(function (resolve, reject) { 110 | 111 | 112 | self.GetList('EntityDefinitions('+ entityID.toString() + ')/Attributes', 113 | {Filter:'((IsValidForRead eq true) and (AttributeOf eq null))',Select:['MetadataId','DisplayName','LogicalName','AttributeType','IsPrimaryId']}).then( 114 | function (r) 115 | { 116 | var list = new Array(); 117 | r.List.forEach(function(attrib) 118 | { 119 | var edm = new Object(); 120 | edm.MetadataId = attrib.MetadataId; 121 | edm.LogicalName = attrib.LogicalName; 122 | edm.IsPrimaryId = attrib.IsPrimaryId; 123 | edm.AttributeType = attrib.AttributeType; 124 | if (attrib.AttributeType === "Lookup" || attrib.AttributeType === "Customer" || attrib.AttributeType === "Owner") 125 | edm.ODataLogicalName = "_" + attrib.LogicalName + "_value"; 126 | else 127 | edm.ODataLogicalName = attrib.LogicalName; 128 | 129 | if ((attrib.DisplayName.LocalizedLabels != null) && (attrib.DisplayName.LocalizedLabels.length > 0)) 130 | { 131 | edm.DisplayName = attrib.DisplayName.LocalizedLabels[0].Label; 132 | if (LCID != null) 133 | attrib.DisplayName.LocalizedLabels.forEach(function (label) { if (label.LanguageCode == LCID) edm.DisplayName = label.Label}); 134 | } 135 | else 136 | edm.DisplayName = edm.LogicalName; 137 | edm.LogicalDisplayName = edm.DisplayName +'(' + edm.LogicalName + ')' 138 | list.push(edm); 139 | } 140 | ) 141 | resolve(list); 142 | }, 143 | function(e){ 144 | console.log(e) 145 | reject(e) 146 | }) 147 | }); 148 | }; -------------------------------------------------------------------------------- /JS/lib/Releases/CRMWebAPIMetadata-1.3.0.js: -------------------------------------------------------------------------------- 1 | CRMWebAPI.prototype.GetOptionSetByName = function (optionSetName) { 2 | var self = this; 3 | return new Promise(function (resolve, reject) { 4 | 5 | self.GetList('GlobalOptionSetDefinitions', 6 | {Select:['Name']}).then( 7 | function (r) 8 | { 9 | r.List.forEach(function(set) 10 | { 11 | if (set.Name == optionSetName) 12 | { 13 | self.Get('GlobalOptionSetDefinitions',set.MetadataId).then( 14 | function(res){ 15 | resolve(res); 16 | },function(err){console.log(err)} 17 | ) 18 | } 19 | } 20 | ) 21 | }, 22 | function(e){ 23 | console.log(e) 24 | reject(e) 25 | }) 26 | }); 27 | }; 28 | 29 | CRMWebAPI.prototype.GetOptionSetUserLabels = function (optionSetName) { 30 | var self = this; 31 | return new Promise(function (resolve, reject) { 32 | 33 | self.GetOptionSetByName(optionSetName).then( 34 | function (result) 35 | { 36 | var displayList = new Array(); 37 | result.Options.forEach(function (option) 38 | { 39 | var displayOption = new Object; 40 | displayOption.Value = option.Value; 41 | displayOption.Label = option.Label.UserLocalizedLabel.Label; 42 | displayList.push(displayOption); 43 | }); 44 | resolve(displayList); 45 | } 46 | , 47 | function (err) 48 | { 49 | console.log(err) 50 | reject(err); 51 | } 52 | ); 53 | }); 54 | 55 | } 56 | 57 | CRMWebAPI.prototype.GetEntityDisplayNameList = function (LCID) { 58 | var self = this; 59 | return new Promise(function (resolve, reject) { 60 | 61 | 62 | self.GetList('EntityDefinitions', 63 | {Filter:'IsPrivate eq false',Select:['MetadataId','EntitySetName','DisplayName', 64 | 'DisplayCollectionName','LogicalName','LogicalCollectionName','PrimaryIdAttribute']}).then( 65 | function (r) 66 | { 67 | var list = new Array(); 68 | r.List.forEach(function(entity) 69 | { 70 | var edm = new Object(); 71 | edm.MetadataId = entity.MetadataId; 72 | edm.EntitySetName = entity.EntitySetName; 73 | edm.LogicalName = entity.LogicalName; 74 | edm.LogicalCollectionName = entity.LogicalCollectionName; 75 | edm.PrimaryIdAttribute = entity.PrimaryIdAttribute; 76 | if ((entity.DisplayName.LocalizedLabels != null) && (entity.DisplayName.LocalizedLabels.length > 0)) 77 | { 78 | edm.DisplayName = entity.DisplayName.LocalizedLabels[0].Label; 79 | if (LCID != null) 80 | entity.DisplayName.LocalizedLabels.forEach(function (label) { if (label.LanguageCode == LCID) edm.DisplayName = label.Label}); 81 | } 82 | else 83 | edm.DisplayName = edm.LogicalName; 84 | if ((entity.DisplayCollectionName.LocalizedLabels != null) && (entity.DisplayCollectionName.LocalizedLabels.length > 0)) 85 | { 86 | edm.DisplayCollectionName = entity.DisplayCollectionName.LocalizedLabels[0].Label; 87 | if (LCID != null) 88 | entity.DisplayCollectionName.LocalizedLabels.forEach(function (label) { if (label.LanguageCode == LCID) edm.DisplayCollectionName = label.Label}); 89 | } 90 | else 91 | edm.DisplayCollectionName = entity.LogicalCollectionName; 92 | edm.LogicalDisplayName = edm.DisplayName +'(' + edm.LogicalName + ')' 93 | edm.LogicalDisplayCollectionName = edm.DisplayCollectionName +'(' + edm.LogicalCollectionName + ')' 94 | list.push(edm); 95 | } 96 | ) 97 | resolve(list); 98 | }, 99 | function(e){ 100 | console.log(e) 101 | reject(e) 102 | }) 103 | }); 104 | }; 105 | 106 | 107 | CRMWebAPI.prototype.GetAttributeDisplayNameList = function (entityID,LCID) { 108 | var self = this; 109 | return new Promise(function (resolve, reject) { 110 | 111 | 112 | self.GetList('EntityDefinitions('+ entityID.toString() + ')/Attributes', 113 | {Filter:'((IsValidForRead eq true) and (AttributeOf eq null))',Select:['MetadataId','DisplayName','LogicalName','SchemaName','AttributeType','IsPrimaryId']}).then( 114 | function (r) 115 | { 116 | var list = new Array(); 117 | r.List.forEach(function(attrib) 118 | { 119 | var edm = new Object(); 120 | edm.MetadataId = attrib.MetadataId; 121 | edm.LogicalName = attrib.LogicalName; 122 | edm.SchemaName = attrib.SchemaName; 123 | edm.IsPrimaryId = attrib.IsPrimaryId; 124 | edm.AttributeType = attrib.AttributeType; 125 | if (attrib.AttributeType === "Lookup" || attrib.AttributeType === "Customer" || attrib.AttributeType === "Owner") 126 | edm.ODataLogicalName = "_" + attrib.LogicalName + "_value"; 127 | else 128 | edm.ODataLogicalName = attrib.LogicalName; 129 | 130 | if ((attrib.DisplayName.LocalizedLabels != null) && (attrib.DisplayName.LocalizedLabels.length > 0)) 131 | { 132 | edm.DisplayName = attrib.DisplayName.LocalizedLabels[0].Label; 133 | if (LCID != null) 134 | attrib.DisplayName.LocalizedLabels.forEach(function (label) { if (label.LanguageCode == LCID) edm.DisplayName = label.Label}); 135 | } 136 | else 137 | edm.DisplayName = edm.LogicalName; 138 | edm.LogicalDisplayName = edm.DisplayName +'(' + edm.LogicalName + ')' 139 | list.push(edm); 140 | } 141 | ) 142 | resolve(list); 143 | }, 144 | function(e){ 145 | console.log(e) 146 | reject(e) 147 | }) 148 | }); 149 | }; 150 | 151 | CRMWebAPI.prototype.CopyEntityAttribute = function (fromEntityID,toEntityID,fromAttributeID,attributeType,toNames) { 152 | var self = this; 153 | return new Promise(function (resolve, reject) { 154 | 155 | var ec ='EntityDefinitions('+ fromEntityID.toString() + ')/Attributes('+fromAttributeID+')'; 156 | if (attributeType == "Boolean") 157 | ec += '/Microsoft.Dynamics.CRM.BooleanAttributeMetadata'; 158 | if (attributeType == "Picklist") 159 | ec += '/Microsoft.Dynamics.CRM.PicklistAttributeMetadata'; 160 | 161 | self.Get(ec,null,{}).then( 162 | function (r) 163 | { 164 | delete r.MetadataId; 165 | if (attributeType == "Boolean" || attributeType == "Picklist") 166 | { 167 | delete r.DefaultValue; 168 | delete r.FormulaDefinition; 169 | delete r.SourceTypeMask; 170 | delete r.DefaultFormValue; 171 | } 172 | r.LogicalName = toNames.LogicalName; 173 | r.SchemaName = toNames.SchemaName; 174 | console.log(JSON.stringify(r)); 175 | 176 | self.Create('EntityDefinitions('+ fromEntityID.toString() + ')/Attributes',r).then( 177 | function (createR) 178 | { 179 | resolve(createR); 180 | }, 181 | function(errorR) 182 | { 183 | console.log(errorR) 184 | reject(errorR) 185 | } 186 | ); 187 | }, 188 | function(e){ 189 | console.log(e) 190 | reject(e) 191 | }) 192 | }); 193 | }; -------------------------------------------------------------------------------- /JS/lib/Releases/README.md: -------------------------------------------------------------------------------- 1 | # CRMWebAPI.js Releases 2 | #### 1.0.0 3 | - intial version 4 | #### 1.1.0 5 | - Added PageAction and RecordAction options to query options 6 | #### 1.2.0 7 | - all functions that take entityID remove {} that is added by Xrm.Page getEntityID so you don't have to pre-process it before passing to API 8 | #### 1.2.1 9 | - allow entity ID to be null when passed to .Get and just use collection name as passed 10 | #### 1.3.0 11 | - Added support for Expand query option 12 | 13 | # CRMWebAPIMetadata.js Releases 14 | #### 1.0.0 15 | - initial version 16 | #### 1.1.3 17 | - added support for GetEntityDisplayNameList 18 | #### 1.2.0 19 | - added support for GetAttributeDisplayNameList 20 | #### 1.2.1 21 | - added filter to GetAttributeDisplayNamelist for attributeof and no read, added ODataLogicalName to handle Owner,Customer and Lookup 22 | #### 1.3.0 23 | - Added CopyEntityAttribute function (note Boolean and Picklist types have a CRM bug) 24 | #### 1.3.1 25 | - Got CopyEntityAttribute to create Boolean and Picklists - as long as picklist isn't global - that is still outstanding 26 | #### 1.3.2 27 | - Got CopyEntityAttribute to create OptionSets pointing to global optionset values -------------------------------------------------------------------------------- /JS/tests/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Mocha Tests 5 | 6 | 7 | 8 | 9 |
10 | AccessToken: 11 | 12 | 13 |
14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /JS/tests/test.node.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var should = require('chai').should(); 3 | var CRMWebAPI = require('../lib/CRMWebAPI.js'); 4 | 5 | describe('CRMWebAPI', function() { 6 | if(process.env.CRM_ACCESS_TOKEN == undefined) { 7 | console.log('Please provide CRM_ACCESS_TOKEN environment variable. I.e.'); 8 | console.log('set CRM_ACCESS_TOKEN=213214213213'); 9 | process.exit(); 10 | } 11 | var api = new CRMWebAPI({ 12 | 'APIUrl': 'https://tr22a.crm.dynamics.com/api/data/v8.0/', 13 | 'AccessToken': process.env.CRM_ACCESS_TOKEN 14 | }); 15 | 16 | var uid1 = '7d7e3791-d5bf-e511-80df-c4346bac0574'; 17 | var uid2 = '2d60a58f-d5bf-e511-80e2-c4346bacf5c0'; 18 | var temp_user_id = ''; 19 | var op; 20 | 21 | describe('Create', function(){ 22 | it('should return GUID', function () { 23 | return api.Create('accounts', {'name': 'test'}) 24 | .then(function(r){ 25 | expect(r).to.have.length(36); 26 | expect(r).to.be.a('string'); 27 | temp_user_id = r; 28 | }, function(e){ 29 | should.not.exist(e); 30 | }) 31 | }); 32 | it('should return error', function () { 33 | return api.Create('accounts', {'sdadsad': 'sadsad'}) 34 | .then(function(r){ 35 | should.not.exist(r); 36 | }, function(e){ 37 | should.exist(e); 38 | expect(e).to.be.a('object'); 39 | }) 40 | }); 41 | }) 42 | describe('Update', function(){ 43 | it('should return same GUID', function(){ 44 | return api.Update('accounts', temp_user_id, {'name': 'testup'}, false).then(function(r){ 45 | expect(r.EntityID).to.have.length(36); 46 | expect(r.EntityID).to.be.a('string'); 47 | expect(r.EntityID).to.equal(temp_user_id); 48 | }, function(e){ 49 | should.not.exist(e); 50 | }); 51 | }); 52 | it('should return another GUID', function(){ 53 | return api.Update('accounts', temp_user_id.replace('1', '3'), {'name': 'testup'}, true).then(function(r){ 54 | expect(r.EntityID).to.have.length(36); 55 | expect(r.EntityID).to.be.a('string'); 56 | expect(r.EntityID).not.equal(temp_user_id); 57 | }, function(e){ 58 | should.not.exist(e); 59 | }); 60 | }); 61 | it('should return error', function(){ 62 | return api.Update('accounts', temp_user_id + 'adsad', {'name': 'testup'}).then(function(r){ 63 | should.not.exist(r); 64 | }, function(e){ 65 | should.exist(e); 66 | expect(e).to.be.a('object'); 67 | }); 68 | }); 69 | }); 70 | describe('Get', function(){ 71 | it('should return object', function(){ 72 | return api.Get('accounts', temp_user_id).then(function(r){ 73 | expect(r).to.be.a('object'); 74 | }, function(e){ 75 | should.not.exist(e); 76 | }); 77 | }); 78 | it('should return error', function(){ 79 | return api.Get('accounts', temp_user_id.replace('1', '0')).then(function(r){ 80 | should.not.exist(r); 81 | }, function(e){ 82 | should.exist(e); 83 | expect(e).to.be.a('object'); 84 | }); 85 | }); 86 | }); 87 | describe('Delete', function(){ 88 | it('should not return error', function(){ 89 | return api.Delete('accounts', temp_user_id).then(function(r){ 90 | expect(r).to.equal(true); 91 | }, function(e){ 92 | should.not.exist(e); 93 | }); 94 | }); 95 | it('should return error', function(){ 96 | return api.Delete('accounts', temp_user_id.replace('1', '0')).then(function(r){ 97 | should.not.exist(r); 98 | }, function(e){ 99 | should.exist(e); 100 | expect(e).to.be.a('object'); 101 | }); 102 | }); 103 | }); 104 | describe('GetCount', function(){ 105 | it('should return object', function(){ 106 | return api.GetCount('accounts').then(function(r){ 107 | expect(r).to.be.a('number'); 108 | }, function(e){ 109 | should.not.exist(e); 110 | }); 111 | }); 112 | it('should return error', function(){ 113 | return api.GetCount('accountsadwad').then(function(r){ 114 | should.not.exist(r); 115 | }, function(e){ 116 | should.exist(e); 117 | expect(e).to.be.a('object'); 118 | }); 119 | }); 120 | }); 121 | describe('GetList', function(){ 122 | it('should return more than 5001 entries', function(){ 123 | return api.GetList('accounts').then(function(r){ 124 | expect(r).to.be.a('object'); 125 | expect(r.List.length).to.be.at.least(5001); 126 | }, function(e){ 127 | should.not.exist(e); 128 | }); 129 | }); 130 | it('should return error', function(){ 131 | return api.GetList('accountsadwad').then(function(r){ 132 | should.not.exist(r); 133 | }, function(e){ 134 | should.exist(e); 135 | expect(e).to.be.a('object'); 136 | }); 137 | }); 138 | it('get opportunity for action', function(){ 139 | return api.GetList("opportunities", {"Top": "1"}).then(function(r){ 140 | expect(r).to.be.a('object'); 141 | op = r.List[0]; 142 | }); 143 | }); 144 | }); 145 | describe('Associate', function(){ 146 | it('should return success', function(){ 147 | return api.Associate('accounts', uid1, 'account_parent_account', 'accounts', uid2).then(function(r){ 148 | expect(r).to.equal(true); 149 | }, function(e){ 150 | should.not.exist(e); 151 | }); 152 | }); 153 | it('should return error', function(){ 154 | return api.Associate('accounts', uid1, 'account_parent_account_asd', 'accounts', uid2).then(function(r){ 155 | should.not.exist(r); 156 | }, function(e){ 157 | should.exist(e); 158 | expect(e).to.be.a('object'); 159 | }); 160 | }); 161 | }); 162 | describe('DeleteAssociation', function(){ 163 | it('should return success', function(){ 164 | return api.DeleteAssociation('accounts', uid1, 'account_parent_account', 'accounts', uid2).then(function(r){ 165 | expect(r).to.equal(true); 166 | }, function(e){ 167 | should.not.exist(e); 168 | }); 169 | }); 170 | it('should return error', function(){ 171 | return api.DeleteAssociation('accounts', uid1, 'account_parent_account_asd', 'accounts', uid2).then(function(r){ 172 | should.not.exist(r); 173 | }, function(e){ 174 | should.exist(e); 175 | expect(e).to.be.a('object'); 176 | }); 177 | }); 178 | }); 179 | describe('ExecuteFunction', function(){ 180 | it('should return object', function(){ 181 | return api.ExecuteFunction('WhoAmI').then(function(r){ 182 | expect(r).to.be.a('object'); 183 | }, function(e){ 184 | should.not.exist(e); 185 | }); 186 | }); 187 | it('should return error', function(){ 188 | return api.ExecuteFunction('AmIWho').then(function(r){ 189 | should.not.exist(r); 190 | }, function(e){ 191 | should.exist(e); 192 | expect(e).to.be.a('object'); 193 | }); 194 | }); 195 | }); 196 | describe('ExecuteAction', function(){ 197 | // TODO: This returns error but all about the params. Fix params to get object; 198 | it('should return object (returns error in fact)', function(){ 199 | var params = { 200 | "Target": { 201 | "opportunityid": op.opportunityid, 202 | "@odata.type": "Microsoft.Dynamics.CRM.opportunity" 203 | }, 204 | "NewProcess": null 205 | }; 206 | return api.ExecuteAction("SetProcess", params).then(function(r){ 207 | expect(r).to.be.a('object'); 208 | }, function(e){ 209 | //should.not.exist(e); // TODO: Uncomment after params fix and remove all below 210 | expect(JSON.parse(e.response).error.message).to.equal('processstage With Id = 00000000-0000-0000-0000-000000000000 Does Not Exist'); 211 | }); 212 | }); 213 | }); 214 | }); 215 | /* 216 | 217 | 218 | 219 | 220 | 221 | QUnit.test('Account', 1, function(assert){ 222 | QUnit.stop(); 223 | api.Create('accounts', {'name': 'testname'}).then(function(r){ 224 | assert.equal(r.length, 36); 225 | var id = r; 226 | 227 | api.Get('accounts', id).then(function(r){ 228 | assert.equal() 229 | }, function(e){ 230 | QUnit.start(); 231 | }); 232 | }, function(e){ 233 | QUnit.start(); 234 | }); 235 | }); 236 | */ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 David Yack 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is an API helper for working with the Common Data Service (CDS) and Dynamics 365 Web API 2 | 3 | Design goals include 4 | - Lightweight 5 | - Simple API signatures as similar as possible across languages 6 | - Integrate well with Azure Active Directory / Authentication libraries but don't bake them in 7 | - JavaScript library to work from web resource or external application 8 | 9 | 10 | There are versions of the API for .NET, JavaScript, Node, Python and PHP with Java coming soon 11 | 12 | Feedback and contributions welcome...if you are going to propose major changes open an issue first to discuss the change. 13 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xrm.tools.crmwebapi", 3 | "homepage": "https://github.com/davidyack/Xrm.Tools.CRMWebAPI", 4 | "authors": [ 5 | "XRM.Tools" 6 | ], 7 | "description": "Helper wrapper to interact with Dynamics 365 API", 8 | "main": [ 9 | "js/lib/CRMWebAPI.js" 10 | ], 11 | "moduleType": [ 12 | "es6" 13 | ], 14 | "license": "MIT", 15 | "ignore": [ 16 | "**/.*", 17 | "dotnet", 18 | "python", 19 | "php", 20 | "nodejs", 21 | "JS/lib/Releases", 22 | "node_modules", 23 | "bower_components", 24 | "test", 25 | "tests", 26 | "archive" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /dotnet/ReadMe.md: -------------------------------------------------------------------------------- 1 | 2 | Install via NuGet (https://www.nuget.org/packages/Xrm.Tools.CRMWebAPI/) 3 | 4 | Support for full .NET, .NET Core and .NET Standard projects 5 | 6 | Install-Package Xrm.Tools.CRMWebAPI 7 | Here is how to get an instance of CRMWebAPI passing an AccessToken 8 | ```` 9 | public static CRMWebAPI GetAPI() 10 | { 11 | 12 | CRMWebAPI api = new CRMWebAPI("https://orgname.api.crm.dynamics.com/api/data/v8.0/", 13 | ""); 14 | return api; 15 | 16 | } 17 | ```` 18 | Here is how to get an instance of CRMWebAPI passing an ADAL with a user and password - to understand how to get a client ID visit the walk through here https://msdn.microsoft.com/en-us/library/mt622431.aspx This requires a native application and is not supported by .NET Core 19 | 20 | ```` 21 | public static CRMWebAPI GetAPI() 22 | { 23 | string authority = "https://login.microsoftonline.com/common"; 24 | string clientId = ""; 25 | string crmBaseUrl = "https://xx.crm.dynamics.com"; 26 | 27 | var authContext = new AuthenticationContext(authority); 28 | UserCredential userCreds = new UserPasswordCredential("", ""); 29 | var result = authContext.AcquireTokenAsync(crmBaseUrl, clientId, userCreds).Result; 30 | CRMWebAPI api = new CRMWebAPI(crmBaseUrl + "/api/data/v9.0/", result.AccessToken); 31 | 32 | return api; 33 | } 34 | ```` 35 | 36 | Here is how to get an instance of CRMWebAPI passing an ADAL with a Server-to-server authentication - to understand Server-to-server authentication visit 37 | https://msdn.microsoft.com/en-us/library/mt790168.aspx 38 | ```` 39 | public async static Task GetAPI() 40 | { 41 | string authority = "https://login.microsoftonline.com/"; 42 | string clientId = ""; 43 | string crmBaseUrl = "https://xx.crm.dynamics.com"; 44 | string clientSecret = ""; 45 | string tenantID = ""; 46 | 47 | var clientcred = new ClientCredential(clientId, clientSecret); 48 | var authContext = new AuthenticationContext(authority + tenantID); 49 | var authenticationResult = await authContext.AcquireTokenAsync(crmBaseUrl, clientcred); 50 | 51 | return new CRMWebAPI(crmBaseUrl + "/api/data/v8.0/", authenticationResult.AccessToken); 52 | } 53 | ```` 54 | 55 | Here are a few simple examples 56 | ```` 57 | Task.Run(async () => 58 | { 59 | var api = GetAPI(); 60 | 61 | dynamic data = new ExpandoObject(); 62 | data.name = "test " + DateTime.Now.ToString(); 63 | 64 | Guid createdID = await api.Create("accounts", data); 65 | 66 | var retrievedObject = await api.Get("accounts", createdID, new CRMGetListOptions() { FormattedValues = true }); 67 | 68 | var retrievedObjectEx = await api.Get("accounts", createdID); 69 | 70 | dynamic updateObject = new ExpandoObject(); 71 | updateObject.name = "updated name " + DateTime.Now.ToString(); 72 | 73 | var updateResult = await api.Update("accounts", createdID, updateObject); 74 | //update with an upsert 75 | var upsertResult = await api.Update("accounts", Guid.NewGuid(), updateObject, Upsert: true); 76 | 77 | await api.Delete("accounts", upsertResult.EntityID); 78 | 79 | var results = await api.GetList("accounts", new CRMGetListOptions() { Top = 5, FormattedValues=true }); 80 | 81 | string fetchXml = ""; 82 | 83 | var fetchResults = await api.GetList("accounts", QueryOptions: new CRMGetListOptions() { FetchXml = fetchXml }); 84 | 85 | var count = await api.GetCount("accounts"); 86 | }).Wait(); 87 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.Core/Xrm.Tools.WebAPI.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp1.0 5 | true 6 | xt.snk 7 | Xrm.Tools.WebAPI 8 | Xrm.Tools.WebAPI 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.Core/Xrm.Tools.WebAPI.Core.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26228.9 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Xrm.Tools.WebAPI.Core", "Xrm.Tools.WebAPI.Core.csproj", "{34DA42DF-002F-46FE-A087-26C8B516ECB1}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xrm.Tools.WebAPI.Standard", "..\Xrm.Tools.WebAPI.Standard\Xrm.Tools.WebAPI.Standard.csproj", "{F5BACF79-BBCA-407F-A46F-00CBC9227800}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|x64 = Debug|x64 14 | Debug|x86 = Debug|x86 15 | Release|Any CPU = Release|Any CPU 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {34DA42DF-002F-46FE-A087-26C8B516ECB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {34DA42DF-002F-46FE-A087-26C8B516ECB1}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {34DA42DF-002F-46FE-A087-26C8B516ECB1}.Debug|x64.ActiveCfg = Debug|Any CPU 23 | {34DA42DF-002F-46FE-A087-26C8B516ECB1}.Debug|x64.Build.0 = Debug|Any CPU 24 | {34DA42DF-002F-46FE-A087-26C8B516ECB1}.Debug|x86.ActiveCfg = Debug|Any CPU 25 | {34DA42DF-002F-46FE-A087-26C8B516ECB1}.Debug|x86.Build.0 = Debug|Any CPU 26 | {34DA42DF-002F-46FE-A087-26C8B516ECB1}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {34DA42DF-002F-46FE-A087-26C8B516ECB1}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {34DA42DF-002F-46FE-A087-26C8B516ECB1}.Release|x64.ActiveCfg = Release|Any CPU 29 | {34DA42DF-002F-46FE-A087-26C8B516ECB1}.Release|x64.Build.0 = Release|Any CPU 30 | {34DA42DF-002F-46FE-A087-26C8B516ECB1}.Release|x86.ActiveCfg = Release|Any CPU 31 | {34DA42DF-002F-46FE-A087-26C8B516ECB1}.Release|x86.Build.0 = Release|Any CPU 32 | {F5BACF79-BBCA-407F-A46F-00CBC9227800}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {F5BACF79-BBCA-407F-A46F-00CBC9227800}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {F5BACF79-BBCA-407F-A46F-00CBC9227800}.Debug|x64.ActiveCfg = Debug|Any CPU 35 | {F5BACF79-BBCA-407F-A46F-00CBC9227800}.Debug|x64.Build.0 = Debug|Any CPU 36 | {F5BACF79-BBCA-407F-A46F-00CBC9227800}.Debug|x86.ActiveCfg = Debug|Any CPU 37 | {F5BACF79-BBCA-407F-A46F-00CBC9227800}.Debug|x86.Build.0 = Debug|Any CPU 38 | {F5BACF79-BBCA-407F-A46F-00CBC9227800}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {F5BACF79-BBCA-407F-A46F-00CBC9227800}.Release|Any CPU.Build.0 = Release|Any CPU 40 | {F5BACF79-BBCA-407F-A46F-00CBC9227800}.Release|x64.ActiveCfg = Release|Any CPU 41 | {F5BACF79-BBCA-407F-A46F-00CBC9227800}.Release|x64.Build.0 = Release|Any CPU 42 | {F5BACF79-BBCA-407F-A46F-00CBC9227800}.Release|x86.ActiveCfg = Release|Any CPU 43 | {F5BACF79-BBCA-407F-A46F-00CBC9227800}.Release|x86.Build.0 = Release|Any CPU 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | EndGlobal 49 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.Core/bin/Debug/netcoreapp1.0/Xrm.Tools.WebAPI.deps.json: -------------------------------------------------------------------------------- 1 | { 2 | "runtimeTarget": { 3 | "name": ".NETCoreApp,Version=v1.0", 4 | "signature": "" 5 | }, 6 | "compilationOptions": {}, 7 | "targets": { 8 | ".NETCoreApp,Version=v1.0": { 9 | "Xrm.Tools.WebAPI/1.0.0": { 10 | "dependencies": { 11 | "Newtonsoft.Json": "9.0.1" 12 | }, 13 | "runtime": { 14 | "Xrm.Tools.WebAPI.dll": {} 15 | } 16 | }, 17 | "Newtonsoft.Json/9.0.1": { 18 | "dependencies": { 19 | "System.Runtime.Serialization.Primitives": "4.1.1" 20 | }, 21 | "runtime": { 22 | "lib/netstandard1.0/Newtonsoft.Json.dll": { 23 | "assemblyVersion": "9.0.0.0", 24 | "fileVersion": "9.0.1.19813" 25 | } 26 | } 27 | }, 28 | "System.Runtime.Serialization.Primitives/4.1.1": { 29 | "runtime": { 30 | "lib/netstandard1.3/System.Runtime.Serialization.Primitives.dll": { 31 | "assemblyVersion": "4.1.1.0", 32 | "fileVersion": "1.0.24212.1" 33 | } 34 | } 35 | } 36 | } 37 | }, 38 | "libraries": { 39 | "Xrm.Tools.WebAPI/1.0.0": { 40 | "type": "project", 41 | "serviceable": false, 42 | "sha512": "" 43 | }, 44 | "Newtonsoft.Json/9.0.1": { 45 | "type": "package", 46 | "serviceable": true, 47 | "sha512": "sha512-U82mHQSKaIk+lpSVCbWYKNavmNH1i5xrExDEquU1i6I5pV6UMOqRnJRSlKO3cMPfcpp0RgDY+8jUXHdQ4IfXvw==", 48 | "path": "newtonsoft.json/9.0.1", 49 | "hashPath": "newtonsoft.json.9.0.1.nupkg.sha512" 50 | }, 51 | "System.Runtime.Serialization.Primitives/4.1.1": { 52 | "type": "package", 53 | "serviceable": true, 54 | "sha512": "sha512-HZ6Du5QrTG8MNJbf4e4qMO3JRAkIboGT5Fk804uZtg3Gq516S7hAqTm2UZKUHa7/6HUGdVy3AqMQKbns06G/cg==", 55 | "path": "system.runtime.serialization.primitives/4.1.1", 56 | "hashPath": "system.runtime.serialization.primitives.4.1.1.nupkg.sha512" 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.Core/xt.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidyack/Xrm.Tools.CRMWebAPI/1d89792291b435cf659932bdc8e54662c7ddf4b7/dotnet/Xrm.Tools.WebAPI.Core/xt.snk -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.NuGet/NuGet.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.NuGet/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidyack/Xrm.Tools.CRMWebAPI/1d89792291b435cf659932bdc8e54662c7ddf4b7/dotnet/Xrm.Tools.WebAPI.NuGet/NuGet.exe -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.NuGet/NuGet.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidyack/Xrm.Tools.CRMWebAPI/1d89792291b435cf659932bdc8e54662c7ddf4b7/dotnet/Xrm.Tools.WebAPI.NuGet/NuGet.log -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.NuGet/NuGetPackage.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [switch]$Publish 3 | ) 4 | 5 | $ErrorActionPreference = "Stop" 6 | $global:ExitCode = 1 7 | 8 | function Write-Log { 9 | 10 | #region Parameters 11 | 12 | [cmdletbinding()] 13 | Param( 14 | [Parameter(ValueFromPipeline=$true)] 15 | [array] $Messages, 16 | 17 | [Parameter()] [ValidateSet("Error", "Warn", "Info")] 18 | [string] $Level = "Info", 19 | 20 | [Parameter()] 21 | [Switch] $NoConsoleOut = $false, 22 | 23 | [Parameter()] 24 | [String] $ForegroundColor = 'White', 25 | 26 | [Parameter()] [ValidateRange(1,30)] 27 | [Int16] $Indent = 0, 28 | 29 | [Parameter()] 30 | [IO.FileInfo] $Path = ".\NuGet.log", 31 | 32 | [Parameter()] 33 | [Switch] $Clobber, 34 | 35 | [Parameter()] 36 | [String] $EventLogName, 37 | 38 | [Parameter()] 39 | [String] $EventSource, 40 | 41 | [Parameter()] 42 | [Int32] $EventID = 1 43 | 44 | ) 45 | 46 | #endregion 47 | 48 | Begin {} 49 | 50 | Process { 51 | 52 | $ErrorActionPreference = "Continue" 53 | 54 | if ($Messages.Length -gt 0) { 55 | try { 56 | foreach($m in $Messages) { 57 | if ($NoConsoleOut -eq $false) { 58 | switch ($Level) { 59 | 'Error' { 60 | Write-Error $m -ErrorAction SilentlyContinue 61 | Write-Host ('{0}{1}' -f (" " * $Indent), $m) -ForegroundColor Red 62 | } 63 | 'Warn' { 64 | Write-Warning $m 65 | } 66 | 'Info' { 67 | Write-Host ('{0}{1}' -f (" " * $Indent), $m) -ForegroundColor $ForegroundColor 68 | } 69 | } 70 | } 71 | 72 | if ($m.Trim().Length -gt 0) { 73 | $msg = '{0}{1} [{2}] : {3}' -f (" " * $Indent), (Get-Date -Format "yyyy-MM-dd HH:mm:ss"), $Level.ToUpper(), $m 74 | 75 | if ($Clobber) { 76 | $msg | Out-File -FilePath $Path -Force 77 | } else { 78 | $msg | Out-File -FilePath $Path -Append 79 | } 80 | } 81 | 82 | if ($EventLogName) { 83 | 84 | if (-not $EventSource) { 85 | $EventSource = ([IO.FileInfo] $MyInvocation.ScriptName).Name 86 | } 87 | 88 | if(-not [Diagnostics.EventLog]::SourceExists($EventSource)) { 89 | [Diagnostics.EventLog]::CreateEventSource($EventSource, $EventLogName) 90 | } 91 | 92 | $log = New-Object System.Diagnostics.EventLog 93 | $log.set_log($EventLogName) 94 | $log.set_source($EventSource) 95 | 96 | switch ($Level) { 97 | "Error" { $log.WriteEntry($Message, 'Error', $EventID) } 98 | "Warn" { $log.WriteEntry($Message, 'Warning', $EventID) } 99 | "Info" { $log.WriteEntry($Message, 'Information', $EventID) } 100 | } 101 | } 102 | } 103 | } 104 | catch { 105 | throw "Failed to create log entry in: '$Path'. The error was: '$_'." 106 | } 107 | } 108 | } 109 | 110 | End {} 111 | 112 | <# 113 | .SYNOPSIS 114 | Writes logging information to screen and log file simultaneously. 115 | 116 | .DESCRIPTION 117 | Writes logging information to screen and log file simultaneously. Supports multiple log levels. 118 | 119 | .PARAMETER Messages 120 | The messages to be logged. 121 | 122 | .PARAMETER Level 123 | The type of message to be logged. 124 | 125 | .PARAMETER NoConsoleOut 126 | Specifies to not display the message to the console. 127 | 128 | .PARAMETER ConsoleForeground 129 | Specifies what color the text should be be displayed on the console. Ignored when switch 'NoConsoleOut' is specified. 130 | 131 | .PARAMETER Indent 132 | The number of spaces to indent the line in the log file. 133 | 134 | .PARAMETER Path 135 | The log file path. 136 | 137 | .PARAMETER Clobber 138 | Existing log file is deleted when this is specified. 139 | 140 | .PARAMETER EventLogName 141 | The name of the system event log, e.g. 'Application'. 142 | 143 | .PARAMETER EventSource 144 | The name to appear as the source attribute for the system event log entry. This is ignored unless 'EventLogName' is specified. 145 | 146 | .PARAMETER EventID 147 | The ID to appear as the event ID attribute for the system event log entry. This is ignored unless 'EventLogName' is specified. 148 | 149 | .EXAMPLE 150 | PS C:\> Write-Log -Message "It's all good!" -Path C:\MyLog.log -Clobber -EventLogName 'Application' 151 | 152 | .EXAMPLE 153 | PS C:\> Write-Log -Message "Oops, not so good!" -Level Error -EventID 3 -Indent 2 -EventLogName 'Application' -EventSource "My Script" 154 | 155 | .INPUTS 156 | System.String 157 | 158 | .OUTPUTS 159 | No output. 160 | 161 | .NOTES 162 | Revision History: 163 | 2011-03-10 : Andy Arismendi - Created. 164 | #> 165 | } 166 | 167 | function Create-Process() { 168 | param([string] $fileName, [string] $arguments) 169 | 170 | $pinfo = New-Object System.Diagnostics.ProcessStartInfo 171 | $pinfo.RedirectStandardError = $true 172 | $pinfo.RedirectStandardOutput = $true 173 | $pinfo.UseShellExecute = $false 174 | $pinfo.FileName = $fileName 175 | $pinfo.Arguments = $arguments 176 | 177 | $p = New-Object System.Diagnostics.Process 178 | $p.StartInfo = $pinfo 179 | 180 | return $p 181 | } 182 | 183 | function HandlePublishError { 184 | param([string] $ErrorMessage) 185 | 186 | # Run NuGet Setup 187 | $encodedMessage = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($ErrorMessage)) 188 | $setupTask = Start-Process PowerShell.exe "-ExecutionPolicy Unrestricted -File .\NuGetSetup.ps1 -Url $url -Base64EncodedMessage $encodedMessage" -Wait -PassThru 189 | 190 | #Write-Log ("NuGet Setup Task Exit Code: " + $setupTask.ExitCode) 191 | 192 | if ($setupTask.ExitCode -eq 0) { 193 | # Try to push package again 194 | $publishTask = Create-Process .\NuGet.exe ("push " + $_.Name + " -Source " + $url) 195 | $publishTask.Start() | Out-Null 196 | $publishTask.WaitForExit() 197 | 198 | $output = ($publishTask.StandardOutput.ReadToEnd() -Split '[\r\n]') |? {$_} 199 | $error = (($publishTask.StandardError.ReadToEnd() -Split '[\r\n]') |? {$_}) 200 | Write-Log $output 201 | Write-Log $error Error 202 | 203 | if ($publishTask.ExitCode -eq 0) { 204 | $global:ExitCode = 0 205 | } 206 | } 207 | elseif ($setupTask.ExitCode -eq 2) { 208 | $global:ExitCode = 2 209 | } 210 | else { 211 | $global:ExitCode = 0 212 | } 213 | } 214 | 215 | function Publish { 216 | 217 | Write-Log " " 218 | Write-Log "Publishing package..." -ForegroundColor Green 219 | 220 | # Get nuget config 221 | [xml]$nugetConfig = Get-Content .\NuGet.Config 222 | 223 | $nugetConfig.configuration.packageSources.add | ForEach-Object { 224 | $url = $_.value 225 | 226 | Write-Log "Repository Url: $url" 227 | Write-Log " " 228 | 229 | Get-ChildItem *.nupkg | Where-Object { $_.Name.EndsWith(".symbols.nupkg") -eq $false } | ForEach-Object { 230 | 231 | # Try to push package 232 | $task = Create-Process .\NuGet.exe ("push " + $_.Name + " -Source " + $url) 233 | $task.Start() | Out-Null 234 | $task.WaitForExit() 235 | 236 | $output = ($task.StandardOutput.ReadToEnd() -Split '[\r\n]') |? { $_ } 237 | $error = ($task.StandardError.ReadToEnd() -Split '[\r\n]') |? { $_ } 238 | Write-Log $output 239 | Write-Log $error Error 240 | 241 | if ($task.ExitCode -gt 0) { 242 | HandlePublishError -ErrorMessage $error 243 | #Write-Log ("HandlePublishError() Exit Code: " + $global:ExitCode) 244 | } 245 | else { 246 | $global:ExitCode = 0 247 | } 248 | } 249 | } 250 | } 251 | 252 | Write-Log " " 253 | Write-Log "NuGet Packager 2.0.3" -ForegroundColor Yellow 254 | 255 | # Make sure the nuget executable is writable 256 | Set-ItemProperty NuGet.exe -Name IsReadOnly -Value $false 257 | 258 | # Make sure the nupkg files are writeable and create backup 259 | if (Test-Path *.nupkg) { 260 | Set-ItemProperty *.nupkg -Name IsReadOnly -Value $false 261 | 262 | Write-Log " " 263 | Write-Log "Creating backup..." -ForegroundColor Green 264 | 265 | Get-ChildItem *.nupkg | ForEach-Object { 266 | Move-Item $_.Name ($_.Name + ".bak") -Force 267 | Write-Log ("Renamed " + $_.Name + " to " + $_.Name + ".bak") 268 | } 269 | } 270 | 271 | Write-Log " " 272 | Write-Log "Updating NuGet..." -ForegroundColor Green 273 | Write-Log (Invoke-Command {.\NuGet.exe update -Self} -ErrorAction Stop) 274 | 275 | Write-Log " " 276 | Write-Log "Creating package..." -ForegroundColor Green 277 | 278 | # Create symbols package if any .pdb files are located in the lib folder 279 | If ((Get-ChildItem *.pdb -Path .\lib -Recurse).Count -gt 0) { 280 | $packageTask = Create-Process .\NuGet.exe ("pack Package.nuspec -Symbol -Verbosity Detailed") 281 | $packageTask.Start() | Out-Null 282 | $packageTask.WaitForExit() 283 | 284 | $output = ($packageTask.StandardOutput.ReadToEnd() -Split '[\r\n]') |? {$_} 285 | $error = (($packageTask.StandardError.ReadToEnd() -Split '[\r\n]') |? {$_}) 286 | Write-Log $output 287 | Write-Log $error Error 288 | 289 | $global:ExitCode = $packageTask.ExitCode 290 | } 291 | Else { 292 | $packageTask = Create-Process .\NuGet.exe ("pack Package.nuspec -Verbosity Detailed") 293 | $packageTask.Start() | Out-Null 294 | $packageTask.WaitForExit() 295 | 296 | $output = ($packageTask.StandardOutput.ReadToEnd() -Split '[\r\n]') |? {$_} 297 | $error = (($packageTask.StandardError.ReadToEnd() -Split '[\r\n]') |? {$_}) 298 | Write-Log $output 299 | Write-Log $error Error 300 | 301 | $global:ExitCode = $packageTask.ExitCode 302 | } 303 | 304 | # Check if package should be published 305 | if ($Publish -and $global:ExitCode -eq 0) { 306 | Publish 307 | } 308 | 309 | Write-Log " " 310 | Write-Log "Exit Code: $global:ExitCode" -ForegroundColor Gray 311 | 312 | $host.SetShouldExit($global:ExitCode) 313 | Exit $global:ExitCode -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.NuGet/NuGetSetup.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$Url, 3 | [string]$Base64EncodedMessage 4 | ) 5 | 6 | $ErrorActionPreference = "Stop" 7 | $ExitCode = 1 8 | 9 | function Write-Log { 10 | 11 | #region Parameters 12 | 13 | [cmdletbinding()] 14 | Param( 15 | [Parameter(ValueFromPipeline=$true)] 16 | [array] $Messages, 17 | 18 | [Parameter()] [ValidateSet("Error", "Warn", "Info")] 19 | [string] $Level = "Info", 20 | 21 | [Parameter()] 22 | [Switch] $NoConsoleOut = $false, 23 | 24 | [Parameter()] 25 | [String] $ForegroundColor = 'White', 26 | 27 | [Parameter()] [ValidateRange(1,30)] 28 | [Int16] $Indent = 0, 29 | 30 | [Parameter()] 31 | [IO.FileInfo] $Path = ".\NuGet.log", 32 | 33 | [Parameter()] 34 | [Switch] $Clobber, 35 | 36 | [Parameter()] 37 | [String] $EventLogName, 38 | 39 | [Parameter()] 40 | [String] $EventSource, 41 | 42 | [Parameter()] 43 | [Int32] $EventID = 1 44 | 45 | ) 46 | 47 | #endregion 48 | 49 | Begin {} 50 | 51 | Process { 52 | 53 | $ErrorActionPreference = "Continue" 54 | 55 | if ($Messages.Length -gt 0) { 56 | try { 57 | foreach($m in $Messages) { 58 | if ($NoConsoleOut -eq $false) { 59 | switch ($Level) { 60 | 'Error' { 61 | Write-Error $m -ErrorAction SilentlyContinue 62 | Write-Host ('{0}{1}' -f (" " * $Indent), $m) -ForegroundColor Red 63 | } 64 | 'Warn' { 65 | Write-Warning $m 66 | } 67 | 'Info' { 68 | Write-Host ('{0}{1}' -f (" " * $Indent), $m) -ForegroundColor $ForegroundColor 69 | } 70 | } 71 | } 72 | 73 | if ($m.Trim().Length -gt 0) { 74 | $msg = '{0}{1} [{2}] : {3}' -f (" " * $Indent), (Get-Date -Format "yyyy-MM-dd HH:mm:ss"), $Level.ToUpper(), $m 75 | 76 | if ($Clobber) { 77 | $msg | Out-File -FilePath $Path -Force 78 | } else { 79 | $msg | Out-File -FilePath $Path -Append 80 | } 81 | } 82 | 83 | if ($EventLogName) { 84 | 85 | if (-not $EventSource) { 86 | $EventSource = ([IO.FileInfo] $MyInvocation.ScriptName).Name 87 | } 88 | 89 | if(-not [Diagnostics.EventLog]::SourceExists($EventSource)) { 90 | [Diagnostics.EventLog]::CreateEventSource($EventSource, $EventLogName) 91 | } 92 | 93 | $log = New-Object System.Diagnostics.EventLog 94 | $log.set_log($EventLogName) 95 | $log.set_source($EventSource) 96 | 97 | switch ($Level) { 98 | "Error" { $log.WriteEntry($Message, 'Error', $EventID) } 99 | "Warn" { $log.WriteEntry($Message, 'Warning', $EventID) } 100 | "Info" { $log.WriteEntry($Message, 'Information', $EventID) } 101 | } 102 | } 103 | } 104 | } 105 | catch { 106 | throw "Failed to create log entry in: '$Path'. The error was: '$_'." 107 | } 108 | } 109 | } 110 | 111 | End {} 112 | 113 | <# 114 | .SYNOPSIS 115 | Writes logging information to screen and log file simultaneously. 116 | 117 | .DESCRIPTION 118 | Writes logging information to screen and log file simultaneously. Supports multiple log levels. 119 | 120 | .PARAMETER Messages 121 | The messages to be logged. 122 | 123 | .PARAMETER Level 124 | The type of message to be logged. 125 | 126 | .PARAMETER NoConsoleOut 127 | Specifies to not display the message to the console. 128 | 129 | .PARAMETER ConsoleForeground 130 | Specifies what color the text should be be displayed on the console. Ignored when switch 'NoConsoleOut' is specified. 131 | 132 | .PARAMETER Indent 133 | The number of spaces to indent the line in the log file. 134 | 135 | .PARAMETER Path 136 | The log file path. 137 | 138 | .PARAMETER Clobber 139 | Existing log file is deleted when this is specified. 140 | 141 | .PARAMETER EventLogName 142 | The name of the system event log, e.g. 'Application'. 143 | 144 | .PARAMETER EventSource 145 | The name to appear as the source attribute for the system event log entry. This is ignored unless 'EventLogName' is specified. 146 | 147 | .PARAMETER EventID 148 | The ID to appear as the event ID attribute for the system event log entry. This is ignored unless 'EventLogName' is specified. 149 | 150 | .EXAMPLE 151 | PS C:\> Write-Log -Message "It's all good!" -Path C:\MyLog.log -Clobber -EventLogName 'Application' 152 | 153 | .EXAMPLE 154 | PS C:\> Write-Log -Message "Oops, not so good!" -Level Error -EventID 3 -Indent 2 -EventLogName 'Application' -EventSource "My Script" 155 | 156 | .INPUTS 157 | System.String 158 | 159 | .OUTPUTS 160 | No output. 161 | 162 | .NOTES 163 | Revision History: 164 | 2011-03-10 : Andy Arismendi - Created. 165 | #> 166 | } 167 | 168 | $choices = [System.Management.Automation.Host.ChoiceDescription[]]( 169 | (New-Object System.Management.Automation.Host.ChoiceDescription "&Add API Key","Add an API Key for this URL"), 170 | (New-Object System.Management.Automation.Host.ChoiceDescription "&Skip","Skip pushing to this URL")) 171 | 172 | Write-Output "" 173 | Write-Log "Invalid API key for this repository URL, or there is a version conflict" Warn 174 | 175 | If ($Base64EncodedMessage) { 176 | Write-Warning ([System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($Base64EncodedMessage))) 177 | } 178 | 179 | $firstAnswer = $Host.UI.PromptForChoice(("Would you like to try adding an API key for " + $Url + "?"), "", $choices, (1)) 180 | 181 | if ($firstAnswer -eq 0) { 182 | $fields = new-object "System.Collections.ObjectModel.Collection``1[[System.Management.Automation.Host.FieldDescription]]" 183 | 184 | $f = New-Object System.Management.Automation.Host.FieldDescription "API Key for $Url" 185 | $f.SetParameterType( [System.Security.SecureString] ) 186 | $f.HelpMessage = "Please enter API Key for $Url" 187 | $f.Label = "&API Key for $Url" 188 | 189 | $fields.Add($f) 190 | 191 | $results = $Host.UI.Prompt( "Add API Key", "", $fields ) 192 | 193 | $pass = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($results["API Key for $Url"])) 194 | 195 | # Add API Key to config file 196 | Write-Log (.\NuGet.exe setApiKey $pass -Source $Url) 197 | 198 | if ($LASTEXITCODE -le 0) { 199 | $ExitCode = 0 200 | } 201 | } 202 | else { 203 | Write-Log "Skipping..." 204 | $ExitCode = 2 205 | } 206 | 207 | $host.SetShouldExit($ExitCode) 208 | Exit $ExitCode -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.NuGet/Package.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Xrm.Tools.CRMWebAPI 5 | 1.0.24 6 | Xrm.Tools.CRMWebAPI 7 | DavidYack 8 | 9 | 10 | This is an API helper for working with the Common Data Service (CDS) and Dynamics 365 Web API 11 | 12 | 13 | 14 | 1.0.0 Initial release 15 | 1.0.1 Cleanup of the API, more comments 16 | 1.0.2 removed JToken from public APIs 17 | 1.0.3 added uwp binary 18 | 1.0.4 fixed bug in ExecuteFunction, added support for Formatted Values 19 | 1.0.5 allow network credentials to be optional for on-prem 20 | 1.0.6 added Metadata Extension methods 21 | 1.0.7 added Expand support to Query Options 22 | 1.0.8 fixed references to System.Net.Http 23 | 1.0.9 added dependency for System.Net.Http.Formatting 24 | 1.0.10 Fixed issue if Select and Orderby were both used 25 | 1.0.11 Improved contents of exception messages 26 | 1.0.12 Fixed issue with Upsert with alternate key 27 | 1.0.13 Added .net core assembly support 28 | 1.0.14 fixed target file for netcore in nuget spec 29 | 1.0.15 fixed target file for netcore in nuget spec 30 | 1.0.16 added .net standard support, fixed return of ID with non lower service url 31 | 1.0.17 fixed ExecuteFunction serialization of object parameters, 32 | GetList by type honor formatted values option 33 | 1.0.18 added support for Entity Change Tracking 34 | 1.0.19 Fixed FetchXML when other params, fix for mixed case org url, Config as a param 35 | 1.0.20 Fixed parsing of entityid on create, added aggregate support 36 | 1.0.21 Removed full framework version of nuget in favor of .net standard 37 | 1.0.22 Changed assembly name of standard version to just Xrm.Tools.WebAPI 38 | 1.0.23 Changed assembly name of core version to just Xrm.Tools.WebAPI 39 | 1.0.24 Added Associate and DeleteAssocation methods 40 | 41 | 42 | This is an API helper for working with the Common Data Service/Dynamics 365 Web API 43 | 44 | en-US 45 | https://github.com/davidyack/Xrm.Tools.CRMWebAPI 46 | https://nuget.org/Content/Images/packageDefaultIcon-50x50.png 47 | false 48 | https://github.com/davidyack/Xrm.Tools.CRMWebAPI/blob/master/LICENSE 49 | Copyright 2018 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.NuGet/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Xrm.Tools.WebAPI.NuGet")] 9 | [assembly: AssemblyDescription("Project template made by EyeCatch (http://www.eyecatch.no/)")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Xrm.Tools.WebAPI.NuGet")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5b586874-8d3e-4137-9ba8-e982413416d5")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.NuGet/Xrm.Tools.CRMWebAPI.1.0.0.nupkg.bak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidyack/Xrm.Tools.CRMWebAPI/1d89792291b435cf659932bdc8e54662c7ddf4b7/dotnet/Xrm.Tools.WebAPI.NuGet/Xrm.Tools.CRMWebAPI.1.0.0.nupkg.bak -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.NuGet/Xrm.Tools.CRMWebAPI.1.0.1.nupkg.bak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidyack/Xrm.Tools.CRMWebAPI/1d89792291b435cf659932bdc8e54662c7ddf4b7/dotnet/Xrm.Tools.WebAPI.NuGet/Xrm.Tools.CRMWebAPI.1.0.1.nupkg.bak -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.NuGet/Xrm.Tools.CRMWebAPI.1.0.2.nupkg.bak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidyack/Xrm.Tools.CRMWebAPI/1d89792291b435cf659932bdc8e54662c7ddf4b7/dotnet/Xrm.Tools.WebAPI.NuGet/Xrm.Tools.CRMWebAPI.1.0.2.nupkg.bak -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.NuGet/Xrm.Tools.CRMWebAPI.1.0.24.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidyack/Xrm.Tools.CRMWebAPI/1d89792291b435cf659932bdc8e54662c7ddf4b7/dotnet/Xrm.Tools.WebAPI.NuGet/Xrm.Tools.CRMWebAPI.1.0.24.nupkg -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.NuGet/Xrm.Tools.CRMWebAPI.1.0.3.nupkg.bak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidyack/Xrm.Tools.CRMWebAPI/1d89792291b435cf659932bdc8e54662c7ddf4b7/dotnet/Xrm.Tools.WebAPI.NuGet/Xrm.Tools.CRMWebAPI.1.0.3.nupkg.bak -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.NuGet/Xrm.Tools.CRMWebAPI.1.0.4.nupkg.bak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidyack/Xrm.Tools.CRMWebAPI/1d89792291b435cf659932bdc8e54662c7ddf4b7/dotnet/Xrm.Tools.WebAPI.NuGet/Xrm.Tools.CRMWebAPI.1.0.4.nupkg.bak -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.NuGet/Xrm.Tools.CRMWebAPI.1.0.5.nupkg.bak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidyack/Xrm.Tools.CRMWebAPI/1d89792291b435cf659932bdc8e54662c7ddf4b7/dotnet/Xrm.Tools.WebAPI.NuGet/Xrm.Tools.CRMWebAPI.1.0.5.nupkg.bak -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.NuGet/Xrm.Tools.WebAPI.NuGet.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {0451BAEF-DF2E-4B98-8644-94EE9415E389} 9 | Library 10 | Properties 11 | Xrm.Tools.WebAPI.NuGet 12 | Xrm.Tools.WebAPI.NuGet 13 | v4.5.2 14 | 15 | 16 | 512 17 | 18 | 19 | AnyCPU 20 | true 21 | full 22 | false 23 | bin\Debug\ 24 | DEBUG;TRACE 25 | prompt 26 | 4 27 | 28 | 29 | AnyCPU 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | AnyCPU 39 | bin\Debug\ 40 | false 41 | 42 | 43 | AnyCPU 44 | bin\Release\ 45 | false 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | ..\packages\Newtonsoft.Json.8.0.2\lib\net35\Newtonsoft.Json.dll 72 | True 73 | 74 | 75 | 76 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.NuGet/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.NuGet/tools/init.ps1: -------------------------------------------------------------------------------- 1 | # Runs the first time a package is installed in a solution, and every time the solution is opened. 2 | 3 | param($installPath, $toolsPath, $package, $project) 4 | 5 | # $installPath is the path to the folder where the package is installed. 6 | # $toolsPath is the path to the tools directory in the folder where the package is installed. 7 | # $package is a reference to the package object. 8 | # $project is null in init.ps1 9 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.NuGet/tools/install.ps1: -------------------------------------------------------------------------------- 1 | # Runs every time a package is installed in a project 2 | 3 | param($installPath, $toolsPath, $package, $project) 4 | 5 | # $installPath is the path to the folder where the package is installed. 6 | # $toolsPath is the path to the tools directory in the folder where the package is installed. 7 | # $package is a reference to the package object. 8 | # $project is a reference to the project the package was installed to. 9 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.NuGet/tools/uninstall.ps1: -------------------------------------------------------------------------------- 1 | # Runs every time a package is uninstalled 2 | 3 | param($installPath, $toolsPath, $package, $project) 4 | 5 | # $installPath is the path to the folder where the package is installed. 6 | # $toolsPath is the path to the tools directory in the folder where the package is installed. 7 | # $package is a reference to the package object. 8 | # $project is a reference to the project the package was installed to. 9 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.Portable/CRMOptionDisplayValue.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Xrm.Tools.WebAPI.Results 8 | { 9 | public class CRMOptionDisplayValue 10 | { 11 | public long Value { get; set; } 12 | public string Label { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.Portable/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Resources; 2 | using System.Reflection; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | 6 | // General Information about an assembly is controlled through the following 7 | // set of attributes. Change these attribute values to modify the information 8 | // associated with an assembly. 9 | [assembly: AssemblyTitle("Xrm.Tools.WebAPI.Portable")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("Xrm.Tools.WebAPI.Portable")] 14 | [assembly: AssemblyCopyright("Copyright © 2016")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | [assembly: NeutralResourcesLanguage("en")] 18 | 19 | // Version information for an assembly consists of the following four values: 20 | // 21 | // Major Version 22 | // Minor Version 23 | // Build Number 24 | // Revision 25 | // 26 | // You can specify all the values or you can default the Build and Revision Numbers 27 | // by using the '*' as shown below: 28 | // [assembly: AssemblyVersion("1.0.*")] 29 | [assembly: AssemblyVersion("1.0.0.0")] 30 | [assembly: AssemblyFileVersion("1.0.0.0")] 31 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.Portable/Xrm.Tools.WebAPI.Portable.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 14.0 6 | Debug 7 | AnyCPU 8 | {2E161345-1A64-45A9-A31B-FDC7054BBEFB} 9 | Library 10 | Properties 11 | Xrm.Tools.WebAPI.Portable 12 | Xrm.Tools.WebAPI.Portable 13 | en-US 14 | 512 15 | {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 16 | 17 | 18 | v5.0 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | TRACE;DEBUG;WINDOWS_APP 26 | prompt 27 | 4 28 | false 29 | 30 | 31 | pdbonly 32 | true 33 | bin\Release\ 34 | TRACE 35 | prompt 36 | 4 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | CRMWebAPI.cs 45 | 46 | 47 | CRMExpandOptions.cs 48 | 49 | 50 | CRMGetListOptions.cs 51 | 52 | 53 | CRMBatchResult.cs 54 | 55 | 56 | CRMGetListResult.cs 57 | 58 | 59 | CRMMultipleOperationResultItem.cs 60 | 61 | 62 | CRMUpdateResult.cs 63 | 64 | 65 | CRMWebAPIException.cs 66 | 67 | 68 | 69 | 70 | 71 | 78 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.Portable/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "supports": { 3 | "net46.app": {}, 4 | "uwp.10.0.app": {} 5 | }, 6 | "dependencies": { 7 | "Microsoft.NETCore": "5.0.0", 8 | "Microsoft.NETCore.Portable.Compatibility": "1.0.0", 9 | "Newtonsoft.Json": "8.0.2" 10 | }, 11 | "frameworks": { 12 | "dotnet": { 13 | "imports": "portable-net452+win81" 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.Standard/Xrm.Tools.WebAPI.Standard.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard1.4;netstandard2.0 5 | true 6 | xt.snk 7 | Xrm.Tools.WebAPI 8 | Xrm.Tools.WebAPI 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.Standard/xt.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidyack/Xrm.Tools.CRMWebAPI/1d89792291b435cf659932bdc8e54662c7ddf4b7/dotnet/Xrm.Tools.WebAPI.Standard/xt.snk -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.Test/ActionTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using System.Threading.Tasks; 4 | using System.Dynamic; 5 | using System.Collections.Generic; 6 | 7 | namespace Xrm.Tools.WebAPI.Test 8 | { 9 | [TestClass] 10 | public class ActionTests : UnitTestBaseClass 11 | { 12 | [TestMethod] 13 | public void TestWinOpportunity() 14 | { 15 | 16 | Task.Run(async () => 17 | { 18 | var api = GetAPI(); 19 | 20 | dynamic account = new ExpandoObject(); 21 | account.name = "test " + DateTime.Now.ToString(); 22 | Guid accountID = await api.Create("accounts", account); 23 | 24 | dynamic contact = new ExpandoObject(); 25 | contact.firstname = "test " + DateTime.Now.ToString(); 26 | contact.lastname = "test " + DateTime.Now.ToString(); 27 | Guid contactID = await api.Create("contacts", contact); 28 | 29 | dynamic opportunity = new ExpandoObject(); 30 | var oppIndexer = opportunity as IDictionary; 31 | opportunity.name = "Test opportunity " + DateTime.Now.ToString(); 32 | oppIndexer["customerid_account@odata.bind"] = "/accounts(" + accountID.ToString() + ")"; 33 | oppIndexer["parentcontactid@odata.bind"] = "/contacts(" + contactID.ToString() + ")"; 34 | Guid oppID = await api.Create("opportunities", opportunity); 35 | 36 | dynamic opportClose = new ExpandoObject(); 37 | var opportCloseIndexer = opportClose as IDictionary; 38 | opportClose.subject = "Won Opportunity"; 39 | opportCloseIndexer["opportunityid@odata.bind"] = "/opportunities(" + oppID.ToString() + ")"; 40 | dynamic lostOpportParams = new ExpandoObject(); 41 | lostOpportParams.Status = 3; 42 | lostOpportParams.OpportunityClose = opportClose; 43 | await api.ExecuteAction("WinOpportunity", lostOpportParams); 44 | 45 | System.Diagnostics.Trace.WriteLine("finished"); 46 | 47 | 48 | }).Wait(); 49 | } 50 | [TestMethod] 51 | public void TestLostOpportunity() 52 | { 53 | 54 | Task.Run(async () => 55 | { 56 | var api = GetAPI(); 57 | 58 | dynamic account = new ExpandoObject(); 59 | account.name = "test " + DateTime.Now.ToString(); 60 | Guid accountID = await api.Create("accounts", account); 61 | 62 | dynamic contact = new ExpandoObject(); 63 | contact.firstname = "test " + DateTime.Now.ToString(); 64 | contact.lastname = "test " + DateTime.Now.ToString(); 65 | Guid contactID = await api.Create("contacts", contact); 66 | 67 | dynamic opportunity = new ExpandoObject(); 68 | var oppIndexer = opportunity as IDictionary; 69 | opportunity.name = "Test opportunity " + DateTime.Now.ToString(); 70 | oppIndexer["customerid_account@odata.bind"] = "/accounts(" + accountID.ToString() + ")"; 71 | oppIndexer["parentcontactid@odata.bind"] = "/contacts(" + contactID.ToString() + ")"; 72 | Guid oppID = await api.Create("opportunities", opportunity); 73 | 74 | dynamic opportClose = new ExpandoObject(); 75 | var opportCloseIndexer = opportClose as IDictionary; 76 | opportClose.subject = "Lost Opportunity"; 77 | opportCloseIndexer["opportunityid@odata.bind"] = "/opportunities(" + oppID.ToString() +")"; 78 | dynamic lostOpportParams = new ExpandoObject(); 79 | lostOpportParams.Status = 4; 80 | lostOpportParams.OpportunityClose = opportClose; 81 | await api.ExecuteAction("LoseOpportunity", lostOpportParams); 82 | 83 | System.Diagnostics.Trace.WriteLine("finished"); 84 | 85 | 86 | }).Wait(); 87 | } 88 | 89 | [TestMethod] 90 | public void TestCalculateRollup() 91 | { 92 | 93 | Task.Run(async () => 94 | { 95 | var api = GetAPI(); 96 | 97 | dynamic voteCountUpdate = new ExpandoObject(); 98 | voteCountUpdate.Target = new ExpandoObject(); 99 | var ivote = voteCountUpdate.Target as IDictionary; 100 | 101 | ivote["@odata.id"] = "ctccrm_ideas(19dc848b-1c5e-e711-8112-e0071b66aea1)"; 102 | voteCountUpdate.FieldName = "ctccrm_votes"; 103 | await api.ExecuteFunction("CalculateRollupField", voteCountUpdate); 104 | 105 | 106 | System.Diagnostics.Trace.WriteLine("finished"); 107 | 108 | 109 | }).Wait(); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.Test/BasicChangeTrackingTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using System.Threading.Tasks; 4 | using System.Dynamic; 5 | 6 | namespace Xrm.Tools.WebAPI.Test 7 | { 8 | [TestClass] 9 | public class BasicChangeTrackingTests : UnitTestBaseClass 10 | { 11 | [TestMethod] 12 | public void TestMethod1() 13 | { 14 | 15 | Task.Run(async () => 16 | { 17 | var api = GetAPI(); 18 | 19 | var results = await api.GetList("accounts", new Requests.CRMGetListOptions() { TrackChanges=true, FormattedValues = true }); 20 | 21 | results = await api.GetList("accounts", new Requests.CRMGetListOptions() { TrackChanges = true, TrackChangesLink=results.TrackChangesLink, FormattedValues = true }); 22 | 23 | dynamic data = new ExpandoObject(); 24 | data.name = "test " + DateTime.Now.ToString(); 25 | 26 | Guid createdID = await api.Create("accounts", data); 27 | 28 | results = await api.GetList("accounts", new Requests.CRMGetListOptions() { TrackChanges = true, TrackChangesLink = results.TrackChangesLink, FormattedValues = true }); 29 | 30 | }).Wait(); 31 | 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.Test/BasicMetadataTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using Xrm.Tools.WebAPI; 4 | using Xrm.Tools.WebAPI.Metadata; 5 | using System.Threading.Tasks; 6 | using System.Linq; 7 | using System.Dynamic; 8 | 9 | namespace Xrm.Tools.WebAPI.Test 10 | { 11 | [TestClass] 12 | public class BasicMetadataTests : UnitTestBaseClass 13 | { 14 | [TestMethod] 15 | public void TestOptionSetNames() 16 | { 17 | Task.Run(async () => 18 | { 19 | var api = GetAPI(); 20 | 21 | var optionSet = await api.GetOptionSetByName("need"); 22 | 23 | var optionSetLabels = await api.GetOptionSetUserLabels("need"); 24 | 25 | }).Wait(); 26 | 27 | } 28 | 29 | [TestMethod] 30 | public void TestEntitySetNames() 31 | { 32 | Task.Run(async () => 33 | { 34 | var api = GetAPI(); 35 | 36 | var entityNameList = await api.GetEntityDisplayNameList(); 37 | 38 | var entityNameListWithLCID = await api.GetEntityDisplayNameList(1033); 39 | 40 | }).Wait(); 41 | 42 | } 43 | 44 | [TestMethod] 45 | public void TestAttributeNames() 46 | { 47 | Task.Run(async () => 48 | { 49 | var api = GetAPI(); 50 | 51 | var entityNameList = await api.GetEntityDisplayNameList(); 52 | 53 | var firstEntity = entityNameList.Where(e => e.LogicalName == "account").FirstOrDefault(); 54 | 55 | var attrNameList = await api.GetAttributeDisplayNameList(firstEntity.MetadataId); 56 | 57 | var attrNameListWithLCID = await api.GetAttributeDisplayNameList(firstEntity.MetadataId,1033); 58 | 59 | }).Wait(); 60 | 61 | } 62 | 63 | [TestMethod] 64 | public void TestCopyAttribute() 65 | { 66 | Task.Run(async () => 67 | { 68 | var api = GetAPI(); 69 | 70 | var entityNameList = await api.GetEntityDisplayNameList(); 71 | 72 | var accountEntity = entityNameList.Where(e => e.LogicalName == "account").FirstOrDefault(); 73 | 74 | var attrNameList = await api.GetAttributeDisplayNameList(accountEntity.MetadataId); 75 | 76 | var nameAttr = attrNameList.Where(a => a.LogicalName == "name").FirstOrDefault(); 77 | 78 | var newAttrib = await api.CopyEntityAttribute(accountEntity.MetadataId, accountEntity.MetadataId, nameAttr.MetadataId, nameAttr.AttributeType, "dy_name123"); 79 | 80 | }).Wait(); 81 | 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Xrm.Tools.WebAPI.Test")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Xrm.Tools.WebAPI.Test")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("2492b98c-952b-41f5-99d3-1168d192e322")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.Test/UnitTestBaseClass.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Xrm.Tools.WebAPI.Test 8 | { 9 | public class UnitTestBaseClass 10 | { 11 | public CRMWebAPI GetAPI() 12 | { 13 | 14 | CRMWebAPI api = new CRMWebAPI("https://orgname.api.crm.dynamics.com/api/data/v9.0/", ""); 15 | return api; 16 | 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.Test/Xrm.Tools.WebAPI.Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {2492B98C-952B-41F5-99D3-1168D192E322} 7 | Library 8 | Properties 9 | Xrm.Tools.WebAPI.Test 10 | Xrm.Tools.WebAPI.Test 11 | v4.6 12 | 512 13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 10.0 15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages 17 | False 18 | UnitTest 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | 39 | 40 | ..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll 41 | True 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | False 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | {8d1c4066-5def-4cc9-b84f-58944bbe86f0} 71 | Xrm.Tools.WebAPI 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | False 83 | 84 | 85 | False 86 | 87 | 88 | False 89 | 90 | 91 | False 92 | 93 | 94 | 95 | 96 | 97 | 98 | 105 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.Test/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.Test/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.3 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xrm.Tools.WebAPI", "Xrm.Tools.WebAPI\Xrm.Tools.WebAPI.csproj", "{8D1C4066-5DEF-4CC9-B84F-58944BBE86F0}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xrm.Tools.WebAPI.Test", "Xrm.Tools.WebAPI.Test\Xrm.Tools.WebAPI.Test.csproj", "{2492B98C-952B-41F5-99D3-1168D192E322}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xrm.Tools.WebAPI.NuGet", "Xrm.Tools.WebAPI.NuGet\Xrm.Tools.WebAPI.NuGet.csproj", "{0451BAEF-DF2E-4B98-8644-94EE9415E389}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Xrm.Tools.WebAPI.Core", "Xrm.Tools.WebAPI.Core\Xrm.Tools.WebAPI.Core.csproj", "{96734240-AB11-44F0-B47D-9169F4334403}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Xrm.Tools.WebAPI.Standard", "Xrm.Tools.WebAPI.Standard\Xrm.Tools.WebAPI.Standard.csproj", "{94F41AEC-9406-44E1-BE56-2E786C51CCA7}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Release|Any CPU = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {8D1C4066-5DEF-4CC9-B84F-58944BBE86F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {8D1C4066-5DEF-4CC9-B84F-58944BBE86F0}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {8D1C4066-5DEF-4CC9-B84F-58944BBE86F0}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {8D1C4066-5DEF-4CC9-B84F-58944BBE86F0}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {2492B98C-952B-41F5-99D3-1168D192E322}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {2492B98C-952B-41F5-99D3-1168D192E322}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {2492B98C-952B-41F5-99D3-1168D192E322}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {2492B98C-952B-41F5-99D3-1168D192E322}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {0451BAEF-DF2E-4B98-8644-94EE9415E389}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {0451BAEF-DF2E-4B98-8644-94EE9415E389}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {0451BAEF-DF2E-4B98-8644-94EE9415E389}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {0451BAEF-DF2E-4B98-8644-94EE9415E389}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {96734240-AB11-44F0-B47D-9169F4334403}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {96734240-AB11-44F0-B47D-9169F4334403}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {96734240-AB11-44F0-B47D-9169F4334403}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {96734240-AB11-44F0-B47D-9169F4334403}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {94F41AEC-9406-44E1-BE56-2E786C51CCA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {94F41AEC-9406-44E1-BE56-2E786C51CCA7}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {94F41AEC-9406-44E1-BE56-2E786C51CCA7}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {94F41AEC-9406-44E1-BE56-2E786C51CCA7}.Release|Any CPU.Build.0 = Release|Any CPU 42 | EndGlobalSection 43 | GlobalSection(SolutionProperties) = preSolution 44 | HideSolutionNode = FALSE 45 | EndGlobalSection 46 | GlobalSection(ExtensibilityGlobals) = postSolution 47 | SolutionGuid = {9BE9241F-12DA-4E8E-9656-FD2A4AD05809} 48 | EndGlobalSection 49 | EndGlobal 50 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI/Metadata/CRMWebAPIMetadata.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Dynamic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Xrm.Tools.WebAPI.Requests; 8 | using Xrm.Tools.WebAPI.Results; 9 | 10 | namespace Xrm.Tools.WebAPI.Metadata 11 | { 12 | public static class CRMWebAPIMetadataExtensions 13 | { 14 | public static async Task GetOptionSetByName(this CRMWebAPI api, string optionSetName) 15 | { 16 | CRMGetListOptions options = new CRMGetListOptions() { Select = new[] { "Name" } }; 17 | 18 | var queryResult = await api.GetList("GlobalOptionSetDefinitions", options); 19 | 20 | foreach(dynamic optionSet in queryResult.List) 21 | { 22 | 23 | if ((optionSet != null) && (optionSet.Name == optionSetName)) 24 | { 25 | var matchingOptionSet = await api.Get("GlobalOptionSetDefinitions", Guid.Parse( optionSet.MetadataId)); 26 | 27 | return matchingOptionSet; 28 | } 29 | } 30 | 31 | return null; 32 | 33 | } 34 | 35 | public static async Task> GetOptionSetUserLabels(this CRMWebAPI api,string optionSetName) 36 | { 37 | var response = new List(); 38 | 39 | dynamic optionSet = await api.GetOptionSetByName(optionSetName); 40 | 41 | foreach(dynamic option in optionSet.Options) 42 | { 43 | CRMOptionDisplayValue odv = new CRMOptionDisplayValue(); 44 | odv.Value = option.Value; 45 | odv.Label = option.Label.UserLocalizedLabel.Label; 46 | response.Add(odv); 47 | } 48 | 49 | return response; 50 | } 51 | 52 | public static async Task> GetEntityDisplayNameList(this CRMWebAPI api, int LCID=0) 53 | { 54 | var result = new List(); 55 | 56 | CRMGetListOptions options = new CRMGetListOptions() 57 | { 58 | Filter = "IsPrivate eq false", 59 | 60 | Select = new[] { "MetadataId","EntitySetName","DisplayName", 61 | "DisplayCollectionName","LogicalName","LogicalCollectionName","PrimaryIdAttribute" } 62 | }; 63 | 64 | var queryResults = await api.GetList("EntityDefinitions", options); 65 | 66 | foreach(dynamic entity in queryResults.List) 67 | { 68 | CRMEntityDisplayName edm = new CRMEntityDisplayName(); 69 | edm.MetadataId = Guid.Parse(entity.MetadataId); 70 | edm.EntitySetName = entity.EntitySetName; 71 | edm.LogicalName = entity.LogicalName; 72 | edm.LogicalCollectionName = entity.LogicalCollectionName; 73 | edm.PrimaryIdAttribute = entity.PrimaryIdAttribute; 74 | if ((entity.DisplayName.LocalizedLabels != null) && (entity.DisplayName.LocalizedLabels.Count > 0)) 75 | { 76 | edm.DisplayName = entity.DisplayName.LocalizedLabels[0].Label; 77 | if (LCID != 0) 78 | foreach (dynamic label in entity.DisplayName.LocalizedLabels) 79 | { if (label.LanguageCode == LCID) edm.DisplayName = label.Label; } 80 | 81 | } 82 | else 83 | edm.DisplayName = edm.LogicalName; 84 | if ((entity.DisplayCollectionName.LocalizedLabels != null) && (entity.DisplayCollectionName.LocalizedLabels.Count > 0)) 85 | { 86 | edm.DisplayCollectionName = entity.DisplayCollectionName.LocalizedLabels[0].Label; 87 | if (LCID != 0) 88 | foreach (dynamic label in entity.DisplayCollectionName.LocalizedLabels) 89 | { if (label.LanguageCode == LCID) edm.DisplayCollectionName = label.Label; } 90 | } 91 | else 92 | edm.DisplayCollectionName = entity.LogicalCollectionName; 93 | edm.LogicalDisplayName = edm.DisplayName + "(" + edm.LogicalName + ")"; 94 | edm.LogicalDisplayCollectionName = edm.DisplayCollectionName + "(" + edm.LogicalCollectionName + ")"; 95 | 96 | result.Add(edm); 97 | 98 | } 99 | 100 | return result; 101 | 102 | } 103 | 104 | public static async Task> GetAttributeDisplayNameList(this CRMWebAPI api, Guid entityID,int LCID = 0) 105 | { 106 | var result = new List(); 107 | 108 | CRMGetListOptions options = new CRMGetListOptions() 109 | { 110 | Filter = "((IsValidForRead eq true) and (AttributeOf eq null))", 111 | 112 | Select = new[] { "MetadataId", "DisplayName", "LogicalName", "SchemaName", "AttributeType", "IsPrimaryId" } 113 | }; 114 | 115 | var queryResults = await api.GetList("EntityDefinitions(" + entityID.ToString() + ")/Attributes", options); 116 | 117 | foreach (dynamic attrib in queryResults.List) 118 | { 119 | CRMAttributeDisplayName edm = new CRMAttributeDisplayName(); 120 | edm.MetadataId = Guid.Parse(attrib.MetadataId); 121 | edm.LogicalName = attrib.LogicalName; 122 | edm.SchemaName = attrib.SchemaName; 123 | edm.IsPrimaryId = attrib.IsPrimaryId; 124 | edm.AttributeType = attrib.AttributeType; 125 | if (attrib.AttributeType == "Lookup" || attrib.AttributeType == "Customer" || attrib.AttributeType == "Owner") 126 | edm.ODataLogicalName = "_" + attrib.LogicalName + "_value"; 127 | else 128 | edm.ODataLogicalName = attrib.LogicalName; 129 | 130 | if ((attrib.DisplayName.LocalizedLabels != null) && (attrib.DisplayName.LocalizedLabels.Count > 0)) 131 | { 132 | edm.DisplayName = attrib.DisplayName.LocalizedLabels[0].Label; 133 | if (LCID != 0) 134 | foreach (dynamic label in attrib.DisplayName.LocalizedLabels) 135 | { if (label.LanguageCode == LCID) edm.DisplayName = label.Label; } 136 | } 137 | else 138 | edm.DisplayName = edm.LogicalName; 139 | edm.LogicalDisplayName = edm.DisplayName + "(" + edm.LogicalName + ")"; 140 | result.Add(edm); 141 | } 142 | 143 | 144 | 145 | return result; 146 | 147 | } 148 | 149 | public static async Task CopyEntityAttribute(this CRMWebAPI api, Guid fromEntityID, Guid toEntityID, Guid fromAttributeID, string attributeType, string logicalName) 150 | { 151 | var ec = "EntityDefinitions(" + fromEntityID.ToString() + ")/Attributes(" + fromAttributeID + ")"; 152 | if (attributeType == "Boolean") 153 | ec += "/Microsoft.Dynamics.CRM.BooleanAttributeMetadata?$expand=OptionSet"; 154 | if (attributeType == "Picklist") 155 | ec += "/Microsoft.Dynamics.CRM.PicklistAttributeMetadata?$expand=OptionSet,GlobalOptionSet"; 156 | 157 | dynamic fromAttrib = await api.Get(ec, Guid.Empty); 158 | IDictionary fromAttribValues = (IDictionary)fromAttrib; 159 | fromAttribValues.Remove("MetadataId"); 160 | fromAttribValues.Remove("EntityLogicalName"); 161 | if (attributeType == "Boolean") 162 | { 163 | fromAttribValues["@odata.type"] = "Microsoft.Dynamics.CRM.BooleanAttributeMetadata"; 164 | fromAttribValues.Remove("OptionSet@odata.context"); 165 | if (fromAttrib.OptionSet != null) 166 | { 167 | IDictionary fromOptionSetValues = (IDictionary)fromAttrib.OptionSet; 168 | fromOptionSetValues.Remove("Name"); 169 | fromOptionSetValues.Remove("MetadataId"); 170 | fromOptionSetValues.Remove("MetadataId"); 171 | fromOptionSetValues["IsCustomOptionSet"] = true; 172 | 173 | } 174 | } 175 | if (attributeType == "Picklist") 176 | { 177 | 178 | fromAttribValues["@odata.type"] = "Microsoft.Dynamics.CRM.PicklistAttributeMetadata"; 179 | 180 | 181 | if (fromAttrib.OptionSet != null) 182 | { 183 | IDictionary fromOptionSetValues = (IDictionary)fromAttrib.OptionSet; 184 | fromOptionSetValues.Remove("Name"); 185 | fromOptionSetValues.Remove("MetadataId"); 186 | fromOptionSetValues.Remove("MetadataId"); 187 | fromOptionSetValues["IsCustomOptionSet"] = true; 188 | 189 | } 190 | else 191 | { 192 | fromAttribValues.Remove("OptionSet"); 193 | fromAttribValues["GlobalOptionSet@odata.bind"] = "/GlobalOptionSetDefinitions(" + fromAttrib.GlobalOptionSet.MetadataId + ")"; 194 | fromAttribValues.Remove("OptionSet@odata.context"); 195 | fromAttribValues.Remove("GlobalOptionSet"); 196 | 197 | } 198 | } 199 | fromAttrib.LogicalName = logicalName; 200 | fromAttrib.SchemaName = logicalName; 201 | 202 | 203 | return await api.Create("EntityDefinitions(" + toEntityID.ToString() + ")/Attributes", fromAttrib); 204 | } 205 | 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Xrm.Tools.WebAPI")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Xrm.Tools.WebAPI")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("8d1c4066-5def-4cc9-b84f-58944bbe86f0")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.12.0")] 36 | [assembly: AssemblyFileVersion("1.0.12.0")] 37 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI/Requests/CRMExpandOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Xrm.Tools.WebAPI.Requests 8 | { 9 | public class CRMExpandOptions 10 | { 11 | public string Property { get; set; } 12 | 13 | public string[] Select { get; set; } 14 | 15 | public string[] OrderBy { get; set; } 16 | 17 | public string Filter { get; set; } 18 | public int Top { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI/Requests/CRMGetListOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Xrm.Tools.WebAPI.Requests 8 | { 9 | public class CRMGetListOptions 10 | { 11 | public string[] Select { get; set; } 12 | 13 | public string[] OrderBy { get; set; } 14 | 15 | public string Filter { get; set; } 16 | 17 | public string Apply { get; set; } 18 | public int Skip { get; set; } 19 | public int Top { get; set; } 20 | public bool IncludeCount { get; set; } 21 | public bool FormattedValues { get; set; } 22 | public bool IncludeAnnotations { get; set; } 23 | 24 | public Guid SystemQuery { get; set; } 25 | 26 | public Guid UserQuery { get; set; } 27 | public string FetchXml { get; set; } 28 | 29 | public CRMExpandOptions[] Expand { get; set; } 30 | 31 | public bool TrackChanges { get; set; } 32 | 33 | public string TrackChangesLink { get; set; } 34 | 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI/Requests/CRMWebAPIConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Threading.Tasks; 4 | 5 | namespace Xrm.Tools.WebAPI.Requests 6 | { 7 | public class CRMWebAPIConfig 8 | { 9 | public string APIUrl { get; set; } 10 | public string AccessToken { get; set; } 11 | public bool ResolveUnicodeNames { get; set; } 12 | public Guid CallerID { get; set; } 13 | public Func> GetAccessToken { get; set; } 14 | public NetworkCredential NetworkCredential { get; set; } 15 | public CRMWebAPILoggingOptions Logging { get; set; } 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI/Requests/CRMWebAPILoggingOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Xrm.Tools.WebAPI.Requests 8 | { 9 | public class CRMWebAPILoggingOptions 10 | { 11 | public Action Logger { get; set; } 12 | public bool ODataUrl { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI/Results/CRMAttributeDisplayName.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Xrm.Tools.WebAPI.Results 8 | { 9 | public class CRMAttributeDisplayName 10 | { 11 | public Guid MetadataId { get; set; } 12 | public string LogicalName { get; set; } 13 | public string SchemaName { get; set; } 14 | public bool IsPrimaryId { get; set; } 15 | public string AttributeType { get; set; } 16 | public string ODataLogicalName { get; set; } 17 | public string DisplayName { get; set; } 18 | public string LogicalDisplayName { get; set; } 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI/Results/CRMBatchResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Xrm.Tools.WebAPI.Results 8 | { 9 | public class CRMBatchResult 10 | { 11 | public List ResultItems { get; set; } 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI/Results/CRMEntityDisplayName.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Xrm.Tools.WebAPI.Results 8 | { 9 | public class CRMEntityDisplayName 10 | { 11 | public Guid MetadataId { get; set; } 12 | public string EntitySetName { get; set; } 13 | public string LogicalName { get; set; } 14 | public string LogicalCollectionName { get; set; } 15 | public string PrimaryIdAttribute { get; set; } 16 | public string DisplayName { get; set; } 17 | public string DisplayCollectionName { get; set; } 18 | public string LogicalDisplayName { get; set; } 19 | public string LogicalDisplayCollectionName { get; set; } 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI/Results/CRMGetListResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Xrm.Tools.WebAPI.Results 9 | { 10 | public class CRMGetListResult 11 | { 12 | public List List { get; set; } 13 | 14 | public int Count { get; set; } 15 | 16 | public string TrackChangesLink { get; set; } 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI/Results/CRMMultipleOperationResultItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Xrm.Tools.WebAPI.Results 8 | { 9 | public class CRMBatchResultItem 10 | { 11 | public Guid EntityID{ get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI/Results/CRMOptionDisplayValue.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Xrm.Tools.WebAPI.Results 8 | { 9 | public class CRMOptionDisplayValue 10 | { 11 | public long Value { get; set; } 12 | public string Label { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI/Results/CRMUpdateResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Xrm.Tools.WebAPI.Results 8 | { 9 | public class CRMUpdateResult 10 | { 11 | 12 | public Guid EntityID { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI/Results/CRMWebAPIException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net.Http; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Xrm.Tools.WebAPI.Results 9 | { 10 | public class CRMWebAPIException : HttpRequestException 11 | { 12 | public CRMWebAPIException(string message) : base(message) 13 | { 14 | 15 | } 16 | public string JSON { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI/Xrm.Tools.WebAPI.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {8D1C4066-5DEF-4CC9-B84F-58944BBE86F0} 8 | Library 9 | Properties 10 | Xrm.Tools.WebAPI 11 | Xrm.Tools.WebAPI 12 | v4.6 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | true 34 | 35 | 36 | xt.snk 37 | 38 | 39 | 40 | ..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll 41 | True 42 | 43 | 44 | 45 | 46 | 47 | 48 | ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll 49 | True 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 87 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /dotnet/Xrm.Tools.WebAPI/xt.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidyack/Xrm.Tools.CRMWebAPI/1d89792291b435cf659932bdc8e54662c7ddf4b7/dotnet/Xrm.Tools.WebAPI/xt.snk -------------------------------------------------------------------------------- /nodejs/README.md: -------------------------------------------------------------------------------- 1 | Currently the nodejs library only supports oAuth authentication use Adal.js for Node to get an access token for real applications or https://xrm.tools/AccessToken for testing 2 | 3 | #Getting Started 4 | 5 | ```` 6 | npm install CRMWebAPI 7 | ```` 8 | 9 | # Usage example 10 | You can find other query example information [here](https://github.com/davidyack/Xrm.Tools.CRMWebAPI/wiki/Query-Examples ) 11 | 12 | ```javascript 13 | var CRMWebAPI = require('CRMWebAPI'); 14 | 15 | var apiconfig = { APIUrl: 'https://orgname.crm.dynamics.com/api/data/v8.0/', AccessToken: "" }; 16 | 17 | var crmAPI = new CRMWebAPI(apiconfig); 18 | 19 | crmAPI 20 | .Create("accounts", { "name": "test2" }) 21 | .then( 22 | function(r){ 23 | console.log('Created: ' + r); 24 | return crmAPI.Update('accounts', r, { "name": "test2updated"}); 25 | }, 26 | function(e){ 27 | console.log(e); 28 | }) 29 | .then( 30 | function(r){ 31 | console.log('Updated: ' + r.EntityID); 32 | return crmAPI.Delete('accounts', r.EntityID); 33 | }, 34 | function(e){ 35 | console.log(e); 36 | }) 37 | .then( 38 | function(r){ 39 | console.log('Deleted'); 40 | }, function(e){ 41 | console.log(e); 42 | }) 43 | ``` 44 | -------------------------------------------------------------------------------- /nodejs/examples/callactionclientcreds/index.js: -------------------------------------------------------------------------------- 1 | 2 | var CRMWebAPI = require('CRMWebAPI'); 3 | var adal = require('adal-node'); 4 | 5 | function _authenticate(server,user,password) 6 | { 7 | return new Promise(function (resolve, reject) { 8 | 9 | var authorityHostUrl = 'https://login.windows.net/common'; 10 | var clientId = 'your client id here'; 11 | 12 | var context = new adal.AuthenticationContext(authorityHostUrl); 13 | 14 | context.acquireTokenWithUsernamePassword(server, user, password, clientId, function(err, tokenResponse) { 15 | if (err) { reject(err);} else { 16 | resolve(tokenResponse.accessToken); 17 | } 18 | }); 19 | }); 20 | } 21 | 22 | var server = 'https://orgname.crm.dynamics.com'; 23 | _authenticate(server,'admin@.onmicrosoft.com','your password').then(function(accessToken) { 24 | 25 | var apiconfig = { APIUrl: server+'/api/data/v8.1/', AccessToken: accessToken }; 26 | 27 | var crmAPI = new CRMWebAPI(apiconfig); 28 | 29 | var params = { 30 | "Country":'US' , 31 | "Amount": 500 32 | }; 33 | 34 | crmAPI.ExecuteAction("xt_CalculateDiscount", params).then(function(r){ 35 | console.log(r); 36 | }, function(e){ 37 | console.log(e); 38 | }); 39 | }); 40 | 41 | -------------------------------------------------------------------------------- /nodejs/examples/callactionclientcreds/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "callaction", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "CRMWebAPI": "^1.0.0", 13 | "adal-node": "^0.1.21" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /nodejs/examples/callactionclientcreds/readme.md: -------------------------------------------------------------------------------- 1 | This is a simple example using Node JS and CRMWebAPI to call a CRM Custom Action. 2 | 3 | This example uses client credentials hard coded and clearly isn't a pattern to follow for production applications and is intended to simply demonstrate how to call an action from Node. 4 | 5 | # Steps to uses 6 | 7 | 1. run npm install to restore node_modules folder 8 | 9 | 2. Register an application with Azure AD and make sure it has CRM permissions configured 10 | 11 | 3. Edit index.js and update the orgName and client ID you just registered as well as appropriate user/passwords hard coded 12 | 13 | 4. In that CRM, create a custom action named xt_CalculateDiscount that takes Country and Amount as input parameters and returns a money field named Discount 14 | 15 | 5. Run the sample e.g. node index.js -------------------------------------------------------------------------------- /nodejs/lib/CRMWebAPI.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for CRMWebAPI 2 | // Project: CRMWebAPI 3 | // Definitions by: Daryl LaBar 4 | 5 | /*~ This is the module template file for class modules. 6 | *~ You should rename it to index.d.ts and place it in a folder with the same name as the module. 7 | *~ For example, if you were writing a file for "super-greeter", this 8 | *~ file should be 'super-greeter/index.d.ts' 9 | */ 10 | 11 | /*~ Note that ES6 modules cannot directly export class objects. 12 | *~ This file should be imported using the CommonJS-style: 13 | *~ import x = require('someLibrary'); 14 | *~ 15 | *~ Refer to the documentation to understand common 16 | *~ workarounds for this limitation of ES6 modules. 17 | */ 18 | 19 | /*~ If this module is a UMD module that exposes a global variable 'CRMWebAPI' when 20 | *~ loaded outside a module loader environment, declare that global here. 21 | *~ Otherwise, delete this declaration. 22 | */ 23 | export as namespace CRMWebAPI; 24 | 25 | /*~ This declaration specifies that the class constructor function 26 | *~ is the exported object from the file 27 | */ 28 | export = CRMWebAPI; 29 | 30 | /*~ Write your module's methods and properties in this class */ 31 | declare class CRMWebAPI { 32 | constructor(config: CRMWebAPI.Config); 33 | 34 | GetList(uri: string, queryOptions: CRMWebAPI.QueryOptions): Promise>; 35 | Get(entityCollection: string, entityId: string, queryOptions: CRMWebAPI.QueryOptions): Promise; 36 | GetCount(uri: string, queryOptions: CRMWebAPI.QueryOptions): Promise; 37 | Create(entityCollection: string, data: any): Promise; 38 | Update(entityCollection: string, key: string, data: any, upsert?: boolean): Promise; 39 | Delete(entityCollection: string, entityID: string): Promise; 40 | Associate(fromEntitycollection: string, fromEntityId: string, navProperty: string, toEntityCollection: string, toEntityId: string): Promise; 41 | DeleteAssociation(fromEntitycollection: string, fromEntityId: string, navProperty: string, toEntityCollection?: string, toEntityId?: string): Promise; 42 | ExecuteFunction(functionName: string, parameters: TRequest): Promise; 43 | ExecuteFunction(functionName: string, parameters: TRequest, entityCollection: string, entityId: string): Promise; 44 | ExecuteAction(actionName: string, data: TRequest): Promise; 45 | ExecuteAction(actionName: string, data: TRequest, entityCollection: string, entityId: string): Promise; 46 | } 47 | 48 | /*~ If you want to expose types from your module as well, you can 49 | *~ place them in this block. 50 | */ 51 | declare namespace CRMWebAPI { 52 | export interface Config{ 53 | APIUrl: string; 54 | AccessToken?: string; 55 | callerId?: string; 56 | } 57 | 58 | export interface GetListResponse { 59 | List: T[]; 60 | } 61 | 62 | export interface UpdateResponse { 63 | EntityID: string; 64 | } 65 | 66 | export interface QueryOptionBase{ 67 | IncludeAnnotations?:boolean; 68 | FormattedValues?:boolean; 69 | Select?: string[]; 70 | Filter?: string; 71 | OrderBy?: string[]; 72 | Top?: number; 73 | } 74 | 75 | export interface ExpandQueryOptions extends QueryOptionBase { 76 | Property: string; 77 | } 78 | 79 | export interface QueryOptions extends QueryOptionBase{ 80 | Expand?: ExpandQueryOptions[]; 81 | FetchXml?: string; 82 | IncludeCount?: boolean; 83 | Skip?: number; 84 | SystemQuery?: string; 85 | UserQuery?: string; 86 | 87 | RecordAction?(record:any); 88 | PageAction?(list:any[]); 89 | } 90 | } -------------------------------------------------------------------------------- /nodejs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Xrm.Tools", 3 | "name": "CRMWebAPI", 4 | "description": "CRMWebAPI Node.js Wrapper", 5 | "version": "1.3.6", 6 | "repository": { 7 | "url": "http://github.com/DavidYack/Xrm.Tools.CRMWebAPI" 8 | }, 9 | "main": "./lib/CRMWebAPI", 10 | "types": "./lib/CRMWebAPI.d.ts", 11 | "dependencies": {}, 12 | "devDependencies": {}, 13 | "optionalDependencies": {}, 14 | "engines": { 15 | "node": ">=0.12" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /php/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | crmwebapi-php-demo.iml 3 | test.php 4 | vendor 5 | -------------------------------------------------------------------------------- /php/README.md: -------------------------------------------------------------------------------- 1 | # Usage example 2 | 3 | ```php 4 | use CRMWebAPI\CRMWebAPI; 5 | 6 | $api = new CRMWebAPI([ 7 | 'APIUrl' => 'https://test.crm.dynamics.com/api/data/v8.0/', 8 | 'AccessToken' => '' 9 | ]); 10 | 11 | $id = $api->Create('accounts', ['name' => 'test-php']); 12 | $uid = $api->Update('accounts', $id, ['name' => 'test-php-updated']); 13 | $api->Delete('accounts', $uid->EntityId); 14 | $whoami = $api->ExecuteFunction("WhoAmI"); 15 | ``` 16 | 17 | As for acquring the token, I would look at https://github.com/jamesmcq/oidc-aad-php-library or one of the Office 365 samples here https://github.com/jasonjoh/php-calendar - for CRM you would need to specify the org URL as the resource 18 | -------------------------------------------------------------------------------- /php/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "davidyack/Xrm.Tools.CRMWebAPI", 3 | "description": "CRM Web API for PHP", 4 | "license": "MIT", 5 | "keywords": [ 6 | "crmwebapi", 7 | "api" 8 | ], 9 | "authors": [ 10 | { 11 | "name": "Xrm.Tools", 12 | "email": "info@coloradotc.com" 13 | } 14 | ], 15 | "require": { 16 | "guzzlehttp/guzzle": "~6" 17 | }, 18 | "require-dev": {}, 19 | "autoload": { 20 | "psr-4": { 21 | "CRMWebAPI\\": "lib" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /php/composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "f10578f6d7d728aa34277c81961d3fc3", 8 | "content-hash": "949eca3f573e3f372ac10e9e79ed3c90", 9 | "packages": [ 10 | { 11 | "name": "guzzlehttp/guzzle", 12 | "version": "6.1.1", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/guzzle/guzzle.git", 16 | "reference": "c6851d6e48f63b69357cbfa55bca116448140e0c" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/guzzle/guzzle/zipball/c6851d6e48f63b69357cbfa55bca116448140e0c", 21 | "reference": "c6851d6e48f63b69357cbfa55bca116448140e0c", 22 | "shasum": "" 23 | }, 24 | "require": { 25 | "guzzlehttp/promises": "~1.0", 26 | "guzzlehttp/psr7": "~1.1", 27 | "php": ">=5.5.0" 28 | }, 29 | "require-dev": { 30 | "ext-curl": "*", 31 | "phpunit/phpunit": "~4.0", 32 | "psr/log": "~1.0" 33 | }, 34 | "type": "library", 35 | "extra": { 36 | "branch-alias": { 37 | "dev-master": "6.1-dev" 38 | } 39 | }, 40 | "autoload": { 41 | "files": [ 42 | "src/functions_include.php" 43 | ], 44 | "psr-4": { 45 | "GuzzleHttp\\": "src/" 46 | } 47 | }, 48 | "notification-url": "https://packagist.org/downloads/", 49 | "license": [ 50 | "MIT" 51 | ], 52 | "authors": [ 53 | { 54 | "name": "Michael Dowling", 55 | "email": "mtdowling@gmail.com", 56 | "homepage": "https://github.com/mtdowling" 57 | } 58 | ], 59 | "description": "Guzzle is a PHP HTTP client library", 60 | "homepage": "http://guzzlephp.org/", 61 | "keywords": [ 62 | "client", 63 | "curl", 64 | "framework", 65 | "http", 66 | "http client", 67 | "rest", 68 | "web service" 69 | ], 70 | "time": "2015-11-23 00:47:50" 71 | }, 72 | { 73 | "name": "guzzlehttp/promises", 74 | "version": "1.0.3", 75 | "source": { 76 | "type": "git", 77 | "url": "https://github.com/guzzle/promises.git", 78 | "reference": "b1e1c0d55f8083c71eda2c28c12a228d708294ea" 79 | }, 80 | "dist": { 81 | "type": "zip", 82 | "url": "https://api.github.com/repos/guzzle/promises/zipball/b1e1c0d55f8083c71eda2c28c12a228d708294ea", 83 | "reference": "b1e1c0d55f8083c71eda2c28c12a228d708294ea", 84 | "shasum": "" 85 | }, 86 | "require": { 87 | "php": ">=5.5.0" 88 | }, 89 | "require-dev": { 90 | "phpunit/phpunit": "~4.0" 91 | }, 92 | "type": "library", 93 | "extra": { 94 | "branch-alias": { 95 | "dev-master": "1.0-dev" 96 | } 97 | }, 98 | "autoload": { 99 | "psr-4": { 100 | "GuzzleHttp\\Promise\\": "src/" 101 | }, 102 | "files": [ 103 | "src/functions_include.php" 104 | ] 105 | }, 106 | "notification-url": "https://packagist.org/downloads/", 107 | "license": [ 108 | "MIT" 109 | ], 110 | "authors": [ 111 | { 112 | "name": "Michael Dowling", 113 | "email": "mtdowling@gmail.com", 114 | "homepage": "https://github.com/mtdowling" 115 | } 116 | ], 117 | "description": "Guzzle promises library", 118 | "keywords": [ 119 | "promise" 120 | ], 121 | "time": "2015-10-15 22:28:00" 122 | }, 123 | { 124 | "name": "guzzlehttp/psr7", 125 | "version": "1.2.1", 126 | "source": { 127 | "type": "git", 128 | "url": "https://github.com/guzzle/psr7.git", 129 | "reference": "4d0bdbe1206df7440219ce14c972aa57cc5e4982" 130 | }, 131 | "dist": { 132 | "type": "zip", 133 | "url": "https://api.github.com/repos/guzzle/psr7/zipball/4d0bdbe1206df7440219ce14c972aa57cc5e4982", 134 | "reference": "4d0bdbe1206df7440219ce14c972aa57cc5e4982", 135 | "shasum": "" 136 | }, 137 | "require": { 138 | "php": ">=5.4.0", 139 | "psr/http-message": "~1.0" 140 | }, 141 | "provide": { 142 | "psr/http-message-implementation": "1.0" 143 | }, 144 | "require-dev": { 145 | "phpunit/phpunit": "~4.0" 146 | }, 147 | "type": "library", 148 | "extra": { 149 | "branch-alias": { 150 | "dev-master": "1.0-dev" 151 | } 152 | }, 153 | "autoload": { 154 | "psr-4": { 155 | "GuzzleHttp\\Psr7\\": "src/" 156 | }, 157 | "files": [ 158 | "src/functions_include.php" 159 | ] 160 | }, 161 | "notification-url": "https://packagist.org/downloads/", 162 | "license": [ 163 | "MIT" 164 | ], 165 | "authors": [ 166 | { 167 | "name": "Michael Dowling", 168 | "email": "mtdowling@gmail.com", 169 | "homepage": "https://github.com/mtdowling" 170 | } 171 | ], 172 | "description": "PSR-7 message implementation", 173 | "keywords": [ 174 | "http", 175 | "message", 176 | "stream", 177 | "uri" 178 | ], 179 | "time": "2015-11-03 01:34:55" 180 | }, 181 | { 182 | "name": "psr/http-message", 183 | "version": "1.0", 184 | "source": { 185 | "type": "git", 186 | "url": "https://github.com/php-fig/http-message.git", 187 | "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" 188 | }, 189 | "dist": { 190 | "type": "zip", 191 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", 192 | "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", 193 | "shasum": "" 194 | }, 195 | "require": { 196 | "php": ">=5.3.0" 197 | }, 198 | "type": "library", 199 | "extra": { 200 | "branch-alias": { 201 | "dev-master": "1.0.x-dev" 202 | } 203 | }, 204 | "autoload": { 205 | "psr-4": { 206 | "Psr\\Http\\Message\\": "src/" 207 | } 208 | }, 209 | "notification-url": "https://packagist.org/downloads/", 210 | "license": [ 211 | "MIT" 212 | ], 213 | "authors": [ 214 | { 215 | "name": "PHP-FIG", 216 | "homepage": "http://www.php-fig.org/" 217 | } 218 | ], 219 | "description": "Common interface for HTTP messages", 220 | "keywords": [ 221 | "http", 222 | "http-message", 223 | "psr", 224 | "psr-7", 225 | "request", 226 | "response" 227 | ], 228 | "time": "2015-05-04 20:22:00" 229 | } 230 | ], 231 | "packages-dev": [], 232 | "aliases": [], 233 | "minimum-stability": "stable", 234 | "stability-flags": [], 235 | "prefer-stable": false, 236 | "prefer-lowest": false, 237 | "platform": [], 238 | "platform-dev": [] 239 | } 240 | -------------------------------------------------------------------------------- /python/.gitignore: -------------------------------------------------------------------------------- 1 | *.py[co] 2 | crm-python.iml 3 | 4 | #small test code that contains my keys 5 | t.py 6 | 7 | # Packages 8 | *.egg 9 | *.egg-info 10 | dist 11 | build 12 | eggs 13 | parts 14 | bin 15 | include 16 | lib 17 | local 18 | var 19 | sdist 20 | develop-eggs 21 | .installed.cfg 22 | 23 | # Installer logs 24 | pip-log.txt 25 | 26 | # Unit test / coverage reports 27 | .coverage 28 | .tox 29 | 30 | # PyCharm data 31 | .idea 32 | 33 | #Translations 34 | *.mo 35 | 36 | #Mr Developer 37 | .mr.developer.cfg 38 | 39 | #Environment 40 | env 41 | 42 | -------------------------------------------------------------------------------- /python/Makefile: -------------------------------------------------------------------------------- 1 | help: 2 | @echo " env create a development environment using virtualenv" 3 | @echo " deps install dependencies" 4 | @echo " clean remove unwanted stuff" 5 | @echo " test run tests" 6 | 7 | env: 8 | sudo easy_install pip && \ 9 | pip install virtualenv && \ 10 | virtualenv env && \ 11 | . env/bin/activate && \ 12 | make deps 13 | 14 | deps: 15 | pip install -r requirements.txt --use-mirrors 16 | 17 | clean: 18 | rm -fr build 19 | rm -fr dist 20 | find . -name '*.pyc' -exec rm -f {} \; 21 | find . -name '*.pyo' -exec rm -f {} \; 22 | find . -name '*~' -exec rm -f {} \; 23 | 24 | test: 25 | nosetests 26 | 27 | build: clean 28 | python setup.py sdist 29 | python setup.py bdist_wheel 30 | 31 | upload: clean 32 | python setup.py sdist upload 33 | python setup.py bdist_wheel upload 34 | 35 | -------------------------------------------------------------------------------- /python/README.md: -------------------------------------------------------------------------------- 1 | CRMWebAPI Python 2 | ================ 3 | 4 | ## Installation 5 | 6 | ### From PyPI 7 | 8 | `pip install crmwebapi` (future) 9 | 10 | ### From sources 11 | 12 | `python setup.py install` 13 | 14 | ## Usage example 15 | 16 | from crmwebapi import CRMWebAPI 17 | 18 | api = CRMWebAPI({ 19 | 'AccessToken': 'token', 20 | 'APIUrl': 'https://test.crm.dynamics.com/api/data/v8.0/'}) 21 | id = api.create('accounts', {'name': 'testpy2'}) 22 | ent = api.get('accounts', id) 23 | upid = api.update('accounts', id, {'name': 'testpy2up'}) 24 | 25 | if id != upid['EntityId']: 26 | print('Something went wrong') 27 | 28 | api.delete('accounts', upid['EntityId']) 29 | print(api.execute_function('WhoAmI')) 30 | -------------------------------------------------------------------------------- /python/README.rst: -------------------------------------------------------------------------------- 1 | CRMWebAPI Python 2 | ================ 3 | 4 | Usage example 5 | 6 | from crmwebapi import CRMWebAPI 7 | 8 | api = CRMWebAPI({ 9 | 'AccessToken': 'token', 10 | 'APIUrl': 'https://test.crm.dynamics.com/api/data/v8.0/'}) 11 | id = api.create('accounts', {'name': 'testpy2'}) 12 | ent = api.get('accounts', id) 13 | upid = api.update('accounts', id, {'name': 'testpy2up'}) 14 | 15 | if id != upid['EntityId']: 16 | print('Something went wrong') 17 | 18 | api.delete('accounts', upid['EntityId']) 19 | print(api.execute_function('WhoAmI')) 20 | -------------------------------------------------------------------------------- /python/crmwebapi/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """A library that provides a Python interface to the CRM Web API""" 4 | from __future__ import absolute_import 5 | 6 | __author__ = '' 7 | __version__ = '1.0' 8 | 9 | import json # noqa 10 | from .crmwebapi import CRMWebAPI # noqa -------------------------------------------------------------------------------- /python/setup.cfg: -------------------------------------------------------------------------------- 1 | [check-manifest] 2 | ignore = 3 | violations.flake8.txt 4 | 5 | [flake8] 6 | ignore = E111,E124,E126,E201,E202,E221,E241,E302,E501 7 | -------------------------------------------------------------------------------- /python/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | '''The setup and build script for the python-crmwebapi library.''' 4 | 5 | import os 6 | 7 | from setuptools import setup, find_packages 8 | 9 | def read(*paths): 10 | """Build a file path from *paths* and return the contents.""" 11 | with open(os.path.join(*paths), 'r') as f: 12 | return f.read() 13 | 14 | setup( 15 | name='xrm-tools-crmwebapi', 16 | version='1.0', 17 | author='Xrm.Tools', 18 | author_email='', 19 | license='MIT', 20 | url='https://github.com/davidyack/Xrm.Tools.CRMWebAPI', 21 | keywords='crmwebapi', 22 | description='A Python version of CRMWebAPI', 23 | long_description=(read('README.rst')), 24 | packages=find_packages(exclude=['tests*']), 25 | install_requires=['future', 'requests'], 26 | classifiers=[ 27 | 'Development Status :: 5 - Production/Stable', 28 | 'Intended Audience :: Developers', 29 | 'License :: OSI Approved :: Apache Software License', 30 | 'Operating System :: OS Independent', 31 | 'Topic :: Software Development :: Libraries :: Python Modules', 32 | 'Topic :: Internet', 33 | 'Programming Language :: Python', 34 | 'Programming Language :: Python :: 2', 35 | 'Programming Language :: Python :: 2.7', 36 | 'Programming Language :: Python :: 3', 37 | 'Programming Language :: Python :: 3.5', 38 | ], 39 | ) 40 | 41 | --------------------------------------------------------------------------------