Giter Site home page Giter Site logo

davidyack / xrm.tools.crmwebapi Goto Github PK

View Code? Open in Web Editor NEW
143.0 33.0 72.0 16.26 MB

This is an API helper for working with the Common Data Service (CDS) Web API

License: MIT License

PowerShell 3.24% C# 19.03% HTML 4.25% JavaScript 68.50% Makefile 0.15% Python 2.59% PHP 2.23%

xrm.tools.crmwebapi's Introduction

This is an API helper for working with the Common Data Service (CDS) and Dynamics 365 Web API

Design goals include

  • Lightweight
  • Simple API signatures as similar as possible across languages
  • Integrate well with Azure Active Directory / Authentication libraries but don't bake them in
  • JavaScript library to work from web resource or external application

There are versions of the API for .NET, JavaScript, Node, Python and PHP with Java coming soon

Feedback and contributions welcome...if you are going to propose major changes open an issue first to discuss the change.

xrm.tools.crmwebapi's People

Contributors

ashlega avatar daryllabar avatar davidyack avatar r10v avatar rafaelcavazza avatar rdeveen avatar trustantialjake avatar wintg-zns avatar xosevilla avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xrm.tools.crmwebapi's Issues

Error when Using Execute Action

Hello I am having an error when using the execute action method in the Node.js package. I am unable to determine if the error is due to the package or my setup.

When using execute action with the QualifyLead action I receive the following error response

{ response: '{\r\n  "error":{\r\n    "code":"","message":"Request message has unresolved parameters.","innererror":{\r\n      "message":"Request message has unresolved parameters.","type":"Microsoft.Crm.CrmHttpException","stacktrace":"   at Microsoft.Crm.Extensibility.OData.CrmODataRoutingConvention.SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup`2 actionMap)\\r\\n   at System.Web.OData.Routing.ODataActionSelector.SelectAction(HttpControllerContext controllerContext)\\r\\n   at System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)\\r\\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"\r\n    }\r\n  }\r\n}',
  headers: 
   { 'cache-control': 'no-cache',
     pragma: 'no-cache',
     'content-type': 'application/json; odata.metadata=minimal',
     expires: '-1',
     server: 'Microsoft-IIS/8.5',
     req_id: 'd209d3a2-2193-4398-aaca-9f1564efc916',
     'odata-version': '4.0',
     'x-aspnet-version': '4.0.30319',
     'x-powered-by': 'ASP.NET',
     date: 'Mon, 02 Jan 2017 21:10:56 GMT',
     connection: 'close',
     'content-length': '719',
     'set-cookie': [ 'crmf5cookie=!PW41x9uFy6IZ3b+9a0vrIWFrFaeDpFUcsH/WFpVQKiR8r7ngE7eQgT9vpXiS7XbW7Nq/92zrL/wtkiM=;secure; path=/' ],
     'strict-transport-security': 'max-age=31536000; includeSubDomains' } }

I have setup the parameters using the following page as a guide.

https://msdn.microsoft.com/en-us/library/mt491164.aspx

below is the code I am running with sensitive data redacted.

var CRMWebAPI = require('CRMWebAPI');

var apiconfig = { APIUrl: 'https://myorghere.crm.dynamics.com/api/data/v8.0/', AccessToken: "access_token_here"};

var crmAPI = new CRMWebAPI(apiconfig);

console.log('hello')

var queryOptions = { 
    Top:10,
   // Select:['firstname', 'statecode'],
    Filter: "_createdby_value eq <userid>"
    //Filter: "statecode eq 0"
}


crmAPI.GetList('leads', queryOptions).then((response)=>{
               //console.log(response); 
               //using 4th index as I know it is an unqualified lead. This is for testing.
               var id = response.List[3].leadid;
               
               var params = {
                   "CreateAccount": false,
                   "CreateContact": true,
                   "CreateOpportunity":false,
                   "OpportunityCurrencyId":"currency_id_here",
                   "OpportunityCustomerId":null,
                   "SourceCampaignId":null,
                   "Status": 3,
                   "ProcessInstanceId":id
               };
               
               
               
               crmAPI.ExecuteAction('Microsoft.Dynamics.CRM.QualifyLead', params, 'leads' , id).then(function(res){
                   console.log(res);
               }).catch((error)=>{
                   console.log(error)
               })
             
                
            }).catch((error)=>{
                
                console.log(error)
            })

