Thursday, April 28, 2011

How To: The Microsoft Dynamics CRM 2011 Style Guide

I have seen several posts in the forums recently about styling or theming CRM 2011.  I just want to mention a few things about this and the role of the CRM 2011 Style Guide included in the SDK in the sdk\resources\styleguide folder.  I was surprised at how little documentation I could find about it's use outside of the e-learning training for the customization Exam for CRM 4.0

What it is:
The styleguide is a collection of CSS style sheets and diagrams showing what styles, fonts, spacings, etc... are used within the CRM application.  This allows a developer or designer to recreate the look and feel of the CRM application in custom applications that may be integrated with CRM.  This gives the user a more seamless experience that looks congruent with the experience you get from working within the CRM application.

What it isn't:
A way to style or theme the CRM application itself.


Bottom Line:
Most custom styling that you can accomplish through any code means (other than using explicit settings in the GUI) is unsupported and could affect the way CRM functions.  These types of customizations could be blown away by a rollup update or future upgrade; or worse, if a rollup or upgrade changed the way the CRM page structure functioned, it might break your CRM form.  I have also seen people who have wondering about supposed themes for CRM, the two people I have heard this from were really looking at Outlook themes that can be used in Outlook (which may or may not have the CRM for Outlook client installed).  There is no supported way to "theme" the application.

I hope this helps!

-

Tuesday, April 26, 2011

How to: Use Retrieve Messages in Jscript and .NET With the Microsoft Dynamics CRM 2011 SDK

Here is a quick demo on how to utilize the Retrieve message of the CRM 2011 Organization service in both C# and Jscript. I will provide two examples.  The first is a simple retrieve of a single entity by it's id.  The second retrieve request will navigate a relationship to retrieve not only the same contact entity, but also all the accounts for which that contact is associated.

CALL # 1



The first call will just be a simple retrieve that returns a contact entity based on it's ID GUID.
NOTE: In .NET you can then examine the Entity attribute of the response to get the main entity, and also iterate through the Entity.RelatedEntities attribute to access the related accounts.
First in C#:


      RetrieveRequest req = new RetrieveRequest();
      req.ColumnSet = new ColumnSet(true);
      req.Target = new EntityReference
      {
          Id = new Guid("007889EB-0B70-E011-8DD8-1CC1DEE8EA59"),
          LogicalName = "contact"

      };
      RetrieveResponse response = (RetrieveResponse)service.Execute(req);


Now here is the Jscript nicely formatted by the CRM 2011 SOAP formatter. Available at: http://crm2011soap.codeplex.com/

To understand how to parse the response please review my post on using the DOM parser.
http://mileyja.blogspot.com/2011/03/microsoft-dynamics-crm-2011-parsing.html

This example is asynchronous, if you want to learn how to make JScript SOAP calls synchronously please visit this posthttp://mileyja.blogspot.com/2011/07/using-jscript-to-access-soap-web.html



//main entry point
function runme() {
   SDK.SAMPLES.RetrieveContactRequest();
}

if (typeof (SDK) == "undefined")
   { SDK = { __namespace: true }; }
       //This will establish a more unique namespace for functions in this library. This will reduce the 
       // potential for functions to be overwritten due to a duplicate name when the library is loaded.
       SDK.SAMPLES = {
           _getServerUrl: function () {
               ///<summary>
               /// Returns the URL for the SOAP endpoint using the context information available in the form
               /// or HTML Web resource.
               ///</summary>
               var OrgServicePath = "/XRMServices/2011/Organization.svc/web";
               var serverUrl = "";
               if (typeof GetGlobalContext == "function") {
                   var context = GetGlobalContext();
                   serverUrl = context.getServerUrl();
               }
               else {
                   if (typeof Xrm.Page.context == "object") {
                         serverUrl = Xrm.Page.context.getServerUrl();
                   }
                   else
                   { throw new Error("Unable to access the server URL"); }
                   }
                  if (serverUrl.match(/\/$/)) {
                       serverUrl = serverUrl.substring(0, serverUrl.length - 1);
                   } 
                   return serverUrl + OrgServicePath;
               }, 
           RetrieveContactRequest: function () {
               var requestMain = ""
               requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
               requestMain += "  <s:Body>";
               requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
               requestMain += "      <request i:type=\"a:RetrieveRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">";
               requestMain += "        <a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>Target</b:key>";
               requestMain += "            <b:value i:type=\"a:EntityReference\">";
               requestMain += "              <a:Id>007889eb-0b70-e011-8dd8-1cc1dee8ea59</a:Id>";
               requestMain += "              <a:LogicalName>contact</a:LogicalName>";
               requestMain += "              <a:Name i:nil=\"true\" />";
               requestMain += "            </b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>ColumnSet</b:key>";
               requestMain += "            <b:value i:type=\"a:ColumnSet\">";
               requestMain += "              <a:AllColumns>true</a:AllColumns>";
               requestMain += "              <a:Columns xmlns:c=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\" />";
               requestMain += "            </b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "        </a:Parameters>";
               requestMain += "        <a:RequestId i:nil=\"true\" />";
               requestMain += "        <a:RequestName>Retrieve</a:RequestName>";
               requestMain += "      </request>";
               requestMain += "    </Execute>";
               requestMain += "  </s:Body>";
               requestMain += "</s:Envelope>";
               var req = new XMLHttpRequest();
               req.open("POST", SDK.SAMPLES._getServerUrl(), true)
               // Responses will return XML. It isn't possible to return JSON.
               req.setRequestHeader("Accept", "application/xml, text/xml, */*");
               req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
               req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
               var successCallback = null;
               var errorCallback = null;
               req.onreadystatechange = function () { SDK.SAMPLES.RetrieveContactResponse(req, successCallback, errorCallback); };
               req.send(requestMain);
           },
       RetrieveContactResponse: function (req, successCallback, errorCallback) {
               ///<summary>
               /// Recieves the assign response
               ///</summary>
               ///<param name="req" Type="XMLHttpRequest">
               /// The XMLHttpRequest response
               ///</param>
               ///<param name="successCallback" Type="Function">
               /// The function to perform when an successfult response is returned.
               /// For this message no data is returned so a success callback is not really necessary.
               ///</param>
               ///<param name="errorCallback" Type="Function">
               /// The function to perform when an error is returned.
               /// This function accepts a JScript error returned by the _getError function
               ///</param>
               if (req.readyState == 4) {
               if (req.status == 200) {
               if (successCallback != null)
               { successCallback(); }
               }
               else {
                   errorCallback(SDK.SAMPLES._getError(req.responseXML));
               }
           }
       },
       _getError: function (faultXml) {
           ///<summary>
           /// Parses the WCF fault returned in the event of an error.
           ///</summary>
           ///<param name="faultXml" Type="XML">
           /// The responseXML property of the XMLHttpRequest response.
           ///</param>
           var errorMessage = "Unknown Error (Unable to parse the fault)";
           if (typeof faultXml == "object") {
               try {
                   var bodyNode = faultXml.firstChild.firstChild;
                   //Retrieve the fault node
                   for (var i = 0; i < bodyNode.childNodes.length; i++) {
                       var node = bodyNode.childNodes[i];
                       //NOTE: This comparison does not handle the case where the XML namespace changes
                       if ("s:Fault" == node.nodeName) {
                       for (var j = 0; j < node.childNodes.length; j++) {
                           var faultStringNode = node.childNodes[j];
                           if ("faultstring" == faultStringNode.nodeName) {
                               errorMessage = faultStringNode.text;
                               break;
                           }
                       }
                       break;
                   }
               }
           }
           catch (e) { };
        }
        return new Error(errorMessage);
     },
 __namespace: true
};


CALL # 2


The sample call I will use will retrieve a contact entity and all related account entities based on the "contact_customer_accounts" relationship.

NOTE: In .NET you can then examine the Entity attribute of the response to get the main entity, and also iterate through the Entity.RelatedEntities attribute to access the related accounts.
First in C#:

RetrieveRequest req = new RetrieveRequest();

      QueryExpression query = new QueryExpression();
      query.EntityName = "account";
      query.ColumnSet = new ColumnSet(true);
      Relationship relationship = new Relationship();

      query.Criteria = new FilterExpression();
      // name of relationship between team & systemuser
      relationship.SchemaName = "contact_customer_accounts";
      RelationshipQueryCollection relatedEntity = new RelationshipQueryCollection();
      relatedEntity.Add(relationship, query);
      RetrieveRequest request = new RetrieveRequest();
      request.RelatedEntitiesQuery = relatedEntity;
      request.ColumnSet = new ColumnSet(true);
      request.Target = new EntityReference
      {
          Id = new Guid("007889EB-0B70-E011-8DD8-1CC1DEE8EA59"),
          LogicalName = "contact"

      };
      RetrieveResponse response = (RetrieveResponse)service.Execute(request);

Now here is the Jscript nicely formatted by the CRM 2011 SOAP formatter. Available at: http://crm2011soap.codeplex.com/

To understand how to parse the response please review my post on using the DOM parser.
http://mileyja.blogspot.com/2011/03/microsoft-dynamics-crm-2011-parsing.html



