Tuesday, April 8, 2014

SSIS Script Task using KingswaySoft for CRM 2011

Hi Guys,
kingswaysoft components allow simple operations like Retrieve, Update or Create, but when you need to do something more complex, there is no kingswaysoft components. But kingswaysoft provides two useful assemblies that you can uses them in a Script Task:
  • KingswaySoft.DynamicsCrmServices
  • KingswaySoft.IntegrationToolkit.DynamicsCrm
To do it follow this short toturial:
You need to create a Script Task in your Data Flow Process.
And to add your kingswaysoft crm connection manager to Connection Managers List:

After that you should to add kingswaysoft assemblies in reference like this :
Then, You should add kingswaysoft namespaces like this:

  1. #region Namespaces
  2. using System;
  3. using System.Data;
  4. using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
  5. using Microsoft.SqlServer.Dts.Runtime.Wrapper;
  6. using System.ServiceModel.Description;
  7. using KingswaySoft.IntegrationToolkit.DynamicsCrm;
  8. using KingswaySoft.DynamicsCrmServices.Soap2011;
  9. using KingswaySoft.DynamicsCrmServices.Soap2011.OrganizationService.Query;
  10. using KingswaySoft.DynamicsCrmServices.Soap2011.OrganizationService;
  11. #endregion
So, Now you need to create a IOrganizationService Object
  1. [Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
  2. public class ScriptMain : UserComponent
  3. {
  4.  
  5.     KingswaySoft.DynamicsCrmServices.Soap2011.OrganizationService.IOrganizationService orgService;
  6.     ...

In PreExecute Methode, intialize your IOrganizationService Object using the AcquireConnection methode:

  1. public override void PreExecute()
  2. {
  3.     base.PreExecute();
  4.     var conn = (CrmConnection)Connections.CrmConnection.AcquireConnection(null);
  5.  
  6.     orgService = (KingswaySoft.DynamicsCrmServices.Soap2011.OrganizationService.IOrganizationService)conn.GetCrmService();
  7.     
  8. }
After that you can use all needed methods like RetrieveMultiple, Execute, Update etc...
Good Luck

N.JL

Thursday, April 3, 2014

How to Close Incident using SOAP on CRM 2011

Hi Guys,

The IncidentResolution entity is a particular entity that we can not modify or form neither fields.

So when you need to put an automatic value in Resolution field (subject) you cannot customize form by adding jscript code.

The only way to do it, is by hiding the Resolve Case button:on Incident form/home page Ribbon, and to create your own custom resolution window or dialog and should send a SOAP request to the CRM Server to close the incident.

There is the most complete source code that you allow to close your incident by sending : Subject, TimeSpent and Description data. This code is synchronous.

Source Code
  1. if (typeof (Sdk) == "undefined")
  2. { Sdk = { __namespace: true }; }
  3. //This will establish a more unique namespace for functions in this library. This will reduce the
  4. // potential for functions to be overwritten due to a duplicate name when the library is loaded.
  5. Sdk.Tools = {
  6.     _getServerUrl: function () {
  7.         ///<summary>
  8.         /// Returns the URL for the SOAP endpoint using the context information available in the form
  9.         /// or HTML Web resource.
  10.         ///</summary>
  11.         var OrgServicePath = "/XRMServices/2011/Organization.svc/web";
  12.         var serverUrl = "";
  13.         if (typeof GetGlobalContext == "function") {
  14.             var context = GetGlobalContext();
  15.             serverUrl = context.getServerUrl();
  16.         }
  17.         else {
  18.             if (typeof Xrm.Page.context == "object") {
  19.                 serverUrl = Xrm.Page.context.getServerUrl();
  20.             }
  21.             else { throw new Error("Unable to access the server URL"); }
  22.         }
  23.         if (serverUrl.match(/\/$/)) {
  24.             serverUrl = serverUrl.substring(0, serverUrl.length - 1);
  25.         }
  26.         return serverUrl + OrgServicePath;
  27.     },
  28.     CloseIncidentRequest: function (incidentId, subject, resolutionTypeValue, durationValue, description) {
  29.  
  30.         var requestMain = ""
  31.         requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
  32.         requestMain += "  <s:Body>";
  33.         requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
  34.         requestMain += "      <request i:type=\"b:CloseIncidentRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\" xmlns:b=\"http://schemas.microsoft.com/crm/2011/Contracts\">";
  35.         requestMain += "        <a:Parameters xmlns:c=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
  36.         requestMain += "          <a:KeyValuePairOfstringanyType>";
  37.         requestMain += "            <c:key>IncidentResolution</c:key>";
  38.         requestMain += "            <c:value i:type=\"a:Entity\">";
  39.         requestMain += "              <a:Attributes>";
  40.         requestMain += "                <a:KeyValuePairOfstringanyType>";
  41.         requestMain += "                  <c:key>incidentid</c:key>";
  42.         requestMain += "                  <c:value i:type=\"a:EntityReference\">";
  43.         requestMain += "                    <a:Id>" + incidentId + "</a:Id>";
  44.         requestMain += "                    <a:LogicalName>incident</a:LogicalName>";
  45.         requestMain += "                    <a:Name i:nil=\"true\" />";
  46.         requestMain += "                  </c:value>";
  47.         requestMain += "                </a:KeyValuePairOfstringanyType>";
  48.         requestMain += "                <a:KeyValuePairOfstringanyType>";
  49.         requestMain += "                  <c:key>subject</c:key>";
  50.         requestMain += "                  <c:value i:type=\"d:string\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">" + subject + "</c:value>";
  51.         requestMain += "                </a:KeyValuePairOfstringanyType>";
  52.         requestMain += "                <a:KeyValuePairOfstringanyType>";
  53.         requestMain += "                  <c:key>description</c:key>";
  54.         requestMain += "                  <c:value i:type=\"d:string\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">" + description + "</c:value>";
  55.         requestMain += "                </a:KeyValuePairOfstringanyType>";
  56.         requestMain += "                <a:KeyValuePairOfstringanyType>";
  57.         requestMain += "                  <c:key>timespent</c:key>";
  58.         requestMain += "                  <c:value i:type=\"d:int\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">" + durationValue + "</c:value>";
  59.         requestMain += "                </a:KeyValuePairOfstringanyType>";
  60.         requestMain += "              </a:Attributes>";
  61.         requestMain += "              <a:EntityState i:nil=\"true\" />";
  62.         requestMain += "              <a:FormattedValues />";
  63.         requestMain += "              <a:Id>00000000-0000-0000-0000-000000000000</a:Id>";
  64.         requestMain += "              <a:LogicalName>incidentresolution</a:LogicalName>";
  65.         requestMain += "              <a:RelatedEntities />";
  66.         requestMain += "            </c:value>";
  67.         requestMain += "          </a:KeyValuePairOfstringanyType>";
  68.         requestMain += "          <a:KeyValuePairOfstringanyType>";
  69.         requestMain += "            <c:key>Status</c:key>";
  70.         requestMain += "            <c:value i:type=\"a:OptionSetValue\">";
  71.         requestMain += "              <a:Value>" + resolutionTypeValue + "</a:Value>";
  72.         requestMain += "            </c:value>";
  73.         requestMain += "          </a:KeyValuePairOfstringanyType>";
  74.         requestMain += "        </a:Parameters>";
  75.         requestMain += "        <a:RequestId i:nil=\"true\" />";
  76.         requestMain += "        <a:RequestName>CloseIncident</a:RequestName>";
  77.         requestMain += "      </request>";
  78.         requestMain += "    </Execute>";
  79.         requestMain += "  </s:Body>";
  80.         requestMain += "</s:Envelope>";
  81.         var req = new XMLHttpRequest();
  82.         req.open("POST", Sdk.Tools._getServerUrl(), false)
  83.         // Responses will return XML. It isn't possible to return JSON.
  84.         req.setRequestHeader("Accept", "application/xml, text/xml, */*");
  85.         req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
  86.         req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
  87.         req.send(requestMain);
  88.  
  89.         //work with response here
  90.         return req.responseXML.xml;
  91.     },
  92.     __namespace: true
  93. };

Enjoy yourself,

N.JL

Open a html webresource as a window or a dialog box in CRM 2011.

Hi Guys,

If you need to open a web resource as a window or as a dialog in Dynamics CRM 2011 you can use these methods. But you need to know somethings:
- When you open a dialog you cannot use anymore F12 key to debug javascript code in your called webresource.
- An opened dialog cannot refresh or close a parent window. If you need to refresh the parent entity form you need to use openWebResourceAsWindow() insteed of openWebResourceAsDialog(). because, in the window mode you can use :

window.opener.location.reload();


Source Code
  1.  
  2. /// <summary>
  3. /// Allow to open a html webresource as a dialog box
  4. /// </summary>
  5. /// <param name="webResourceName"><b>string</b>: HTML web resource logical name like (new_webresource.html)</param>
  6. /// <param name="webResourceData"><b>string</b>: URI Encoded web resource data using encodeURIComponent() that begins with "?"</param>
  7. /// <param name="width"><b>int</b>: the width of the window without (px)</param>
  8. /// <param name="height"><b>int</b>: the height of the window without (px)</param>
  9. /// <param name="viewScrollbars"><b>bool</b>: allow to view the scrollbars (true or false)</param>
  10. /// <param name="viewToolbar"><b>bool</b>: allow to view the toolbar (true or false)</param>
  11. /// <param name="viewMenubar"><b>bool</b>: allow to view the menubar (true or false)</param>
  12. /// <param name="viewLocation"><b>bool</b>: allow to view the location (true or false)</param>
  13. function openWebResourceAsDialog(webResourceName, webResourceData, width, height, viewScrollbars, viewToolbar, viewMenubar, viewLocation) {
  14.     var $v_0 = Mscrm.CrmUri.create(String.format("$webresource:{0}", webResourceName));
  15.  
  16.     if (!isNullOrEmptyString(webResourceData)) {
  17.         $v_0 = $v_0 + webResourceData;
  18.     }
  19.     var parameters = "";
  20.     if (viewScrollbars !== undefined && viewScrollbars == true) {
  21.         parameters = "scrollbars=1,";
  22.     }
  23.     else {
  24.         parameters = "scrollbars=0,";
  25.     }
  26.     if (viewToolbar !== undefined && viewToolbar == true) {
  27.         parameters += "toolbar=1,";
  28.     }
  29.     else {
  30.         parameters += "toolbar=0,";
  31.     }
  32.     if (viewMenubar !== undefined && viewMenubar == true) {
  33.         parameters += "menubar=1,";
  34.     }
  35.     else {
  36.         parameters += "menubar=0,";
  37.     }
  38.     if (viewLocation !== undefined && viewLocation == true) {
  39.         parameters += "location=1";
  40.     }
  41.     else {
  42.         parameters += "location=0";
  43.     }
  44.  
  45.     return openStdDlg($v_0, null, width, height, true, false, parameters);
  46. }
  47.  
  48. /// <summary>
  49. /// Allow to open a html webresource as a window
  50. /// </summary>
  51. /// <param name="webResourceName"><b>string</b>: HTML web resource logical name like (new_webresource.html)</param>
  52. /// <param name="webResourceData"><b>string</b>: URI Encoded web resource data using encodeURIComponent() that begins with "?"</param>
  53. /// <param name="width"><b>int</b>: the width of the window without (px)</param>
  54. /// <param name="height"><b>int</b>: the height of the window without (px)</param>
  55. /// <param name="viewScrollbars"><b>bool</b>: allow to view the scrollbars (true or false)</param>
  56. /// <param name="viewToolbar"><b>bool</b>: allow to view the toolbar (true or false)</param>
  57. /// <param name="viewMenubar"><b>bool</b>: allow to view the menubar (true or false)</param>
  58. /// <param name="viewLocation"><b>bool</b>: allow to view the location (true or false)</param>
  59. function openWebResourceAsWindow(webResourceName, webResourceData, width, height, viewScrollbars, viewToolbar, viewMenubar, viewLocation) {
  60.     var $v_0 = Mscrm.CrmUri.create(String.format("$webresource:{0}", webResourceName));
  61.  
  62.     if (!isNullOrEmptyString(webResourceData)) {
  63.         $v_0 = $v_0 + webResourceData;
  64.     }
  65.     var parameters = "";
  66.     if (viewScrollbars !== undefined && viewScrollbars == true) {
  67.         parameters = "scrollbars=1,";
  68.     }
  69.     else {
  70.         parameters = "scrollbars=0,";
  71.     }
  72.     if (viewToolbar !== undefined && viewToolbar == true) {
  73.         parameters += "toolbar=1,";
  74.     }
  75.     else {
  76.         parameters += "toolbar=0,";
  77.     }
  78.     if (viewMenubar !== undefined && viewMenubar == true) {
  79.         parameters += "menubar=1,";
  80.     }
  81.     else {
  82.         parameters += "menubar=0,";
  83.     }
  84.     if (viewLocation !== undefined && viewLocation == true) {
  85.         parameters += "location=1";
  86.     }
  87.     else {
  88.         parameters += "location=0";
  89.     }
  90.     return openStdWin($v_0, null, width, height, parameters)
  91. }
  92.  
  93. /// <summary>
  94. /// Allows to open the custom Discount Dialog
  95. /// </summary>
  96. function openDiscountDialog() {
  97.     if (Xrm.Page.data.entity.getIsDirty()) {
  98.         alert("One or more fields are modified. Please save the form.");
  99.         return;
  100.     }
  101.     var entityId = Xrm.Page.data.entity.getId();
  102.     var entityName = Xrm.Page.data.entity.getEntityName();
  103.     var customParameters = encodeURIComponent("?EntityName=" + entityName + "&EntityId=" + entityId);
  104.     openWebResourceAsDialog("njl_discountDialog.html", customParameters, 280, 130, false, false, false, false);
  105. }
  106.  
  107. /// <summary>
  108. /// Allows to open the custom Incident Resolution Window
  109. /// </summary>
  110. function openIncidentResolutionWindow() {
  111.     if (Xrm.Page.data.entity.getIsDirty()) {
  112.         alert("One or more fields are modified. Please save the form.");
  113.         return;
  114.     }
  115.     var entityId = Xrm.Page.data.entity.getId();
  116.     var entityName = Xrm.Page.data.entity.getEntityName();
  117.     var customParameters = encodeURIComponent("?EntityName=" + entityName + "&EntityId=" + entityId);
  118.     openWebResourceAsWindow("njl_incidentResolutionWindow.html", customParameters, 400, 280, true, false, false, true);
  119. }

Enjoy yourself,
N.JL

Wednesday, February 5, 2014

Error: Unable to load plug-in Assembly in offline mode for Dynamics CRM 2011 / CRM 2013

Hi Guys,

If you are working on Dynamics CRM 2011 or 2013, and you need to work with offline mode of CRM Outlook Client. And when you do something that need a custom plugin execution. You may come face-to-face with this kind of probleme :

Error Message : Unable to load plug-in Assembly


 And when you download the log file you will see something like this :

Public key token 0868a8a927707e20 is not found in allow list.


The reason for this error is that when you install the CRM Outlook offline client, this one adds in your system registry a new entry called Allow List that contains all public token keys of the allowed plugins. But, this Allow List don't contain the public token key of your plugin. You need to add all public token keys of the offline plugins in this Allow List.

To do it you need to :

  • Open your PRT (Plugin Registration Tool).
  • Select, one by one, all plugins that contain offline mode. Properties window will contains all details about your plugin
  • Copy the public key token like this.


  • You need to open your system registry
  • Navigate to this location : HKEY_CURRENT_USER\Software\Microsoft\MSCRMClient\AllowList

  • Click on AllowList and create a new key:

  • Paste the public token key in the name of the new key.
  • Repeat this operation for all offline plugins

Have a nice day,

N.JL

Tuesday, February 4, 2014

How to programmatically initilize mapped attributes when you create a new record

Hi Guys,

When you have a 1:N relationship in Dynamics CRM 2011/2013 between two entities such as Account and Contact, this relationship can be respresented by a subgrid of contacts on the account form.

If this relationship contains some mapping attributes, and you want to create a contact from this subgrid, the new contact record will contains all mapped attributes with data from the parent account record. but when you want to create this record programmatically using a plugin, this mapping will dont work.

To force this mapping using the code, you need to use InitializeFromRequest - InitializeFromResponse.

The InitializeFromRequest - InitializeFromResponse message allow CRM to initialize all mapping attribute between source and target entities.

the InitializeFromResponse object contain a member called Entity that contains a memory image of the target entity record with all mapped attributes. So you need to get this Entity object and call service.create().

There is an example that illustrate this case :

  // Allow CRM to initialize all mapping attributes between account and contact entities.
  InitializeFromRequest initializeFromRequest = new InitializeFromRequest();
  initializeFromRequest.EntityMoniker = new EntityReference("account", accountRecord.Id);
  initializeFromRequest.TargetEntityName = "contact";
  initializeFromRequest.TargetFieldType = TargetFieldType.All;

  InitializeFromResponse initializeFromResponse = (InitializeFromResponse)service.Execute(initializeFromRequest);


  // Create a new contact record with all initialized mapped attributes
  Entity contact = initializeFromResponse.Entity;
  service.Create(contact);



have a nice day.

N.JL

Monday, July 8, 2013

How to resolve this problem SecLib::AccessCheckEx failed.

Hi Guys,

If someone had an error like this one while testing a scenario on his  CRM 2011 organization:

Unhandled Exception: System.ServiceModel.FaultException
PluginName : SecLib::AccessCheckEx failed. 
Returned hr = -2147187962, 
ObjectID: 8f3a3333-09e3-e211-b4c7-0050568c06b4, 
OwnerId: a9acc15c-95d2-e211-b3ed-0050568c06b4,  
OwnerIdType: 8 
and CallingUser: 576bd94b-27e3-e211-9980-0050568c06b4. 

ObjectTypeCode: 10008, 
objectBusinessUnitId: 6fad00e6-71d2-e211-b3ed-0050568c06b4, AccessRights: WriteAccess 


Don't worry, it's a right problem. But to resolve it, you need to have a database access to the CRM Sql Server.

You need to verify these points :

- If you don't know who is the CallingUser with the id : 576bd94b-27e3-e211-9980-0050568c06b4 you need to make a search on SystemUser table.

USE [ORGANIZATION_MSCRM]
GO

SELECT * FROM SystemUserBase WHERE SystemUserId = '56C9CC2B-E2C4-4012-B946-34024CBBA15A'

- After that, you need to enumerate the user's roles.
- Then, You need to detect the entity that generate the problem. To do this, you need to use the Object Type Code information : ObjectTypeCode: 10008


USE [ORGANIZATION_MSCRM]
GO

SELECT * fROM EntityView WHERE ObjectTypeCode = 10008

Execute this query to get entity name,

- Finnally, use this information : AccessRights: WriteAccess to verify in all user's roles if this entity had write privilege

You will find that any role has this privilege on this entity.

So, add this privilege to the role that you want and retry your scenario. You will see that it works.

have a nice day.

N.JL



Thursday, June 27, 2013

How to use Fiddler to debug CRM 2011 Javascript and HTML Webresources


Hi Guys,

In order to properly develop JavaScript and/or Html webresources, a CRM 2011 developer needs to make many publications on CRM development server, sometimes, with many errors. And when a team works on the same server, especially on the same entity, that can make the work troublesome and make any back slowly during these publications.

Using Fiddler 2 locally as an auto-responder is the solution.  


As a web debugging proxy, Fiddler will intercept any session (web call) outgoing form your local machine. And it can redirect some session to call instead of letting it out to web server. This is the role of the Auto-Responder.



And now, follow these steps:


  1. Launch Fiddler 2
  2. Make a Filter to show only sessions going to CRM Server like this:

  3. After this operation, select all session in the “Web Sessions” list and remove theme.

  4. Open IE and go to “ Inernet Option”, and delete “Temporary Internet Files and Website Files” like this :


  5. Back to Fiddler and click to Autoresponder tab.
  6. Ckeck this two options

  7. In Web Sessions List, Select Session line corresponding to your javascript/Html webresource that you want to work on then, drag and drop it in " If URI Matchs..." list.


  8. That add a line in this list. This line starts With the keyword : "EXACT". The same line is added in the first combbox of the "Rule Editor", and a in the second combobox this string "*200-SESSION_211" is added.


  9. You need to replace EXACT keyword by REGEX keyword In the first combobox, then replace the entire URL string up before the name of the WebResources by "*/" and finally you need to add ".*" in the end of string like this : 
  10. EXACT:http://ServerName/OrgName/WebResources/new__common.utilities.js
    become
    REGEX:.*/new_common.utilities.js.*



  11. After that, in the second combobox, put the local file path of your webresource like this:




  12. Finally click to Save.
Repeat this operation for all your webresources that you want to work on. and not forget to empty Temporary IE Files everytime you want to put a new webresource.

Have a nice Day.

I hope that this post helps you.

N.JL