Any help you could provide I greatly appreciate.

If the error is with my setup and not with the package I apologize for the issue in advance.

.Net Core Example Does Not Compile

public static CRMWebAPI GetAPI()
{
     string authority = "https://login.microsoftonline.com/common";
     string clientId = "<clientid>";
     string crmBaseUrl = "https://xx.crm.dynamics.com";
     var authContext = new AuthenticationContext(authority);
     UserCredential userCreds = new UserCredential("userEmail", "userPassword");
     var result = authContext.AcquireToken(crmBaseUrl, clientId, userCreds);
     CRMWebAPI api = new CRMWebAPI(crmBaseUrl + "/api/data/v8.0/", result.AccessToken);
     return api;
}

I tried this on .Net Core 2 today and
UserCredential userCreds = new UserCredential("userEmail", "userPassword");
No longer has a constructor that accepts a username and password.

Delete Field syntax?

Refer to this article:

Looks like clearing (aka nulling, aka deleting) a field in CRM isn't always possible with the patch request (I believe this is only for Entity-References). The DeleteAssociation appears to implement this using the Delete call which I believe to be correct and a requirement for N:N, but for N:1, I don't believe as much information is required. Just the field and $ref "/api/data/v8.0/accounts(1DD18913-11CB-E511-80D2-C4346BDC11C1)/primarycontactid/$ref"

Could this shorter syntax get added to the library?

If you'd like me to just submit a PR, let me know.

Java Port

Does the Java Api have a release date?
I can help you with the Java Api, if you want :)

Thanks.

parameter formatting in ExecuteFunctions adds quotes and sometimes you don't want them

I was issuing a Rollup function call and passing in an enum type that needs to format to @pX=Microsoft.Dynamics.CRM.RollupType'Extended' but the function is adding the quotes in where it should not. Probably the best way to code this is to see if there are quotes in it already meaning that's already quoted/qualified or allow a function in its place that evaluates to the proper value to insert into the query parameter value. Otherwise, we have to use a wacky workaround. Related to #38.

Here's the code issue:

