Friday, January 30, 2015

Workflow Wait Conditions: Best Practices - Dynamics CRM 2011

Scheduling recurring workflows in CRM

CRM 2011 Javascript null check

if (Xrm.Page.getAttribute('myfield') != null) {
    var text = '';
    if (Xrm.Page.getAttribute('myfield').getValue() != null) {
        text = Xrm.Page.getAttribute('myfield').getSelectedOption().text;
    }
}



function SectionExistsOnForm(tabName, sectionName) {
    var section = Xrm.Page.ui.tabs.get(tabName).sections.get(sectionName);
    return section != null;
}

function FieldExistsOnForm(field) {
    var fieldControl = Xrm.Page.getAttribute(field);
    return fieldControl != null;
}

function GetOptionSetText(field) {
    if (FieldExistsOnForm(field)) {
        var text = '';
        if (Xrm.Page.getAttribute(field).getValue() != null) {
            text = Xrm.Page.getAttribute(field).getSelectedOption().text;
        }
        return text;
    }
}

function GetLookupValue(lookup) {
    var name = '';
    var lookupid;
    var lookupObject = Xrm.Page.getAttribute(lookup);

    if (lookupObject != null) {
        var lookUpObjectValue = lookupObject.getValue();
        if ((lookUpObjectValue != null)) {
            name = lookUpObjectValue[0].name;
            lookupid = lookUpObjectValue[0].id;
        }
    }

    return lookupid;
}

function SetLookupValue(lookup, name, id, entityType) {
    if (FieldExistsOnForm(lookup)) {
        var lookupid = null;
        var lookupObject = Xrm.Page.getAttribute(lookup);
        var value = new Array();
        value[0] = new Object();
        value[0].id = id;
        value[0].name = name;
        value[0].entityType = entityType;

        Xrm.Page.getAttribute(lookup).setValue(value);
    }
}

Wednesday, January 28, 2015

Adding HTML web resource in Visual Ribbon editor


Query for getting label of Optionset Used in SSRS report


  select t1.activityid,t1. abc_tasktype,t2.value as ActivityName   FROM Task t1
   left outer join StringMap t2 on 
        (t2.AttributeName = 'abc_tasktype'
        and t2.ObjectTypeCode = 4212)

Thursday, January 15, 2015

Best practices for activity reporting in micro soft dynamics crm 2011.

Updates the email address of a Crm 2011 User record from Active Directory.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices.AccountManagement;
using Microsoft.Xrm.Client;
using Microsoft.Xrm.Client.Services;
using Microsoft.Xrm.Sdk;
using System.DirectoryServices;

namespace UpdateCRM2011UsersFromAD
{
    class Program
    {
        static Dictionary<string, string> xRMToADFields = new Dictionary<string, string>();
        /// <summary>
        /// Setup which xRM fields map to which AD fields
        /// </summary>
        public static void SetupFieldMapping()
        {
            xRMToADFields.Add("firstname", "givenName");
            xRMToADFields.Add("lastname", "sn");
            xRMToADFields.Add("internalemailaddress", "mail");
            xRMToADFields.Add("title", "title");
            xRMToADFields.Add("address1_telephone1", "telephoneNumber");
            xRMToADFields.Add("mobilephone", "mobile");
            xRMToADFields.Add("address1_fax", "facsimileTelephoneNumber");
            xRMToADFields.Add("address1_line1", "streetAddress");
            xRMToADFields.Add("address1_city", "l");
            xRMToADFields.Add("address1_stateorprovince", "st");
            xRMToADFields.Add("address1_postalcode", "postalCode");
            xRMToADFields.Add("address1_country", "co");
        }