//main entry point
function runme() {
   SDK.SAMPLES.RetrieveRelatedContactsRequest();
}

if (typeof (SDK) == "undefined")
   { SDK = { __namespace: true }; }
       //This will establish a more unique namespace for functions in this library. This will reduce the 
       // potential for functions to be overwritten due to a duplicate name when the library is loaded.
       SDK.SAMPLES = {
           _getServerUrl: function () {
               ///<summary>
               /// Returns the URL for the SOAP endpoint using the context information available in the form
               /// or HTML Web resource.
               ///</summary>
               var OrgServicePath = "/XRMServices/2011/Organization.svc/web";
               var serverUrl = "";
               if (typeof GetGlobalContext == "function") {
                   var context = GetGlobalContext();
                   serverUrl = context.getServerUrl();
               }
               else {
                   if (typeof Xrm.Page.context == "object") {
                         serverUrl = Xrm.Page.context.getServerUrl();
                   }
                   else
                   { throw new Error("Unable to access the server URL"); }
                   }
                  if (serverUrl.match(/\/$/)) {
                       serverUrl = serverUrl.substring(0, serverUrl.length - 1);
                   } 
                   return serverUrl + OrgServicePath;
               }, 
           RetrieveRelatedContactsRequest: function () {
               var requestMain = "";
               requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
               requestMain += "  <s:Body>";
               requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
               requestMain += "      <request i:type=\"a:RetrieveRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">";
               requestMain += "        <a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>Target</b:key>";
               requestMain += "            <b:value i:type=\"a:EntityReference\">";
               requestMain += "              <a:Id>007889eb-0b70-e011-8dd8-1cc1dee8ea59</a:Id>";
               requestMain += "              <a:LogicalName>contact</a:LogicalName>";
               requestMain += "              <a:Name i:nil=\"true\" />";
               requestMain += "            </b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>ColumnSet</b:key>";
               requestMain += "            <b:value i:type=\"a:ColumnSet\">";
               requestMain += "              <a:AllColumns>true</a:AllColumns>";
               requestMain += "              <a:Columns xmlns:c=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\" />";
               requestMain += "            </b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>RelatedEntitiesQuery</b:key>";
               requestMain += "            <b:value i:type=\"a:RelationshipQueryCollection\">";
               requestMain += "              <a:KeyValuePairOfRelationshipQueryBaseX_PsK4FkN>";
               requestMain += "                <b:key>";
               requestMain += "                  <a:PrimaryEntityRole i:nil=\"true\" />";
               requestMain += "                  <a:SchemaName>contact_customer_accounts</a:SchemaName>";
               requestMain += "                </b:key>";
               requestMain += "                <b:value i:type=\"a:QueryExpression\">";
               requestMain += "                  <a:ColumnSet>";
               requestMain += "                    <a:AllColumns>true</a:AllColumns>";
               requestMain += "                    <a:Columns xmlns:c=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\" />";
               requestMain += "                  </a:ColumnSet>";
               requestMain += "                  <a:Criteria>";
               requestMain += "                    <a:Conditions />";
               requestMain += "                    <a:FilterOperator>And</a:FilterOperator>";
               requestMain += "                    <a:Filters />";
               requestMain += "                  </a:Criteria>";
               requestMain += "                  <a:Distinct>false</a:Distinct>";
               requestMain += "                  <a:EntityName>account</a:EntityName>";
               requestMain += "                  <a:LinkEntities />";
               requestMain += "                  <a:Orders />";
               requestMain += "                  <a:PageInfo>";
               requestMain += "                    <a:Count>0</a:Count>";
               requestMain += "                    <a:PageNumber>0</a:PageNumber>";
               requestMain += "                    <a:PagingCookie i:nil=\"true\" />";
               requestMain += "                    <a:ReturnTotalRecordCount>false</a:ReturnTotalRecordCount>";
               requestMain += "                  </a:PageInfo>";
               requestMain += "                  <a:NoLock>false</a:NoLock>";
               requestMain += "                </b:value>";
               requestMain += "              </a:KeyValuePairOfRelationshipQueryBaseX_PsK4FkN>";
               requestMain += "            </b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "        </a:Parameters>";
               requestMain += "        <a:RequestId i:nil=\"true\" />";
               requestMain += "        <a:RequestName>Retrieve</a:RequestName>";
               requestMain += "      </request>";
               requestMain += "    </Execute>";
               requestMain += "  </s:Body>";
               requestMain += "</s:Envelope>";
               var req = new XMLHttpRequest();
               req.open("POST", SDK.SAMPLES._getServerUrl(), true)
               // Responses will return XML. It isn't possible to return JSON.
               req.setRequestHeader("Accept", "application/xml, text/xml, */*");
               req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
               req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
               var successCallback = null;
               var errorCallback = null;
               req.onreadystatechange = function () { SDK.SAMPLES.RetrieveRelatedContactsResponse(req, successCallback, errorCallback); };
               req.send(requestMain);
           },
       RetrieveRelatedContactsResponse: function (req, successCallback, errorCallback) {
               ///<summary>
               /// Recieves the assign response
               ///</summary>
               ///<param name="req" Type="XMLHttpRequest">
               /// The XMLHttpRequest response
               ///</param>
               ///<param name="successCallback" Type="Function">
               /// The function to perform when an successfult response is returned.
               /// For this message no data is returned so a success callback is not really necessary.
               ///</param>
               ///<param name="errorCallback" Type="Function">
               /// The function to perform when an error is returned.
               /// This function accepts a JScript error returned by the _getError function
               ///</param>
               if (req.readyState == 4) {
               if (req.status == 200) {
               //***********************
               //   ALERT RESULT HERE
               //***********************
                    alert(req.responseXML.xml.toString());
               }
               else {
                   errorCallback(SDK.SAMPLES._getError(req.responseXML));
               }
           }
       },
       _getError: function (faultXml) {
           ///<summary>
           /// Parses the WCF fault returned in the event of an error.
           ///</summary>
           ///<param name="faultXml" Type="XML">
           /// The responseXML property of the XMLHttpRequest response.
           ///</param>
           var errorMessage = "Unknown Error (Unable to parse the fault)";
           if (typeof faultXml == "object") {
               try {
                   var bodyNode = faultXml.firstChild.firstChild;
                   //Retrieve the fault node
                   for (var i = 0; i < bodyNode.childNodes.length; i++) {
                       var node = bodyNode.childNodes[i];
                       //NOTE: This comparison does not handle the case where the XML namespace changes
                       if ("s:Fault" == node.nodeName) {
                       for (var j = 0; j < node.childNodes.length; j++) {
                           var faultStringNode = node.childNodes[j];
                           if ("faultstring" == faultStringNode.nodeName) {
                               errorMessage = faultStringNode.text;
                               break;
                           }
                       }
                       break;
                   }
               }
           }
           catch (e) { };
        }
        return new Error(errorMessage);
     },
 __namespace: true
};


Now you can call the runme function from your form jscript handler.
Thats all there is to it!

I hope this helps!

Fixed: Microsoft Dynamics CRM 2011 Jscript Won't Debug, Just Errors!

I ran into an annoying error in Microsoft Dynamics CRM 2011 the other day. It wasn't a big thing but was a pain to figure out and something I can see anyone accidentally doing, so I thought it warranted a blog post.  It seems that I have a strong desire to put opening and closing parenthesis in my Jscript "Function" field for my event handler definitions like this.


If you do this your function won't run.  You can put in "debugger;" statements and it still won't run, nor will it catch your breakpoint.  The preview screen blows up completely.

The solution: Just remove the opening and closing parenthesis from the "Function" name specified above.  It should look like this:



There, now it's all fixed! :)

Monday, April 25, 2011

Storing and Utilizing X509 Certificates in Microsoft Dynamics CRM 2011 Online or On-Premise

I have been working on a project recently where I have been tasked with making secure web service calls using X509 client certificates. This proved to be a semi-daunting task but we soon got it figured out as a team.

Here is how it works:

1. You must first store the X509 certificates as a web resource in CRM. I made a post on storing files of any type as web resources here. http://mileyja.blogspot.com/2011/04/storing-any-file-type-in-microsoft.html

2. Now you must retrieve the content attribute of the web resource and use it to instantiate an X509 certificate. This example retrieves the needed client certificate, and attaches it to the secure call to a web service that requires client-certificate authentication.

  RetrieveMultipleRequest rmr = new RetrieveMultipleRequest();
                        RetrieveMultipleResponse resp = new RetrieveMultipleResponse();
                        Entity wr = new Entity();

                        QueryExpression query = new QueryExpression()
                        {
                            EntityName = "webresource",
                            ColumnSet = new ColumnSet("content"),
                            Criteria = new FilterExpression
                            {
                                FilterOperator = LogicalOperator.And,
                                Conditions = 
                                {
                                    new ConditionExpression
                                    {
                                        AttributeName = "name",
                                        Operator = ConditionOperator.Equal,
                                        Values = { "new_mywebresourcename" }
                                    }
                                }
                            }
                        };

                        rmr.Query = query;
                        resp = (RetrieveMultipleResponse)service.Execute(rmr);
                        wr = (Entity)resp.EntityCollection.Entities[0];
                        byte[] certbytes = Convert.FromBase64String(wr.Attributes["content"].ToString());

                        X509Certificate2 cert = new X509Certificate2(certbytes, "certpassword");

                        //make call
                        using (WebServiceClient client = new WebServiceClient())
                        {
                            

                            client.Url = @"https://domain.com/mysecurewebservice.asmx";
                            client.ClientCertificates.Add(cert);
                            entity.Attributes.Add("description", client.HelloWorld());

                        }