(key) {
	var val = parameters[key];
	parmvars.push(key + "=" + "@p" + parmcount.toString());
	f (typeof val === 'string' || val instanceof String) parmvalues.push("@p" + parmcount.toString() + "='" + val + "'");
	    else parmvalues.push("@p" + parmcount.toString() + "=" + val);
	parmcount++;

I worked around this by using:

 function ToString(arg) { this.toString = function() { return arg } }

Then varToPassInParameters = new ToString("blah").

JS namespace

There is no namespace for the JS library, just the "class" name CRMWebAPI.
To reduce risk of "colliding code" it might be better to use a "namespace" for the "class".
Perhaps something like this?

if (typeof (ColoradoTech) === "undefined") { ColoradoTech = {}; }
if (typeof (ColoradoTech.Xrm) === "undefined") { ColoradoTech.Xrm = {}; }
if (typeof (ColoradoTech.Xrm.Tools) === "undefined") { ColoradoTech.Xrm.Tools = {}; }
ColoradoTech.Xrm.Tools.CRMWebAPI = (function () {
  ...
})();

The call to construct an instance would then be
var crmAPI = new ColoradoTech.Xrm.Tools.CRMWebAPI(apiconfig);

Update fails when passing false as upsert parameter

When expecting to perform an update only, passing false as the upsert parameter causes an exception of 'Id ... already exists'.

When passing false the header is 'If-None-Match', shouldn't this be 'If-Match'?

Create method on CRMWebAPI class returns an empty guid when there are uppercase characters in the CRM WebAPI URL

Create method on the CRMWebAPI class returns an empty Guid when there are uppercase characters in the CRM WebAPI URL

This was tested using .net core class library and problem is most likely related to the following helper method:
private static Guid GetEntityIDFromResponse(string fullUrl, HttpResponseMessage response)

as the logic in the helper relies on the fullUrl.ToLower() string:
idString = idString.Replace(fullUrl.ToLower(), "").Replace("(", "").Replace(")", "");

Workaround:
When initiating the CRMWebAPI instance, provide the CRM WebAPI URL in lowercase only.

.NET WebApi Authentication with ADFS and OnPremise

Hi there,

i would like to use this library for an OnPremise Installation with AD FS 3.0, but it doesn't work for me.
If I am using somthing like this:

public CRMWebAPI GetAPI()
{
     CRMWebAPI api = new CRMWebAPI("https://server/Instance/api/data/v8.2/", CredentialCache.DefaultNetworkCredentials);
     return api;
}

The HttpResponse is the html of the AD FS page which want me to Login.
Is it generally possible in this constelation to use this library and what I have to do that it works?

Thanks for your help
Markus

Make a TypeScript version

This would fulfill #19 too I think. Since this already looks like a class output from typescript, maybe you have that already, otherwise I would suggest to make one in conjunction with the xrm.d.ts from definitely typed.

GetList results in a 404 - 'File or directory not found' excepttion for too many columns

Odd behaviour , running against an IFD, account query with more than 22 columns causes a 404, same against contacts, allowed more columns but same result:

` [TestClass]
public class GetListTest : UnitTestBaseClass
{
[TestMethod]
public void TestMethod1()
{

        Task.Run(async () =>
        {
            var api = GetAPI();

            string entitySet = "accounts";
            string selectAttributes = "<attribute name='accountid'/><attribute name='name'/><attribute name='emailaddress1'/><attribute name='websiteurl'/><attribute name='telephone1'/><attribute name='fax'/><attribute name='accountnumber'/><attribute name='address1_line1'/><attribute name='address1_line2'/><attribute name='address1_line3'/><attribute name='address1_city'/><attribute name='address1_postalcode'/><attribute name='address1_country'/><attribute name='address2_line1'/><attribute name='address2_line2'/><attribute name='address2_city'/><attribute name='address2_postalcode'/><attribute name='address2_country'/><attribute name='parentaccountid'/><attribute name='primarycontactid'/><attribute name='statecode'/><attribute name='statuscode'/>";
            selectAttributes += "<attribute name='telephone2'/>"; // Any extra field causes a 404

            string fetchXml = "<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='true'>\r\n                                              <entity name='account'>\r\n                                                <filter type='and'>\r\n                                                  <condition attribute='primarycontactid' operator='eq' value='74eaeb77-e23b-e811-a9a7-000d3af3c361' />\r\n                                                </filter>\r\n                                              </entity>\r\n                                            </fetch>";

            CRMGetListOptions queryOptions = null;
            if (fetchXml != null)
            {
                queryOptions = new CRMGetListOptions { FetchXml = WebUtility.UrlEncode(FetchXmlWithSelectAttributes(fetchXml, selectAttributes)) };
            }
            var getListResult = await api.GetList(entitySet, QueryOptions: queryOptions);
            var list = getListResult.List;
     
        }).Wait();

    }


    private static string FetchXmlWithSelectAttributes(string fetchXml, string selectAttributes)
    {
        string entityTagPattern = @"<entity\s+name='\w+'\s*>";
        string entityTag = "";
        Regex regex = new Regex(entityTagPattern);
        Match matchResult = regex.Match(fetchXml);
        if (matchResult.Success)
        {
            entityTag = matchResult.Value;
        }

        int entityTagEndIndex = fetchXml.IndexOf(entityTag) + entityTag.Length;
        return fetchXml.Substring(0, entityTagEndIndex) + selectAttributes + fetchXml.Substring(entityTagEndIndex);
    }


}`

Message: Test method Xrm.Tools.WebAPI.Test.GetListTest.GetListTest threw exception:
System.AggregateException: One or more errors occurred. ---> Xrm.Tools.WebAPI.Results.CRMWebAPIException: HTML Error Content:

<title>404 - File or directory not found.</title> <style type="text/css"> </style>

Server Error

404 - File or directory not found.

The resource you are looking for might have been removed, had its name changed, or is temporarily unavailable.

ExecuteAction is not working in JS

Hello,

I'm using your CRMWebAPI in JS and i want to use the function "ExecuteAction". I have created the following lines of code :

TestFunction: function (isoCode,phone_number)
{
var params = {
"PhoneNumber": phone_number,
"Country": isoCode
};

    Infront.account.CrmApi().ExecuteAction("ng_AccountValidatePhoneNumber", params).then(function (r) {
        alert(r);
    }, function (e) {
        alert(e);
    });
}

But when the code is executed i get the following error : Resource not found for the segment 'ng_AccountValidatePhoneNumber'.

What i'm doing wrong ? Are there more examples of using an action ?

Kind regards,

Sigurd Geerts

Load Promise if missing

IE11 does not support promises OoB, so it would be great if it could be loaded by the CRMWebAPI if needed.
Perhaps something like this in the "constructor"?

   if (typeof (Promise) === "undefined") {
       LoadPromise();  // Some method loading from promisejs.org
   }

QueryOptions needs to accommodate following an entity property

If I want to follow a property from an entity you need to add something Path to the QueryOptions:

..._BuildQueryURL...
     const path = (queryOptions && queryOptions.Path) ? 
                     queryOptions.Path.map(part => 
                         typeof part === 'string' ?
                                                 `/${part}` :
                                                 `/${part.Name}` + (part.Type ? `/${part.Type}` : "")
                     ): []
        let fullurl = config.APIUrl + uri + (path.length > 0 ? path.join("/"):"")

The query parameter $fetchXml is not supported

I getting the following error

The query parameter $fetchXml is not supported

It happens when I set any other CRMGetListOptions along with the FetchXml option.

var results = await _api.GetList("lmnz_memberships", new CRMGetListOptions
{
    FetchXml = fetchXml,
    IncludeCount = true
});

If I only set FetchXml it works.

var results = await _api.GetList("lmnz_memberships", new CRMGetListOptions
{
    FetchXml = fetchXml,
});

I believe is has to do with the firstParam variable in the CRMWebAPI class (line 763).

if (firstParam)
    fullurl = fullurl + string.Format("?fetchXml={0}", Uri.EscapeUriString(queryOptions.FetchXml));
else
    fullurl = fullurl + string.Format("&$fetchXml={0}", Uri.EscapeUriString(queryOptions.FetchXml));

Out of curiosity, what is the reason for the firstParam variable?

Thanks!

Error with ExecuteAction

I'm getting an error when I execute the action associated with running a full-text search on the KnowledgeArticle entities:

function getArticles(phrase, fn) {
    var action = "FullTextSearchKnowledgeArticle";
    var params = {
        'SearchText': phrase,
        'StateCode': 1,
        'QueryExpression': {
            'ColumnSet': ['title', 'description', 'articlepublicnumber'],
            'EntityName' : 'knowledgearticle'
        }
    };
    crmApi.ExecuteAction(action, params).then(function(r) {
        fn(r);
    }, function(e) {
        logError('getArticles', e);
    });
}

The error returned is:

The property 'ColumnSet' does not exist on type 'Microsoft.Dynamics.CRM.QueryBase'. Make sure to only use property names that are defined by the type.

What I need to be able to do is specify the QueryExpression parameter as a type Microsoft.CRM.Dynamics.QueryExpression instead of it's base class, Microsoft.Dynamics.CRM.QueryBase.

Any ideas on how to do this? Hopefully I'm just missing something that should be obvious...

Creating a Lookup to existing entity

Hi

I am trying to create an entity, but give it a lookup to an existing entity.

Is this possible? Currently the Create is also trying to generate the lookup entity, which fails as a key already exists.

Thanks

Promises for IE 11

Since this is not supported in IE 11 how do I make this work in your code?

Thanks

JS code formatting

This is not really an "issue", but I don't see any discussion links such as Gitter (recommended!) for this repository.

I notice that when I open CRMWebAPI.js in Visual Studio and hit the Format Document menu a few changes are made. So which formatting standard should be used for this file?

image

Clear Lookup Value with Update function

Hi, I'm trying to remove a lookup value with Update function, it's not causing any error but it did not clear the field as Well.

Snippet:
var lookupString ;
u["[email protected]"] = lookupString;
crmAPI.Update("gdi_valeur_extrants", data.model.gdi_valeur_extrantid, u).then(function(){

                   },
                     function (error) {
                         alert(error.responseText);
                     });

I'm wondering if I could use the DeleteAssociation function instead of Update when I need to do this kind of action.

JS - Simplify Build Query Method

CRMWebAPI.prototype._BuildQueryURL = function (uri, queryOptions, config) {
var fullurl = config.APIUrl + uri;
var qs = [];

if (queryOptions != null) {
if (queryOptions.Select != null) qs.push("$select=" + queryOptions.Select.join(","));
if (queryOptions.OrderBy != null) qs.push("$orderby=" + queryOptions.OrderBy.join(","));
if (queryOptions.Filter != null) qs.push("$filter=" + queryOptions.Filter);
if (queryOptions.Filter != null) qs.push("$filter=" + queryOptions.Filter);
if (queryOptions.IncludeCount) qs.push("$count=true");
if (queryOptions.Skip > 0) qs.push("skip=" + queryOptions.Skip);
if (queryOptions.Top > 0) qs.push("$top=" + queryOptions.Top);
if (queryOptions.SystemQuery != null) qs.push("savedQuery=" + queryOptions.SystemQuery);
if (queryOptions.UserQuery != null) qs.push("userQuery=" + queryOptions.UserQuery);
if (queryOptions.FetchXml != null) qs.push("fetchXml=" + encodeURI(queryOptions.FetchXml));
}
if (qs.length > 0) fullurl += "?" + qs.join("&")
return fullurl;
};

Format CRM Response

Hi!

Have you considered using some sort of return object?

The Dynamic object is great for converting into JSON and sending data, but it complicated when we need to check if some field is present.

Something like the current SDK, using a dictionary internaly, so we can check is some attribute existe ou even have somethin like:

object.GetAttributeValue<T>("name")
or
object["name"] ;

Returning de default T value if the attribute dosen't exist.

Thanks!

The CRMWebAPI Create method doesn't return an entity record guid if the CRM WebAPI URL is slightly different than the one returned in http response

The CRMWebAPI Create method doesn't return an entity record guid if the CRM Web API URL contains duplicated backslashes or additional trailing backslash. However, please note that the records are actually created in CRM in such cases.

I suggest to change the below logic to e.g. regex:

private static Guid GetEntityIDFromResponse(string fullUrl, HttpResponseMessage response)
        {
           ...

            //Looks like this requires ToLower for idString - otherwise, it does not work when there is an uppercase character
            //in the original web api url
            idString = idString.ToLower().Replace(fullUrl.ToLower(), "").Replace("(", "").Replace(")", "");
            
            var idGuid = Guid.Empty;
            //if alternate key was used to perform an upsert, guid not currently returned
            //the call returns the alternate key which is not in guid format
            Guid.TryParse(idString, out idGuid);
           
            return idGuid;
        }

https://github.com/davidyack/Xrm.Tools.CRMWebAPI/blob/master/dotnet/Xrm.Tools.WebAPI/CRMWebAPI.cs

Calling Global Custom Actions

I'm having issue when trying to call a global custom action. I don't know if it is because I'm not using the tool properly or not. Error message is :

An unexpected 'PrimitiveValue' node was found when reading from the JSON reader. A 'StartObject' node was expected.","innererror":{\r\n "message":"An unexpected 'PrimitiveValue' node was found when reading from the JSON reader. A 'StartObject' node was expected.","type":"Microsoft.Crm.CrmHttpException","stacktrace":" at Microsoft.Crm.Extensibility.OData.CrmODataUtilities.ValidateInputParameters(ModelStateDictionary controllerModelState)\r\n

Guidance on WebAPI

Hi David,

This is not about any issue in CRMWebAPI but rather a discussion on it. I'm looking for some guidance for real world applications that currently use the SOAP endpoint to eventually switch to WebAPI. Right now, looking at the SDK samples and this WebAPI, it appears the solution won't look clean, everything is pretty loosely coupled. Also, it appears to be more work will need to do done to process the "Messages"/Requests WinOpportunity, QualifyLead among others, as you have to create the request yourself and load in the parameters. The OData style queries in code, it's a mess. Your solution is the only one I came across to do bulk Create/Update operations using MultipartContent.

I'm not sure what feedback Microsoft CRM team is getting but I don't think they should remove the 2011 endpoint.

Your thoughts?

Entities Extraction By WebAPI

A Cool improvement to this library is an entity extraction tool because the models from CrmSvcUtil are dirty with not used properties and inherited from base SDK entities.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.