        /// <summary>
        /// Finds differences in email between AD and crm 2011 user record.
        /// Argument0: CRM 2011 Url ex. http://crm/crmorg
        /// Argument1: Run mode (S)can, (P)rompt, or (U)pdate
        /// </summary>
        /// <param name="args"></param>
        public static void Main(string[] args)
        {
            Console.WriteLine("Initializing...");
            SetupFieldMapping();

            // Grab the Crm Url from the first line argument. Ex. http://crmservername/crmorgname
            string crmUrl = args[0];

            // Grab the running mode (S = scan mode, P = prompt mode, U = update mode)
            // scan mode only displays the differences
            // prompt mode prompts you before updating the current record
            // and update mode updates everything without

            string runMode;

            // Default it to Prompt mode if not entered
            if (args.Count() > 1)
                runMode = args[1];
            else
                runMode = "P";

            runMode = runMode.ToUpper();

            string crmConnectionString = "Url=" + crmUrl;
            var systemConnection = CrmConnection.Parse(crmConnectionString);

            using (var crmContext = new CrmOrganizationServiceContext(systemConnection))
            {
                // Disable caching
                crmContext.TryAccessCache(cache => cache.Mode = OrganizationServiceCacheMode.Disabled);

                // Get all the non disabled users
                var enabledUsers = (from u in crmContext.CreateQuery("systemuser") where u.GetAttributeValue<bool>("isdisabled") == false select u);

                // Grab the domain context
                Dictionary<string, string> modifiedFields = new Dictionary<string, string>();

                foreach (var currentEnabledUser in enabledUsers)
                {
                    crmContext.Detach(currentEnabledUser);

                    // Make sure the user record is valid and has a domain name.
                    if (!string.IsNullOrWhiteSpace(currentEnabledUser.GetAttributeValue<string>("domainname")))
                    {
                        // Get System User's Domain name and email address.
                        string userDomainName = currentEnabledUser.GetAttributeValue<string>("domainname");
             
                        string domainName = userDomainName.Substring(0, userDomainName.IndexOf('\\'));

                        PrincipalContext domain = new PrincipalContext(ContextType.Domain, domainName);
             
                        // Grab the crm system user's Active Directory object
                        UserPrincipal ADUserRecord = UserPrincipal.FindByIdentity(domain, userDomainName);

                        if (ADUserRecord != null)
                        {
                            bool isUserModified = false;
                            Entity userObject = new Entity("systemuser");
                            userObject.Id = currentEnabledUser.Id;
                            crmContext.Attach(userObject);

                            // Open up the actual directory entry object which contains much more data than a simple user principal object
                            using (DirectoryEntry underlyingADRecord = (DirectoryEntry)ADUserRecord.GetUnderlyingObject())
                            {
                                // Look through each field, if they do not match prompt/or update
                                foreach (var currentProperty in xRMToADFields)
                                {
                                    // Get the AD and the CRM values for the current property.
                                    string adValue = underlyingADRecord.Properties.Contains(currentProperty.Value)
                                                   ? underlyingADRecord.Properties[currentProperty.Value].Value.ToString()
                                                   : "";

                                    string crmValue = currentEnabledUser.Attributes.Contains(currentProperty.Key)
                                                    ? currentEnabledUser.GetAttributeValue<string>(currentProperty.Key)
                                                    : "";

                                    // Check if any of the fields are modified if so turn the flag to true without overriding it.
                                    if ((currentEnabledUser.GetAttributeValue<string>(currentProperty.Key) == null && !string.IsNullOrWhiteSpace(adValue))
                                        ||
                                        adValue.ToLower() != crmValue.ToLower())
                                    {
                                        // It is the first modified field of a new user so display the user we are processing.
                                        if (!isUserModified)
                                        {
                                            Console.WriteLine();
                                            Console.WriteLine("Modifications to the user: {0}", userDomainName);
                                            Console.WriteLine();
                                        }

                                        // Display the fields that need an update
                                        Console.WriteLine("Old {0}: {1}{3}New {0}: {2}{3}",
                                            currentProperty.Key,
                                            crmValue,
                                            adValue,
                                            Environment.NewLine);

                                        // Put the changes to the User Object
                                        userObject[currentProperty.Key] = adValue;

                                        // Flag that user record has been modified
                                        isUserModified |= true;
                                    }
                                }

                                // If the record has modifications that we need to push and it is not scan mode run the update block
                                if (isUserModified && runMode != "S")
                                {
                                    // Try prompting the user if the runmode is not on update mode
                                    if (runMode != "U")
                                    {
                                        // Prompt the user if we should update this record.
                                        Console.WriteLine("Would you like to update the record Y/N/U U for Updating all the users.");
                                        var response = Console.ReadLine();

                                        response = response.ToUpper().ElementAt(0).ToString();
                                     
                                        // if they said U switch the run mode to update so they don't get consequent prompts.
                                        if (response == "U")
                                            runMode = "U";

                                        // If it is not a positive response skip updating the record, start processing the next record
                                        if (response != "U" && response != "Y")
                                            continue;
                                    }

                                    // If the code reached here it means we want to push the user object to the crm server
                                    try
                                    {
                                        crmContext.UpdateObject(userObject);
                                        crmContext.SaveChanges();

                                        Console.WriteLine("Updated User: {0}", userDomainName);
                                    }
                                    catch (Exception ex)
                                    {
                                        Console.WriteLine("Error on user {0]", userDomainName);
                                        Console.WriteLine(ex.Message);
                                    }

                                    Console.WriteLine();
                                }
                            }
                            crmContext.Detach(userObject);
                        }
                        else
                            Console.WriteLine("Warning: User {0} no longer exists in AD.", userDomainName);
                    }
                }
            }

            Console.WriteLine("Run completed, press any key to continue...");
            Console.ReadKey();
        }
    }
}