3. Now let's examine the gotcha that was involved in this scenario.

- You have to use the X509Certificate2 class, not the X509Certificate class when you instantiate the certificate from the returned byte array if you intend to use the call in a sandbox environment.

 

 

Thursday, April 21, 2011

Storing any File Type in a Microsoft Dynamics CRM 2011 Solution as a Web Resource

I ran into a situation the other day where I had to store an oddball file type in a CRM solution that was to be reconstituted and used by code within a plugin from CRM Online.  My thought was to store the file as a web resource but quickly realized that there wasn't a file type for my file.  But I still got it in there.

Here's how:

1. Rename the file extension to .xml and choose the XML file type.  

2. It seems that the application doesn't actually check to see if the file type matches within the file and just blindly uploads it.

3. You can now reconstitute the file from a byte array in code by examining the content attribute of that particular webresource entity.  It is base64 encoded (probably to avoid having to use escape sequences), but that is an easy thing to deal with in .NET.  If I spit the byte array out to a file using a stream reader I can verify that the SHA-1 hash of the reconstituted file matches that of the original file, and it does.

Here is what the code looks like to retrieve your file using C#.  In this example we will spit it out to a file.  This code just uses a retrievemultiple to call to get the webresource, decodes the content attribute into an array of bytes and spits it out to a file.

RetrieveMultipleRequest rmr = new RetrieveMultipleRequest();
      RetrieveMultipleResponse resp = new RetrieveMultipleResponse();
      WebResource wr = new WebResource();

      QueryExpression query = new QueryExpression()
      {
          EntityName = "webresource",
          ColumnSet = new ColumnSet("content"),
          Criteria = new FilterExpression
          {
              FilterOperator = LogicalOperator.And,
              Conditions = 
                {
                    new ConditionExpression
                    {
                        AttributeName = "name",
                        Operator = ConditionOperator.Equal,
                        Values = { "new_testwebresource" }
                    }
                }
          }
      };

      rmr.Query = query;
      resp = (RetrieveMultipleResponse)service.Execute(rmr);
      wr = (WebResource)resp.EntityCollection.Entities[0];
      byte[] filebytes = Convert.FromBase64String(wr.Content);
      FileStream fs = new FileStream(@"c:\testfiles\randomfile.ext",FileMode.Create);
      foreach (byte b in filebytes)
      {
          fs.WriteByte(b);
      }
      fs.Close();

I hope this helps!

 

 

Wednesday, April 20, 2011

Microsoft Dynamics CRM 2011 Diagnostic Tool Download

One of the biggest names in CRM tools has released a good platform trace tool for Microsoft Dynamics CRM 2011. We have been waiting for a new platform trace tool for some time.  Here it is:
http://mscrmtools.blogspot.com/2011/04/new-tool-crmdiagtool-2011.html



I hope this helps

Get CRM 2011 CrmSvcUtil.exe and the Plugin Registration Tool to Work With WIF on Windows XP

Microsoft Dynamics CRM 2011 makes heavy use of the new Windows Identity Framework.   This been heavily integrated into most of the tools out there for development with the CRM 2011 platform.  This includes CrmSvcUtil.exe and the new plugin / plug-in registration tool.  This also presents a headache for anyone who would like to do any development for CRM 2011 with a Windows XP machine as WIF will not install on an XP machine.  You need to have Vista SP1+, Windows 7, or Windows Server.

It seems that there is an "unsupported" workaround for this.

1. If you were to happen to navigate to the following folder (C:\Program Files\Reference Assemblies\Microsoft\Windows Identity Foundation) on a supported machine that has the Windows Identity Framework (WIF) already installed you might find some assemblies in the directory structure and it's sub folders.

There are four assemblies in my installation:
- Microsoft.IdentityModel.dll
- Microsoft.IdentityModel.resources.dll
- Microsoft.IdentityModel.WindowsTokenService.dll
- Microsoft.IdentityModel.WindowsTokenService.resources.dll

2. If you were to happen to (accidentally of course) copy these assemblies and move them to the same folder as the CrmSvcUtil.exe file or the executable for the Plugin Registration Tool, they will function normally without needing to install the whole WIF framework package.

To build the plugin registration tool you just copy the 4 assemblies from that folder structure to the bin\debug folder and build the tool using Visual Studio.   It then functions normally.

Here is an example from the forums where someone has gotten this to work for CrmSvcUtil, and I have personally done this for the Plugin Registration Tool.  You will also notice that I was the naysayer in the thread at the time :)
http://social.microsoft.com/Forums/en/crmdevelopment/thread/8d8bd121-a34c-402d-86fd-b3c47709a0b4

I hope this helps!

Monday, April 18, 2011

Plugin Registration Console Application Tool for Microsoft Dynamics CRM 2011.

I like it when people create new tools that make my life easier. The purpose this one is to allow for easy registration and un-registration from a post-build or automated build environment, like TFS or Cruise Control.NET.  It is created by Johan K├╝stner, a name that is new to me.  Keep up the good work!

I recommend checking it out at CodePlex here: http://pluginregcrm2011.codeplex.com/

Here are is instructions:

This tool uses the API provided in the SDK of Microsoft Dynamics CRM 2011:

*Microsoft.Crm.Sdk.Proxy
*Microsoft.Xrm.Sdk

This tool is intended to be compiled by Visuals Studio 2010 within the .NET Framework 4.0 and is intended for Microsoft Dynamics CRM 2011..

The tool exists in a Visual Studio Solution called PluginRegistrationTool.sln and consists of a Console Application Project called PluginRegistrationTool.csproj and a Test Project called PluginRegistrationToolTestProject.csproj.

The tool has the option of using an AssemblyRegistration.xml XML file providing the input parameters with an AssemblyRegistration.xsd schema. The tool also has the option of being called directly from code, as indicated by the Unit Test called RegisterTest in the RegistrationHelperTest Class in the PluginRegistrationToolTestProject Test Project.

It is also possible to add the registered plugins or CWAs to a specific solution, which can be specified in the XML file. This is provided in the SolutionUniqueName node within the relevant Registration node. Each Registration can therefore be linked to a different Solution.

The AssemblyRegistration.xml and AssemblyRegistration.xsd files correlate with the AssemblyRegistration.cs Class in the project.

The AssemblyRegistration XML consists of the following:
  • A AssemblyRegistration node.
  • The AssemblyRegistration has a XrmServerDetails and Registrations node.
  • The XrmServerDetails node consists of a ServerAddress, OrganizationName and XrmCredentials node.
  • The XrmCredentials node consists of a Domain, UserName and Password node.
  • The Registrations node consists of one or more Registration nodes.
  • The Registration node consists of an AssemblyPath, AssemblySourceType, IsolationMode, Steps and SolutionUniqueName node.
  • The Steps node contains one or more PluginStep nodes.
  • The PluginStep node consists of a PluginName, UnsecureConfiguration, SecureConfiguration, Name, Mode, Rank, InvocationSource, PluginMessage, PrimaryEntity, SecondaryEntity, ImpersonatingUserDomainName, Stage, Deployment, Description and Images node.
  • The Images node contains one or more Image nodes.
  • The Image node contains an ImageType, EntityAlias, Attributes, MessageProperty and Merge node.
  • The Attributes node contains an array of strings.

The Console Application accepts the following parameters:
Parameter: Description:
/PATH: The full path to the XML containing the assembly array details.
/UNREGISTER: Only specify this switch to unregister the assembly array.
/Help or /?: Displays the help.


Remember that when you build the Solution in Visual Studio, the Console Application is created as an executable file called PluginRegistrationTool.exe in the the bin\debug or bin\release folder of the Project.

Examples of running the Console Application:
  • PluginRegistrationTool.exe /?
  • PluginRegistrationTool.exe /HELP
  • PluginRegistrationTool.exe
  • PluginRegistrationTool.exe /UNREGISTER
  • PluginRegistrationTool.exe /PATH=C:\AssemblyRegistration.xml
  • PluginRegistrationTool.exe /PATH=C:\AssemblyRegistration.xml /UNREGISTER

Sunday, April 17, 2011

Instantiating a Service Object Within a Plug-in in Microsoft Dynamics CRM 2011

I have seen people asking lately in the forums about how to instantiate a service reference from within a plug-in / plugin.  I whipped up a quick example the other day.  I will show you how to do it and work with an entity without generating early bound types or specific proxies, but I will also provide a link below to a walk-through on how to go that route also.  This example uses the Entity class from the CRM SDK.  It is the equivalent to DynamicEntity in CRM 4.0.  It is nice because you can dynamically work with entities without having generated the specific proxy information for your organization's metadata.

First, here is a simple plugin example that instantiates a service object in the simplest way.  The example then uses the exposed context UserID to perform a retrievemultiple request on a systemuser and adds the user fullname attribute to the contact entity that is the target of the plug-in execution.  Don't ask why I am putting this info into the address1_city as this is just a simple proof of concept. This example is intended to be registered pre-operation on the contact entity.

 public void Execute(IServiceProvider serviceProvider)
        {
            
            // Obtain the organization service reference.

            IPluginExecutionContext context = (IPluginExecutionContext)
               serviceProvider.GetService(typeof(IPluginExecutionContext));

            IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
          

            // The InputParameters collection contains all the data passed in the message request.
            if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
            {
                // Obtain the target entity from the input parmameters.
                Entity entity = (Entity)context.InputParameters["Target"];

                if (entity.LogicalName == "contact")
                {
                    if (entity.Attributes.Contains("address1_city") == false)
                    {
                        

                        RetrieveMultipleRequest rmreq = new RetrieveMultipleRequest();
                        RetrieveMultipleResponse rmresp = new RetrieveMultipleResponse();
                        
                        
                        QueryExpression query = new QueryExpression()
                        {
                            EntityName = "systemuser",
                            ColumnSet = new ColumnSet(true),
                            Criteria = new FilterExpression
                            {
                                FilterOperator = LogicalOperator.And,
                                Conditions = 
                                {
                                    new ConditionExpression
                                    {
                                        AttributeName = "systemuserid",
                                        Operator = ConditionOperator.Equal,
                                        Values = { context.UserId.ToString() }
                                    }
                                }
                            }
                        };

                        rmreq.Query = query;
                        rmresp = (RetrieveMultipleResponse)service.Execute(rmreq);
                        Entity user = (Entity)rmresp.EntityCollection.Entities[0];

                        entity.Attributes.Add("address1_city", context.UserId.ToString() + ": " + user.Attributes["fullname"]);
                    }
                    else
                    {
                        // Throw an error, because account numbers must be system generated.
                        // Throwing an InvalidPluginExecutionException will cause the error message to be displayed in a dialog of the Web application.
                        throw new InvalidPluginExecutionException("Bad, Naughty Plug-in, Don't do that!.");
                    }
                }
            }
        }


Also, here is a walk-through on working with the early-bound entity types in a plug-in:
http://msdn.microsoft.com/en-us/library/gg695782.aspx

 

 

Friday, April 15, 2011

Microsoft Dynamics CRM 2011 – Visual Studio Plugin Templates

Pogo69 was nice enough to create some awesome Visual Studio 2010 templates for Plugin and Workflow activity development for CRM 2011.




Please check these out at his blog:
http://pogo69.wordpress.com/2011/04/15/crm-2011-visual-studio-plugin-templates/

 

 

Wednesday, April 13, 2011

How to: Use Delete Messages in Jscript and .NET With the Microsoft Dynamics CRM 2011 SDK

Here is a quick demo on how to utilize the delete message of the CRM 2011 Organization service in both C# and Jscript.

First in C# (I am using SOAPLogger solution included with the SDK:

SoapLoggerOrganizationService slos = new SoapLoggerOrganizationService(serverConfig.OrganizationUri, service, output);

      //Add the code you want to test here:
      // You must use the SoapLoggerOrganizationService 'slos' proxy rather than the IOrganizationService proxy you would normally use.

      //It is easiest to just first retrieve the entity we want to delete
      RetrieveMultipleRequest rmr = new RetrieveMultipleRequest();
      RetrieveMultipleResponse resp = new RetrieveMultipleResponse();
      Account acct = new Account();

      QueryExpression query = new QueryExpression()
      {
          EntityName = "account",
          ColumnSet = new ColumnSet("name"),
          Criteria = new FilterExpression
          {
              FilterOperator = LogicalOperator.And,
              Conditions = 
                {
                    new ConditionExpression
                    {
                        AttributeName = "name",
                        Operator = ConditionOperator.Equal,
                        Values = { "test account in code" }
                    }
                }
          }
      };

      rmr.Query = query;
      resp = (RetrieveMultipleResponse)slos.Execute(rmr);
      acct = (Account)resp.EntityCollection.Entities[0];

      //Entity reference is required for delete call in .NET
      EntityReference refAcct = new EntityReference("account", acct.AccountId.Value);
         

      //now we will make our delete call
      DeleteRequest dr = new DeleteRequest();
      dr.Target = refAcct;
      slos.Execute(dr);

Now here is the Jscript nicely formatted by the CRM 2011 SOAP formatter. Available at: http://crm2011soap.codeplex.com/



function runme() {
   SDK.SAMPLES.DeleteAccountRequest();
}

if (typeof (SDK) == "undefined")
{ SDK = { __namespace: true }; }
//This will establish a more unique namespace for functions in this library. This will reduce the 
// potential for functions to be overwritten due to a duplicate name when the library is loaded.
SDK.SAMPLES = {
    _getServerUrl: function () {
        ///<summary>
        /// Returns the URL for the SOAP endpoint using the context information available in the form
        /// or HTML Web resource.
        ///</summary>
        var OrgServicePath = "/XRMServices/2011/Organization.svc/web";
        var serverUrl = "";
        if (typeof GetGlobalContext == "function") {
            var context = GetGlobalContext();
            serverUrl = context.getServerUrl();
        }
        else {
            if (typeof Xrm.Page.context == "object") {
                serverUrl = Xrm.Page.context.getServerUrl();
            }
            else
            { throw new Error("Unable to access the server URL"); }
        }
        if (serverUrl.match(/\/$/)) {
            serverUrl = serverUrl.substring(0, serverUrl.length - 1);
        }
        return serverUrl + OrgServicePath;
    },
    DeleteAccountRequest: function () {
        var requestMain = "";
        requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
        requestMain += "  <s:Body>";
        requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
        requestMain += "      <request i:type=\"a:DeleteRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">";
        requestMain += "        <a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
        requestMain += "          <a:KeyValuePairOfstringanyType>";
        requestMain += "            <b:key>Target</b:key>";
        requestMain += "            <b:value i:type=\"a:EntityReference\">";
        requestMain += "              <a:Id>feb0b757-1748-e011-a53f-080027ad5b6e</a:Id>";
        requestMain += "              <a:LogicalName>account</a:LogicalName>";
        requestMain += "              <a:Name i:nil=\"true\" />";
        requestMain += "            </b:value>";
        requestMain += "          </a:KeyValuePairOfstringanyType>";
        requestMain += "        </a:Parameters>";
        requestMain += "        <a:RequestId i:nil=\"true\" />";
        requestMain += "        <a:RequestName>Delete</a:RequestName>";
        requestMain += "      </request>";
        requestMain += "    </Execute>";
        requestMain += "  </s:Body>";
        requestMain += "</s:Envelope>";
        var req = new XMLHttpRequest();
        req.open("POST", SDK.SAMPLES._getServerUrl(), true)
        // Responses will return XML. It isn't possible to return JSON.
        req.setRequestHeader("Accept", "application/xml, text/xml, */*");
        req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
        req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
        var successCallback = null;
        var errorCallback = null;
        req.onreadystatechange = function () { SDK.SAMPLES.DeleteAccountResponse(req, successCallback, errorCallback); };
        req.send(requestMain);
    },
    DeleteAccountResponse: function (req, successCallback, errorCallback) {
        ///<summary>
        /// Recieves the assign response
        ///</summary>
        ///<param name="req" Type="XMLHttpRequest">
        /// The XMLHttpRequest response
        ///</param>
        ///<param name="successCallback" Type="Function">
        /// The function to perform when an successfult response is returned.
        /// For this message no data is returned so a success callback is not really necessary.
        ///</param>
        ///<param name="errorCallback" Type="Function">
        /// The function to perform when an error is returned.
        /// This function accepts a JScript error returned by the _getError function
        ///</param>
        if (req.readyState == 4) {
            if (req.status == 200) {
                if (successCallback != null)
                { successCallback(); }
            }
            else {
                errorCallback(SDK.SAMPLES._getError(req.responseXML));
            }
        }
    },
    _getError: function (faultXml) {
        ///<summary>
        /// Parses the WCF fault returned in the event of an error.
        ///</summary>
        ///<param name="faultXml" Type="XML">
        /// The responseXML property of the XMLHttpRequest response.
        ///</param>
        var errorMessage = "Unknown Error (Unable to parse the fault)";
        if (typeof faultXml == "object") {
            try {
                var bodyNode = faultXml.firstChild.firstChild;
                //Retrieve the fault node
                for (var i = 0; i < bodyNode.childNodes.length; i++) {
                    var node = bodyNode.childNodes[i];
                    //NOTE: This comparison does not handle the case where the XML namespace changes
                    if ("s:Fault" == node.nodeName) {
                        for (var j = 0; j < node.childNodes.length; j++) {
                            var faultStringNode = node.childNodes[j];
                            if ("faultstring" == faultStringNode.nodeName) {
                                errorMessage = faultStringNode.text;
                                break;
                            }
                        }
                        break;
                    }
                }
            }
            catch (e) { };
        }
        return new Error(errorMessage);
    },
    __namespace: true
};