Reports Basics

ILMerge Issues

http://inogic.com/blog/2014/12/ilmerge-issues/

Inside Report Prefiltering

Capturing and Analysing SQL Queries in CRM Implementations

Finding the value of the state and status codes in CRM 2011

select 
    AttributeName, 
    AttributeValue,
    Value
from dbo.StringMap 
where
(dbo.StringMap.AttributeName = 'statuscode' 
or
dbo.StringMap.AttributeName = 'statecode')
and 
dbo.StringMap.ObjectTypeCode = 1





Will display the following values for the Account Entity ( ObjectTypeCode = 1 ):

AttributeName AttributeValue Value 
statecode    0      Active
 
statecode   1       Inactive
 
statuscode  1   Active
 
statuscode   2 Inactive

Extension Method

Q10. What is Extension method?
Ans. An extension method is a static method of a static class that can be invoked like as an instance method syntax. Extension methods are used to add new behaviors to an existing type without altering.

In extension method "this" keyword is used with the first parameter and the first parameter will be of type that is extended by extension method. Other parameters of extensions types can be of any types (data type).

Example: //defining extension method public static class MyExtensions
{ public static int WordCount(this String str) {

return str.Split(new char[] { ' ', '.', ',' }).Length; } }
 class Program { public static void Main() { string s = "Dot Net Tricks Extension Method Example";
 //calling extension method int i = s.WordCount(); Console.WriteLine(i); } }
//output: //6

Key points about extension method

1. An extension method is defined as static method but it is called like as an instance method.

2. An extension method first parameter specifies the type of the extended object, and it is preceded by the "this" keyword.

3. An extension method having the same name and signature like as an instance method will never be called since it has low priority than instance method.

4. An extension method couldn't override the existing instance methods.

5. An extension method cannot be used with fields, properties or events.

6. The compiler doesn't cause an error if two extension methods with same name and signature are defined in two different namespaces and these namespaces are included in same class file using directives. Compiler will cause an error if you will try to call one of them extension method.

Anonymous Method and Lambda Expression

What is anonymous method?
Ans. The concept of anonymous method was introduced in C# 2.0. An anonymous method is an inline unnamed method in the code. It is created using the delegate keyword and doesn’t have its name and return type.
In this way, an anonymous method has no name, optional parameters and return type; it has only body. An anonymous method behaves like a regular method and allows you to write inline code in place of regular method.



class Program {
 //delegate for representing anonymous method
delegate int del(int x, int y); static void Main(string[] args)
 { //anonymous method using delegate keyword
del d1 = delegate(int x, int y)
 { return x * y; };
 int z1 = d1(2, 3);
 Console.WriteLine(z1); } }




Key points about anonymous method
1. A variable, declared outside the anonymous method can be accessed inside the anonymous method.
2. A variable, declared inside the anonymous method can’t be accessed outside the anonymous method.
3. We use anonymous method in event handling.
4. An anonymous method, declared without parenthesis can be assigned to a delegate with any signature.
5. Unsafe code can’t be accessed within an anonymous method.
6. An anonymous method can’t access the ref or out parameters of an outer scope.



What is lambda expression?
Ans. The concept of lambda expression was introduced in C# 3.0. Typically, lambda expression is a more concise syntax of anonymous method. It is just a new way to write anonymous method. At compile time all the lambda expressions are converted into anonymous methods according to lambda expression conversion rules. The left side of the lambda operator "=>" represents the arguments of anonymous method and the right side represents the method body.
Lambda expression Syntax



(Input-parameters) => expression-or-statement-block
Types of Lambda expression
1. Statement Lambda -Statement lambda has a statement block on the right side of the lambda operator "=>". x => { return x * x; };
2. Expression Lambda - Expression lambda has only an expression (no return statement or curly braces), on the right side of the lambda operator "=>".

x => x * x; // here x*x is expression


Anonymous Method and Lambda Expression example:
 class Program { //delegate for representing anonymous method
delegate int del(int x, int y);
static void Main(string[] args)

{ //anonymous method using expression lambda
del d1 = (x, y) => x * y; //
 or (int x, int y) => x * y;
//anonymous method using statement lambda del d2 = (x, y) => { return x * y; };
 // or (int x, int y) => { return x * y; };
//anonymous method using delegate keyword
del d3 = delegate(int x, int y)
 { return x * y; };
int z1 = d1(2, 3);
 int z2 = d2(3, 3);
int z3 = d3(4, 3);
 Console.WriteLine(z1);
 Console.WriteLine(z2);
 Console.WriteLine(z3);
 } } /

Sharepoint - CRM Integration

Dynamics-CRM-DateTimes

Top 25 Dynamics CRM Blog

MSCRM 2011 Online bookmarks

CRM 2011 Server Setup Commonly Asked Questions

As customers are starting to plan for CRM 2011 installations and upgrades, we’ve begun to see questions regarding environment setups.  Here’s a list of the questions I’ve seen thus far:

Q: Are the CRM 2011 Report Extensions (commonly referred to as the “report connector”) an optional component?
A: All installations now require the CRM 2011 Report Extensions to be installed and configured on the SQL Reporting Server.  If it is not installed, certain features will not work properly: reporting will not function, creating new organizations, and organization imports will be blocked until the extensions are installed and configured.

Q: Do I need to install the CRM 2011 Reporting Extensions prior to installing CRM?
A: No, these should be installed after you install the CRM 2011 Server components.

Q: When installing CRM server roles on different servers (ex: install front-end and deployment components on server1 and back-end components on server2) I am not prompted to install the reporting extensions, why is this?
A: When the CRM server roles are installed separately (without first installing a CRM full-server) you’ll notice that no organizations are created by default.  Once the servers are all setup and configured, the first step to setup CRM is to launch deployment manager and create an organization.  It is at that time you will be required to input a reporting server that has the CRM 2011 Reporting Extensions installed.

Q: On CRM 4.0, as long as the report extensions were not installed, a Reporting Server (or scaled out reporting server farm) could host reports for multiple CRM installations/deployments.  How has this changed in CRM 2011?
A: In CRM 2011 the Reporting Extensions are now required, which means each Reporting server (or scaled out reporting server farm) with the report extensions installed may only host reports for a single CRM 2011 Deployment.  NOTE: The Reporting Server (or scaled out reporting server farm) can host reports for multiple tenants (organizations) in the deployment.

Q: If I were to run all CRM servers services under different service accounts how many service accounts do I need and what CRM groups should each service account belong to?
A: There are numerous configurations you could use to accomplish this, but if you were to separate everything here is a table explaining what group membership is required-- I’ve also included SSRS and SQL server:


Service
PrivUser
Group
SqlAccess
Group
PrivRept
Group
Rept
Group
Perf. Log 
Users*
CRM User?
Deployment Services SvcAcct
þ
þ
-
-
-
NO
Application Service (CRMAppPool)
þ
þ
-
-
þ
NO
Async service SvcAcct
þ
þ
-
-
þ
NO
Sandbox services SvcAcct
NO
NO
-
-
þ
NO
SQL Server SvcAcct
-
-
-
-
-
-
SQL Reporting Services SvcAcct
þ
-
þ
-
-
NO
Email router account**
þ
-
-
-
-
NO
Installing User***
-
-
-
þ
-
þ
User accounts in CRM
NO
NO
NO
þ
-
þ






* The performance log user group is a local group on each server and not a domain group
** Email router will run as local system
*** The Installing user should be a separate service account, but it should not be used to run any services.
IMPORTANT: If any of the service accounts are created as users in CRM, you may encounter various problems, some of which are potential security issues.

Q: I am concerned when it comes to security and want to be sure I limit my attack surface whenever possible.  What Windows Server Roles and Features are required for each CRM Server role?
A: Below is a table broken down by the 8 different server roles CRM installs.



Component
Web
App
Org
WS
Disc
WS
Help
Server
Depl
Tools
Depl
WS
Async
Svc
Sandbox
Svc

IIS Web Server Role
þ
þ
þ
þ
-
þ
-
-

.NET HTTP  Activation
-
þ
þ
-
-
þ
-
-

File Server Indexing Services
-
-
-
þ
-
-
-
-

Windows PowerShell
-
-
-
-
þ
-
-
-




NOTE: The IIS Web Server will also install the following role services:
·Web-Static-Content
·Web-Default-Doc
·Web-Http-Errors
·Web-Http-Redirect
·Web-Dir-Browsing
·Web-Asp-Net
·Web-Windows-Auth
·Web-Stat-Compression
·Web-Dyn-Compression
·Web-Mgmt-Console
·Web-Metabase

Q: If I want to split up my roles between a CRM Front-End Server and a CRM Back-End Server, but I don’t want to have a third server just for the purpose of hosting the deployment tools.  Is there a best practice or preferred placement given the two choices?
A: The deployment tools can live on either server.  As you see in the chart above, the IIS Windows Web Server Role is required for both the Front-End Server services as well as the Deployment tools.  If you have a goal of minimizing your attack surface and want to limit your installations of IIS, the best location for the Deployment Tools role would be on the Front-End Server as all web services would be hosted on your Front-End Server and the Back-End Server would be hosting non-IIS based components.

Q: How does the CRM Front-End Server Roles contact the CRM Sandbox and Async Services and do I need to set anything up or allow for any firewall exceptions?
A: The CRM Async service is not called directly by any of the other services.  The async service operates out of the AsyncOperations queue and will process records as they’re place into the queue.  However, the Sandbox service operates differently.  When work is handed off to the Sandbox service it is done so over a TCP channel (port 808 by default). In the case of a synchronous plugin, the web application server will contact the sandbox service; in the case of an asynchronous plugin, the async service will contact the sandbox service.  Also, note: if you are: A) Running the sandbox service on a dedicated server (not installing the full server role) and B) running the sandbox service as a service account identity, and not as network service, a dedicated SPN is required in active directory. The SPN would be homed under the service account running the sandbox service and would look like this: MSCRMSandboxService/<SandboxServerName>.  For example: if my sandbox server was named “CRMSandboxSrv01” and my sandbox service ran under CRM_Sandbox_SvcAcct my SPN would look like: MSCRMSandboxService/CrmSandboxSrv01 and the SPN would live under the CRM_Sandbox_SvcAcct user object in Active Directory.

Q: If I want to manage my CRM deployment via PowerShell are there any specific recommendations or “gotcha’s”?
A: Currently, if you wish to manage your CRM deployment via PowerShell, the Deployment Web Services must be running as a service account identity and not as Network Service. If you run the deployment web services as Network Service, certain functions of the CRM PowerShell add-in will return a security error.

If additional questions come up feel free to leave them as comments and we’ll do our best to address them in some way, shape, or form.  I hope this helps clear up the confusion around some of the more complex environment configurations and what operating system features and roles are required for various CRM Server Roles.




CRM 2011 Error Messages

Best practices for developing with Microsoft Dynamics CRM

.NET Task Parallel Library (TPL) in CRM 2011

Script Error “The system cannot find the file specified” when using Microsoft Dynamics CRM 2011.

Using Fiddler To Check For Kerberos Auth

http://blogs.msdn.com/b/crminthefield/archive/2012/10/10/using-fiddler-to-check-for-kerberos-auth.aspx

CRM 2011 Performance: Take advantage of better query performance for your Quickfinds

Microsoft Dynamics CRM 2015 White Papers & Technical

Dynamics CRM QuickFind on Selected View

Configuring SQL Server 2012 AlwaysOn Availability Groups with Dynamics CRM

CRM 2011 SSRS Drill down reports