Now you can call the runme() function from your form jscript handler.
Thats all there is to it!

I hope this helps!

Tuesday, April 12, 2011

What to Take Into Consideration When Upgrading to Microsoft Dynamics CRM 2011

I used to work for a guy named Ryan Toenies at a company named Inetium (now Avtex).  Ryan now is the VP of Sales for the Sonoma Partners CRM practice and his company has posted some great information about what to take into account when considering an upgrade from CRM 4.0 to CRM 2011.

Read More here:
http://blog.sonomapartners.com/2011/04/upgrading-to-crm-2011-our-story.html

There is a lot of wisdom presented here and I think it gives a good roadmap for some things that need to be considered when upgrading.  Obviously it is not exhaustive and you need to consider the implentation guide to really get official upgrade information, but I think this if very helpful and has presented a few things to consider that I haven't thought of before.

Thanks,  and I hope this helps!

How To: Use Update Requests in .NET and Jscript in Microsoft Dynamics CRM 2011

Here is a quick demo on how to utilize the update message of the CRM 2011 Organization service in both C# and Jscript.

First in C# (I am using SOAPLogger solution included with the SDK:


 SoapLoggerOrganizationService slos = new SoapLoggerOrganizationService(serverConfig.OrganizationUri, service, output);

      //Add the code you want to test here:
      // You must use the SoapLoggerOrganizationService 'slos' proxy rather than the IOrganizationService proxy you would normally use.

      //It is easiest to just first retrieve the entity we want to update
      RetrieveMultipleRequest rmr = new RetrieveMultipleRequest();
      RetrieveMultipleResponse resp = new RetrieveMultipleResponse();
      Account acct = new Account();

      QueryExpression query = new QueryExpression()
      {
          EntityName = "account",
          ColumnSet = new ColumnSet("name"),
          Criteria = new FilterExpression
          {
              FilterOperator = LogicalOperator.And,
              Conditions = 
                {
                    new ConditionExpression
                    {
                        AttributeName = "name",
                        Operator = ConditionOperator.Equal,
                        Values = { "test account in code" }
                    }
                }
          }
      };

      rmr.Query = query;
      resp = (RetrieveMultipleResponse)slos.Execute(rmr);
      acct = (Account)resp.EntityCollection.Entities[0];

      //Now we will modify our entity's properties
      acct.Address1_City = "Toronto";
      acct.Address1_PostalCode = "55555";

      //now we will make our update call
      UpdateRequest ur = new UpdateRequest();
      ur.Target = acct;
      slos.Execute(ur);

Now here is the Jscript nicely formatted by the CRM 2011 SOAP formatter. Available at: http://crm2011soap.codeplex.com/

This example is asynchronous, if you want to learn how to make JScript SOAP calls synchronously please visit this posthttp://mileyja.blogspot.com/2011/07/using-jscript-to-access-soap-web.html


function runme() {
    
    SDK.SAMPLES.UpdateAccountRequest();
}

if (typeof (SDK) == "undefined")
   { SDK = { __namespace: true }; }
       //This will establish a more unique namespace for functions in this library. This will reduce the 
       // potential for functions to be overwritten due to a duplicate name when the library is loaded.
       SDK.SAMPLES = {
           _getServerUrl: function () {
               ///<summary>
               /// Returns the URL for the SOAP endpoint using the context information available in the form
               /// or HTML Web resource.
               ///</summary>
               var OrgServicePath = "/XRMServices/2011/Organization.svc/web";
               var serverUrl = "";
               if (typeof GetGlobalContext == "function") {
                   var context = GetGlobalContext();
                   serverUrl = context.getServerUrl();
               }
               else {
                   if (typeof Xrm.Page.context == "object") {
                         serverUrl = Xrm.Page.context.getServerUrl();
                   }
                   else
                   { throw new Error("Unable to access the server URL"); }
                   }
                  if (serverUrl.match(/\/$/)) {
                       serverUrl = serverUrl.substring(0, serverUrl.length - 1);
                   } 
                   return serverUrl + OrgServicePath;
               }, 
           UpdateAccountRequest: function () {
               var requestMain = ""
               requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
               requestMain += "  <s:Body>";
               requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
               requestMain += "      <request i:type=\"a:UpdateRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">";
               requestMain += "        <a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>Target</b:key>";
               requestMain += "            <b:value i:type=\"a:Entity\">";
               requestMain += "              <a:Attributes>";
               requestMain += "                <a:KeyValuePairOfstringanyType>";
               requestMain += "                  <b:key>name</b:key>";
               requestMain += "                  <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">test account in code</b:value>";
               requestMain += "                </a:KeyValuePairOfstringanyType>";
               requestMain += "                <a:KeyValuePairOfstringanyType>";
               requestMain += "                  <b:key>accountid</b:key>";
               requestMain += "                  <b:value i:type=\"c:guid\" xmlns:c=\"http://schemas.microsoft.com/2003/10/Serialization/\">f85ec915-ea61-e011-9eec-080027ad5b6e</b:value>";
               requestMain += "                </a:KeyValuePairOfstringanyType>";
               requestMain += "                <a:KeyValuePairOfstringanyType>";
               requestMain += "                  <b:key>address1_city</b:key>";
               requestMain += "                  <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">Toronto</b:value>";
               requestMain += "                </a:KeyValuePairOfstringanyType>";
               requestMain += "                <a:KeyValuePairOfstringanyType>";
               requestMain += "                  <b:key>address1_postalcode</b:key>";
               requestMain += "                  <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">55555</b:value>";
               requestMain += "                </a:KeyValuePairOfstringanyType>";
               requestMain += "              </a:Attributes>";
               requestMain += "              <a:EntityState i:nil=\"true\" />";
               requestMain += "              <a:FormattedValues />";
               requestMain += "              <a:Id>f85ec915-ea61-e011-9eec-080027ad5b6e</a:Id>";
               requestMain += "              <a:LogicalName>account</a:LogicalName>";
               requestMain += "              <a:RelatedEntities />";
               requestMain += "            </b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "        </a:Parameters>";
               requestMain += "        <a:RequestId i:nil=\"true\" />";
               requestMain += "        <a:RequestName>Update</a:RequestName>";
               requestMain += "      </request>";
               requestMain += "    </Execute>";
               requestMain += "  </s:Body>";
               requestMain += "</s:Envelope>";
               var req = new XMLHttpRequest();
               req.open("POST", SDK.SAMPLES._getServerUrl(), true)
               // Responses will return XML. It isn't possible to return JSON.
               req.setRequestHeader("Accept", "application/xml, text/xml, */*");
               req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
               req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
               var successCallback = null;
               var errorCallback = null;
               req.onreadystatechange = function () { SDK.SAMPLES.UpdateAccountResponse(req, successCallback, errorCallback); };
               req.send(requestMain);
           },
       UpdateAccountResponse: function (req, successCallback, errorCallback) {
               ///<summary>
               /// Recieves the assign response
               ///</summary>
               ///<param name="req" Type="XMLHttpRequest">
               /// The XMLHttpRequest response
               ///</param>
               ///<param name="successCallback" Type="Function">
               /// The function to perform when an successfult response is returned.
               /// For this message no data is returned so a success callback is not really necessary.
               ///</param>
               ///<param name="errorCallback" Type="Function">
               /// The function to perform when an error is returned.
               /// This function accepts a JScript error returned by the _getError function
               ///</param>
               if (req.readyState == 4) {
               if (req.status == 200) {
               if (successCallback != null)
               { successCallback(); }
               }
               else {
                   errorCallback(SDK.SAMPLES._getError(req.responseXML));
               }
           }
       },
       _getError: function (faultXml) {
           ///<summary>
           /// Parses the WCF fault returned in the event of an error.
           ///</summary>
           ///<param name="faultXml" Type="XML">
           /// The responseXML property of the XMLHttpRequest response.
           ///</param>
           var errorMessage = "Unknown Error (Unable to parse the fault)";
           if (typeof faultXml == "object") {
               try {
                   var bodyNode = faultXml.firstChild.firstChild;
                   //Retrieve the fault node
                   for (var i = 0; i < bodyNode.childNodes.length; i++) {
                       var node = bodyNode.childNodes[i];
                       //NOTE: This comparison does not handle the case where the XML namespace changes
                       if ("s:Fault" == node.nodeName) {
                       for (var j = 0; j < node.childNodes.length; j++) {
                           var faultStringNode = node.childNodes[j];
                           if ("faultstring" == faultStringNode.nodeName) {
                               errorMessage = faultStringNode.text;
                               break;
                           }
                       }
                       break;
                   }
               }
           }
           catch (e) { };
        }
        return new Error(errorMessage);
     },
 __namespace: true
};


Now you can call the runme() function from your form jscript handler.
Thats all there is to it!