How var type is different from anonymous type


Ans. var- var data type was introduced with C# 3.0. It is used to declare implicitly typed local variable means it tells the

compiler to figure out the type of the variable at compile time. A var variable must be initialized at the time of declaration.

For Example: var i = 20; // implicitly typed int i = 20; //explicitly typed var str = "1"; //declaration and initialization var num = 0; string s = "string"; //explicitly typed var s2 = s; // implicitly typed

Basically, var is an anonymous type, hence use it whenever you don't know the type of output or it is anonymous. Suppose you are

joining two tables and retrieving data from both the tables then the result will be an anonymous type since data will come from both the tables.

Expression assigned to var must be executed at compile time to know the type of output, so that var type may behave like the new type assigned to it.

DataContext context =
new DataContext();
var q =
(from e in context.Employee join d in context.Department on e.DeptID equals d.DeptID
select new { e.EmpID, e.FirstName, d.DeptName, d.DeptLocation });



Anonymous Type- An anonymous type is a simple class generated by the compiler within IL to store a set of values. var data type and new keyword is used to create an anonymous type.
var emp = new { Name = "Deepak", Address = "Noida", Salary = 21000 };
At compile time, the compiler will create an anonymous type, as follows:



class __Anonymous1
{ private string name;
 private string address;
int salary;
 public string Name { get { return name; } set { name=value } }
 public string Address { get { return address; }
 set { address = value; } } public int Salary { get { return salary; }
 set { salary = value; }
}
}