I hope this helps!

Monday, April 11, 2011

Available Microsoft Dynamics CRM 2011 Plugin Messages - Part 2

Here is the second and final installment of available plugin messages for CRM 2011. The list was so big it blew up my blogger when I tried to put it all in one post.

Part 1 with the first half of the messages can be found here:
http://mileyja.blogspot.com/2011/04/available-microsoft-dynamics-crm-2011.html


Message Name
Primary Entity
Secondary Entity
Message Availability
Entity Supported Deployment
RetrieveMultiple
BusinessUnitNewsArticle
NULL
Both
Both
RetrieveMultiple
Calendar
NULL
Both
Both
RetrieveMultiple
Campaign
NULL
Both
Both
RetrieveMultiple
CampaignActivity
NULL
Both
Both
RetrieveMultiple
CampaignActivityItem
NULL
Both
Both
RetrieveMultiple
CampaignItem
NULL
Both
Both
RetrieveMultiple
CampaignResponse
NULL
Both
Both
RetrieveMultiple
ClientUpdate
NULL
Both
Both
RetrieveMultiple
Commitment
NULL
Both
Both
RetrieveMultiple
Competitor
NULL
Both
Both
RetrieveMultiple
CompetitorAddress
NULL
Both
Both
RetrieveMultiple
CompetitorProduct
NULL
Both
Both
RetrieveMultiple
CompetitorSalesLiterature
NULL
Both
Both
RetrieveMultiple
Connection
NULL
Both
Both
RetrieveMultiple
ConnectionRole
NULL
Both
Both
RetrieveMultiple
ConnectionRoleAssociation
NULL
Both
Both
RetrieveMultiple
ConnectionRoleObjectTypeCode
NULL
Both
Both
RetrieveMultiple
Contact
NULL
Both
Both
RetrieveMultiple
ContactInvoices
NULL
Both
Both
RetrieveMultiple
ContactLeads
NULL
Both
Both
RetrieveMultiple
ContactOrders
NULL
Both
Both
RetrieveMultiple
ContactQuotes
NULL
Both
Both
RetrieveMultiple
Contract
NULL
Both
Both
RetrieveMultiple
ContractDetail
NULL
Both
Both
RetrieveMultiple
ContractTemplate
NULL
Both
Both
RetrieveMultiple
CustomerAddress
NULL
Both
Both
RetrieveMultiple
CustomerOpportunityRole
NULL
Both
Both
RetrieveMultiple
CustomerRelationship
NULL
Both
Both
RetrieveMultiple
Dependency
NULL
Both
Server
RetrieveMultiple
DependencyNode
NULL
Both
Both
RetrieveMultiple
Discount
NULL
Both
Both
RetrieveMultiple
DiscountType
NULL
Both
Both
RetrieveMultiple
DisplayStringMap
NULL
Both
Both
RetrieveMultiple
DocumentIndex
NULL
Both
Both
RetrieveMultiple
Email
NULL
Both
Both
RetrieveMultiple
EmailHash
NULL
Both
Both
RetrieveMultiple
EmailSearch
NULL
Both
Both
RetrieveMultiple
Equipment
NULL
Both
Both
RetrieveMultiple
Fax
NULL
Both
Both
RetrieveMultiple
FilterTemplate
NULL
Both
Both
RetrieveMultiple
Goal
NULL
Both
Both
RetrieveMultiple
GoalRollupQuery
NULL
Both
Both
RetrieveMultiple
Incident
NULL
Both
Both
RetrieveMultiple
IncidentResolution
NULL
Both
Both
RetrieveMultiple
InternalAddress
NULL
Both
Both
RetrieveMultiple
InterProcessLock
NULL
Both
Both
RetrieveMultiple
InvalidDependency
NULL
Both
Server
RetrieveMultiple
Invoice
NULL
Both
Both
RetrieveMultiple
InvoiceDetail
NULL
Both
Both
RetrieveMultiple
KbArticle
NULL
Both
Both
RetrieveMultiple
KbArticleComment
NULL
Both
Both
RetrieveMultiple
KbArticleTemplate
NULL
Both
Both
RetrieveMultiple
Lead
NULL
Both
Both
RetrieveMultiple
LeadAddress
NULL
Both
Both
RetrieveMultiple
LeadCompetitors
NULL
Both
Both
RetrieveMultiple
LeadProduct
NULL
Both
Both
RetrieveMultiple
Letter
NULL
Both
Both
RetrieveMultiple
License
NULL
Both
Both
RetrieveMultiple
List
NULL
Both
Both
RetrieveMultiple
ListMember
NULL
Both
Both
RetrieveMultiple
Metric
NULL
Both
Both
RetrieveMultiple
new_customentity
NULL
Both
Server
RetrieveMultiple
Notification
NULL
Both
Both
RetrieveMultiple
Opportunity
NULL
Both
Both
RetrieveMultiple
OpportunityClose
NULL
Both
Both
RetrieveMultiple
OpportunityCompetitors
NULL
Both
Both
RetrieveMultiple
OpportunityProduct
NULL
Both
Both
RetrieveMultiple
OrderClose
NULL
Both
Both
RetrieveMultiple
OrganizationStatistic
NULL
Both
Both
RetrieveMultiple
Owner
NULL
Both
Both
RetrieveMultiple
PhoneCall
NULL
Both
Both
RetrieveMultiple
PriceLevel
NULL
Both
Both
RetrieveMultiple
PrincipalObjectAccess
NULL
Both
Both
RetrieveMultiple
PrivilegeObjectTypeCodes
NULL
Both
Both
RetrieveMultiple
ProcessSession
NULL
Both
Both
RetrieveMultiple
Product
NULL
Both
Both
RetrieveMultiple
ProductAssociation
NULL
Both
Both
RetrieveMultiple
ProductPriceLevel
NULL
Both
Both
RetrieveMultiple
ProductSalesLiterature
NULL
Both
Both
RetrieveMultiple
ProductSubstitute
NULL
Both
Both
RetrieveMultiple
Publisher
NULL
Both
Both
RetrieveMultiple
PublisherAddress
NULL
Both
Server
RetrieveMultiple
Queue
NULL
Both
Both
RetrieveMultiple
Quote
NULL
Both
Both
RetrieveMultiple
QuoteClose
NULL
Both
Both
RetrieveMultiple
QuoteDetail
NULL
Both
Both
RetrieveMultiple
RecurrenceRule
NULL
Both
Both
RetrieveMultiple
RecurringAppointmentMaster
NULL
Both
Both
RetrieveMultiple
ResourceGroupExpansion
NULL
Both
Both
RetrieveMultiple
RolePrivileges
NULL
Both
Both
RetrieveMultiple
RoleTemplate
NULL
Both
Both
RetrieveMultiple
RoleTemplatePrivileges
NULL
Both
Both
RetrieveMultiple
RollupField
NULL
Both
Both
RetrieveMultiple
SalesLiterature
NULL
Both
Both
RetrieveMultiple
SalesLiteratureItem
NULL
Both
Both
RetrieveMultiple
SalesOrder
NULL
Both
Both
RetrieveMultiple
SalesOrderDetail
NULL
Both
Both
RetrieveMultiple
SalesProcessInstance
NULL
Both
Both
RetrieveMultiple
SavedQuery
NULL
Both
Both
RetrieveMultiple
SavedQueryVisualization
NULL
Both
Both
RetrieveMultiple
Service
NULL
Both
Both
RetrieveMultiple
ServiceAppointment
NULL
Both
Both
RetrieveMultiple
ServiceContractContacts
NULL
Both
Both
RetrieveMultiple
SharePointDocumentLocation
NULL
Both
Server
RetrieveMultiple
SharePointSite
NULL
Both
Server
RetrieveMultiple
Site
NULL
Both
Both
RetrieveMultiple
Solution
NULL
Both
Both
RetrieveMultiple
SolutionComponent
NULL
Both
Both
RetrieveMultiple
StatusMap
NULL
Both
Both
RetrieveMultiple
StringMap
NULL
Both
Both
RetrieveMultiple
Subject
NULL
Both
Both
RetrieveMultiple
SystemUserBusinessUnitEntityMap
NULL
Both
Both
RetrieveMultiple
SystemUserLicenses
NULL
Both
Both
RetrieveMultiple
SystemUserPrincipals
NULL
Both
Both
RetrieveMultiple
SystemUserProfiles
NULL
Both
Server
RetrieveMultiple
SystemUserRoles
NULL
Both
Both
RetrieveMultiple
Task
NULL
Both
Both
RetrieveMultiple
Team
NULL
Both
Both
RetrieveMultiple
TeamMembership
NULL
Both
Both
RetrieveMultiple
TeamProfiles
NULL
Both
Server
RetrieveMultiple
TeamRoles
NULL
Both
Both
RetrieveMultiple
Template
NULL
Both
Both
RetrieveMultiple
Territory
NULL
Both
Both
RetrieveMultiple
UnresolvedAddress
NULL
Both
Both
RetrieveMultiple
UoM
NULL
Both
Both
RetrieveMultiple
UoMSchedule
NULL
Both
Both
RetrieveMultiple
UserEntityInstanceData
NULL
Both
Both
RetrieveMultiple
UserFiscalCalendar
NULL
Both
Both
RetrieveMultiple
UserForm
NULL
Both
Both
RetrieveMultiple
UserQuery
NULL
Both
Both
RetrieveMultiple
UserQueryVisualization
NULL
Both
Both
RetrieveMultiple
UserSettings
NULL
Both
Both
RetrieveMultiple
WebResource
NULL
Both
Both
RetrievePrincipalAccess
Account
NULL
Both
Both
RetrievePrincipalAccess
Annotation
NULL
Both
Both
RetrievePrincipalAccess
Appointment
NULL
Both
Both
RetrievePrincipalAccess
Campaign
NULL
Both
Both
RetrievePrincipalAccess
CampaignActivity
NULL
Both
Both
RetrievePrincipalAccess
CampaignResponse
NULL
Both
Both
RetrievePrincipalAccess
Connection
NULL
Both
Both
RetrievePrincipalAccess
Contact
NULL
Both
Both
RetrievePrincipalAccess
Contract
NULL
Both
Both
RetrievePrincipalAccess
CustomerOpportunityRole
NULL
Both
Both
RetrievePrincipalAccess
CustomerRelationship
NULL
Both
Both
RetrievePrincipalAccess
Email
NULL
Both
Both
RetrievePrincipalAccess
Fax
NULL
Both
Both
RetrievePrincipalAccess
Goal
NULL
Both
Both
RetrievePrincipalAccess
GoalRollupQuery
NULL
Both
Both
RetrievePrincipalAccess
Incident
NULL
Both
Both
RetrievePrincipalAccess
IncidentResolution
NULL
Both
Both
RetrievePrincipalAccess
Invoice
NULL
Both
Both
RetrievePrincipalAccess
Lead
NULL
Both
Both
RetrievePrincipalAccess
Letter
NULL
Both
Both
RetrievePrincipalAccess
List
NULL
Both
Both
RetrievePrincipalAccess
new_customentity
NULL
Both
Server
RetrievePrincipalAccess
Opportunity
NULL
Both
Both
RetrievePrincipalAccess
OpportunityClose
NULL
Both
Both
RetrievePrincipalAccess
OrderClose
NULL
Both
Both
RetrievePrincipalAccess
PhoneCall
NULL
Both
Both
RetrievePrincipalAccess
ProcessSession
NULL
Both
Both
RetrievePrincipalAccess
Queue
NULL
Both
Both
RetrievePrincipalAccess
Quote
NULL
Both
Both
RetrievePrincipalAccess
QuoteClose
NULL
Both
Both
RetrievePrincipalAccess
RecurringAppointmentMaster
NULL
Both
Both
RetrievePrincipalAccess
SalesOrder
NULL
Both
Both
RetrievePrincipalAccess
ServiceAppointment
NULL
Both
Both
RetrievePrincipalAccess
SharePointDocumentLocation
NULL
Both
Both
RetrievePrincipalAccess
SharePointSite
NULL
Both
Both
RetrievePrincipalAccess
Task
NULL
Both
Both
RetrievePrincipalAccess
Template
NULL
Both
Both
RetrievePrincipalAccess
UserForm
NULL
Both
Both
RetrievePrincipalAccess
UserQuery
NULL
Both
Both
RetrievePrincipalAccess
UserQueryVisualization
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
Account
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
Annotation
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
Appointment
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
Campaign
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
CampaignActivity
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
CampaignResponse
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
Connection
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
Contact
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
Contract
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
CustomerOpportunityRole
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
CustomerRelationship
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
Email
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
Fax
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
Goal
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
GoalRollupQuery
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
Incident
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
IncidentResolution
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
Invoice
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
Lead
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
Letter
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
List
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
new_customentity
NULL
Both
Server
RetrieveSharedPrincipalsAndAccess
Opportunity
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
OpportunityClose
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
OrderClose
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
PhoneCall
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
ProcessSession
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
Queue
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
Quote
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
QuoteClose
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
RecurringAppointmentMaster
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
SalesOrder
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
ServiceAppointment
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
SharePointDocumentLocation
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
SharePointSite
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
Task
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
Template
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
UserForm
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
UserQuery
NULL
Both
Both
RetrieveSharedPrincipalsAndAccess
UserQueryVisualization
NULL
Both
Both
RetrieveUnpublished
WebResource
NULL
Server
Server
RetrieveUnpublishedMultiple
WebResource
NULL
Server
Server
RevokeAccess
Account
NULL
Server
Server
RevokeAccess
Annotation
NULL
Server
Server
RevokeAccess
Appointment
NULL
Server
Server
RevokeAccess
Campaign
NULL
Server
Server
RevokeAccess
CampaignActivity
NULL
Server
Server
RevokeAccess
CampaignResponse
NULL
Server
Server
RevokeAccess
Connection
NULL
Server
Server
RevokeAccess
Contact
NULL
Server
Server
RevokeAccess
Contract
NULL
Server
Server
RevokeAccess
CustomerOpportunityRole
NULL
Server
Server
RevokeAccess
CustomerRelationship
NULL
Server
Server
RevokeAccess
Email
NULL
Server
Server
RevokeAccess
Fax
NULL
Server
Server
RevokeAccess
Goal
NULL
Server
Server
RevokeAccess
GoalRollupQuery
NULL
Server
Server
RevokeAccess
Incident
NULL
Server
Server
RevokeAccess
IncidentResolution
NULL
Server
Server
RevokeAccess
Invoice
NULL
Server
Server
RevokeAccess
Lead
NULL
Server
Server
RevokeAccess
Letter
NULL
Server
Server
RevokeAccess
List
NULL
Server
Server
RevokeAccess
new_customentity
NULL
Server
Server
RevokeAccess
Opportunity
NULL
Server
Server
RevokeAccess
OpportunityClose
NULL
Server
Server
RevokeAccess
OrderClose
NULL
Server
Server
RevokeAccess
PhoneCall
NULL
Server
Server
RevokeAccess
ProcessSession
NULL
Server
Server
RevokeAccess
Queue
NULL
Server
Server
RevokeAccess
Quote
NULL
Server
Server
RevokeAccess
QuoteClose
NULL
Server
Server
RevokeAccess
RecurringAppointmentMaster
NULL
Server
Server
RevokeAccess
SalesOrder
NULL
Server
Server
RevokeAccess
ServiceAppointment
NULL
Server
Server
RevokeAccess
SharePointDocumentLocation
NULL
Server
Server
RevokeAccess
SharePointSite
NULL
Server
Server
RevokeAccess
Task
NULL
Server
Server
RevokeAccess
Template
NULL
Server
Server
RevokeAccess
UserForm
NULL
Server
Server
RevokeAccess
UserQuery
NULL
Server
Server
RevokeAccess
UserQueryVisualization
NULL
Server
Server
Route
Appointment
NULL
Both
Both
Route
CampaignActivity
NULL
Both
Both
Route
CampaignResponse
NULL
Both
Both
Route
Email
NULL
Both
Both
Route
Fax
NULL
Both
Both
Route
Incident
NULL
Both
Both
Route
Letter
NULL
Both
Both
Route
PhoneCall
NULL
Both
Both
Route
RecurringAppointmentMaster
NULL
Both
Both
Route
ServiceAppointment
NULL
Both
Both
Route
Task
NULL
Both
Both
Send
Email
NULL
Both
Both
Send
Fax
NULL
Both
Both
Send
Template
NULL
Both
Both
SendFromTemplate
Email
NULL
Server
Server
SetRelated
Invoice
Contact
Both
Both
SetRelated
Lead
Account
Both
Both
SetRelated
Lead
Contact
Both
Both
SetRelated
Opportunity
Account
Both
Both
SetRelated
Opportunity
Contact
Both
Both
SetRelated
Opportunity
Competitor
Both
Both
SetRelated
Product
Lead
Both
Both
SetRelated
Product
Competitor
Both
Both
SetRelated
Quote
Contact
Both
Both
SetRelated
SalesLiterature
Competitor
Both
Both
SetRelated
SalesLiterature
Product
Both
Both
SetRelated
SalesOrder
Contact
Both
Both
SetState
Account
NULL
Both
Both
SetState
Appointment
NULL
Both
Both
SetState
BusinessUnit
NULL
Both
Server
SetState
Campaign
NULL
Both
Both
SetState
CampaignActivity
NULL
Both
Both
SetState
CampaignResponse
NULL
Both
Both
SetState
Connection
NULL
Both
Both
SetState
ConnectionRole
NULL
Both
Both
SetState
Contact
NULL
Both
Both
SetState
Contract
NULL
Both
Both
SetState
ContractDetail
NULL
Both
Both
SetState
DiscountType
NULL
Both
Both
SetState
Email
NULL
Both
Both
SetState
Fax
NULL
Both
Both
SetState
Incident
NULL
Both
Both
SetState
IncidentResolution
NULL
Both
Both
SetState
Invoice
NULL
Both
Both
SetState
KbArticle
NULL
Both
Both
SetState
Lead
NULL
Both
Both
SetState
Letter
NULL
Both
Both
SetState
List
NULL
Both
Both
SetState
new_customentity
NULL
Both
Server
SetState
Opportunity
NULL
Both
Both
SetState
OpportunityClose
NULL
Both
Both
SetState
OrderClose
NULL
Both
Both
SetState
PhoneCall
NULL
Both
Both
SetState
PriceLevel
NULL
Both
Both
SetState
Product
NULL
Both
Both
SetState
Queue
NULL
Both
Both
SetState
QueueItem
NULL
Both
Both
SetState
Quote
NULL
Both
Both
SetState
QuoteClose
NULL
Both
Both
SetState
RecurringAppointmentMaster
NULL
Both
Both
SetState
SalesOrder
NULL
Both
Both
SetState
ServiceAppointment
NULL
Both
Both
SetState
SharePointDocumentLocation
NULL
Both
Both
SetState
SharePointSite
NULL
Both
Both
SetState
SystemUser
NULL
Both
Server
SetState
Task
NULL
Both
Both
SetState
TransactionCurrency
NULL
Both
Server
SetState
UserQuery
NULL
Both
Both
SetStateDynamicEntity
Account
NULL
Both
Both
SetStateDynamicEntity
Appointment
NULL
Both
Both
SetStateDynamicEntity
BusinessUnit
NULL
Both
Server
SetStateDynamicEntity
Campaign
NULL
Both
Both
SetStateDynamicEntity
CampaignActivity
NULL
Both
Both
SetStateDynamicEntity
CampaignResponse
NULL
Both
Both
SetStateDynamicEntity
Connection
NULL
Both
Both
SetStateDynamicEntity
ConnectionRole
NULL
Both
Both
SetStateDynamicEntity
Contact
NULL
Both
Both
SetStateDynamicEntity
Contract
NULL
Both
Both
SetStateDynamicEntity
ContractDetail
NULL
Both
Both
SetStateDynamicEntity
DiscountType
NULL
Both
Both
SetStateDynamicEntity
Email
NULL
Both
Both
SetStateDynamicEntity
Fax
NULL
Both
Both
SetStateDynamicEntity
Goal
NULL
Both
Server
SetStateDynamicEntity
GoalRollupQuery
NULL
Both
Server
SetStateDynamicEntity
Incident
NULL
Both
Both
SetStateDynamicEntity
IncidentResolution
NULL
Both
Both
SetStateDynamicEntity
Invoice
NULL
Both
Both
SetStateDynamicEntity
KbArticle
NULL
Both
Both
SetStateDynamicEntity
Lead
NULL
Both
Both
SetStateDynamicEntity
Letter
NULL
Both
Both
SetStateDynamicEntity
List
NULL
Both
Both
SetStateDynamicEntity
Metric
NULL
Both
Server
SetStateDynamicEntity
new_customentity
NULL
Both
Server
SetStateDynamicEntity
Opportunity
NULL
Both
Both
SetStateDynamicEntity
OpportunityClose
NULL
Both
Both
SetStateDynamicEntity
OrderClose
NULL
Both
Both
SetStateDynamicEntity
PhoneCall
NULL
Both
Both
SetStateDynamicEntity
PriceLevel
NULL
Both
Both
SetStateDynamicEntity
ProcessSession
NULL
Both
Both
SetStateDynamicEntity
Product
NULL
Both
Both
SetStateDynamicEntity
Queue
NULL
Both
Both
SetStateDynamicEntity
QueueItem
NULL
Both
Both
SetStateDynamicEntity
Quote
NULL
Both
Both
SetStateDynamicEntity
QuoteClose
NULL
Both
Both
SetStateDynamicEntity
RecurringAppointmentMaster
NULL
Both
Both
SetStateDynamicEntity
SalesOrder
NULL
Both
Both
SetStateDynamicEntity
SavedQuery
NULL
Both
Server
SetStateDynamicEntity
ServiceAppointment
NULL
Both
Both
SetStateDynamicEntity
SharePointDocumentLocation
NULL
Both
Both
SetStateDynamicEntity
SharePointSite
NULL
Both
Both
SetStateDynamicEntity
SystemUser
NULL
Both
Server
SetStateDynamicEntity
Task
NULL
Both
Both
SetStateDynamicEntity
TransactionCurrency
NULL
Both
Server
SetStateDynamicEntity
UoMSchedule
NULL
Both
Both
SetStateDynamicEntity
UserQuery
NULL
Both
Both
TriggerServiceEndpointCheck
ServiceEndpoint
NULL
Server
Server
UnlockInvoicePricing
NULL
NULL
Server
Server
UnlockSalesOrderPricing
NULL
NULL
Server
Server
Update
Account
NULL
Both
Both
Update
ActivityMimeAttachment
NULL
Both
Both
Update
Annotation
NULL
Both
Both
Update
Appointment
NULL
Both
Both
Update
BusinessUnit
NULL
Both
Server
Update
BusinessUnitNewsArticle
NULL
Both
Both
Update
Calendar
NULL
Both
Both
Update
Campaign
NULL
Both
Both
Update
CampaignActivity
NULL
Both
Both
Update
CampaignResponse
NULL
Both
Both
Update
Competitor
NULL
Both
Both
Update
Connection
NULL
Both
Both
Update
ConnectionRole
NULL
Both
Both
Update
Contact
NULL
Both
Both
Update
Contract
NULL
Both
Both
Update
ContractDetail
NULL
Both
Both
Update
ContractTemplate
NULL
Both
Server
Update
CustomerAddress
NULL
Both
Both
Update
CustomerOpportunityRole
NULL
Both
Both
Update
CustomerRelationship
NULL
Both
Both
Update
Discount
NULL
Both
Both
Update
DiscountType
NULL
Both
Both
Update
Email
NULL
Both
Both
Update
Equipment
NULL
Both
Server
Update
Fax
NULL
Both
Both
Update
FieldPermission
NULL
Both
Server
Update
FieldSecurityProfile
NULL
Both
Server
Update
Goal
NULL
Both
Server
Update
GoalRollupQuery
NULL
Both
Server
Update
Incident
NULL
Both
Both
Update
IncidentResolution
NULL
Both
Both
Update
Invoice
NULL
Both
Both
Update
InvoiceDetail
NULL
Both
Both
Update
KbArticle
NULL
Both
Both
Update
KbArticleComment
NULL
Both
Both
Update
KbArticleTemplate
NULL
Both
Both
Update
Lead
NULL
Both
Both
Update
Letter
NULL
Both
Both
Update
List
NULL
Both
Both
Update
Metric
NULL
Both
Server
Update
new_customentity
NULL
Both
Server
Update
Opportunity
NULL
Both
Both
Update
OpportunityClose
NULL
Both
Both
Update
OpportunityProduct
NULL
Both
Both
Update
OrderClose
NULL
Both
Both
Update
Organization
NULL
Both
Server
Update
PhoneCall
NULL
Both
Both
Update
PriceLevel
NULL
Both
Both
Update
PrincipalObjectAttributeAccess
NULL
Both
Server
Update
ProcessSession
NULL
Both
Both
Update
Product
NULL
Both
Both
Update
ProductPriceLevel
NULL
Both
Both
Update
Queue
NULL
Both
Server
Update
QueueItem
NULL
Both
Both
Update
Quote
NULL
Both
Both
Update
QuoteClose
NULL
Both
Both
Update
QuoteDetail
NULL
Both
Both
Update
RecurrenceRule
NULL
Both
Server
Update
RecurringAppointmentMaster
NULL
Both
Both
Update
Role
NULL
Both
Server
Update
RollupField
NULL
Both
Server
Update
SalesLiterature
NULL
Both
Both
Update
SalesLiteratureItem
NULL
Both
Both
Update
SalesOrder
NULL
Both
Both
Update
SalesOrderDetail
NULL
Both
Both
Update
Service
NULL
Both
Server
Update
ServiceAppointment
NULL
Both
Both
Update
SharePointDocumentLocation
NULL
Both
Server
Update
SharePointSite
NULL
Both
Server
Update
Site
NULL
Both
Server
Update
Subject
NULL
Both
Both
Update
SystemUser
NULL
Both
Server
Update
Task
NULL
Both
Both
Update
Team
NULL
Both
Server
Update
Template
NULL
Both
Both
Update
Territory
NULL
Both
Server
Update
TransactionCurrency
NULL
Both
Server
Update
UoM
NULL
Both
Both
Update
UoMSchedule
NULL
Both
Both
Update
UserForm
NULL
Both
Server
Update
UserQuery
NULL
Both
Both
Update
UserQueryVisualization
NULL
Both
Both
Update
WebResource
NULL
Both
Server
ValidateRecurrenceRule
RecurrenceRule
NULL
Both
Both
Win
Opportunity
NULL
Both
Both
Win
Quote
NULL
Both
Both





The Message Availability and Entity Supported Deployment columns indicate if the message or entity are supported on just the Microsoft Dynamics CRM server, or on both the server and Outlook client.