The anonymous type is very useful when you want to shape the result in your desired form like this:


DataContext context = new DataContext();
 var result = from book in context.Books where book.Price > 200 orderby book.IssueDate
 descending
select new { Name = book.Name, IssueNumber = "#" + book.Issue };

In above example, I change the name of the “Issue” field of Book table to “IssueNumber” and add # before value to get desired output.


Dynamics CRM Outlook Client Troubleshooting

Outlook Client Best Practices

Soap Retrieve Entity Request

RetrieveEntityRequest = function (logicalName, fnSuccessCallback, fnErrorCallback) {
/// Returns a sorted array of entities
var request = "";
request += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
request += "  <s:Body>";
request += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
request += "      <request i:type=\"a:RetrieveEntityRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">";
request += "        <a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
request += "          <a:KeyValuePairOfstringanyType>";
request += "            <b:key>EntityFilters</b:key>";
request += "            <b:value i:type=\"c:EntityFilters\" xmlns:c=\"http://schemas.microsoft.com/xrm/2011/Metadata\">Entity Attributes Privileges Relationships</b:value>";
request += "          </a:KeyValuePairOfstringanyType>";
request += "          <a:KeyValuePairOfstringanyType>";
request += "            <b:key>MetadataId</b:key>";
request += "            <b:value i:type=\"ser:guid\"  xmlns:ser=\"http://schemas.microsoft.com/2003/10/Serialization/\">00000000-0000-0000-0000-000000000000</b:value>";
request += "          </a:KeyValuePairOfstringanyType>";
request += "          <a:KeyValuePairOfstringanyType>";
request += "             <b:key>LogicalName</b:key>";
request += "             <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + logicalName + "</b:value>";
request += "          </a:KeyValuePairOfstringanyType>";
request += "          <a:KeyValuePairOfstringanyType>";
request += "            <b:key>RetrieveAsIfPublished</b:key>";
request += "            <b:value i:type=\"c:boolean\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">true</b:value>";
request += "          </a:KeyValuePairOfstringanyType>";
request += "        </a:Parameters>";
request += "        <a:RequestId i:nil=\"true\" />";
request += "        <a:RequestName>RetrieveEntity</a:RequestName>";
request += "      </request>";
request += "    </Execute>";
request += "  </s:Body>";
request += "</s:Envelope>";

return _ExecuteRequest(request, "Execute", .RetrieveEntityResponse, fnSuccessCallback, fnErrorCallback);
};