How to control PrincipalObjectAccess table growth in Microsoft Dynamics CRM 2011

Control PrincipalObjectAccess table growth in Microsoft Dynamics CRM 2011

SYMPTOMS: After you use Microsoft Dynamics CRM 2011, you may notice that the size of the SQL table PrincipalObjectAccess grows and could be using a large percentage of the database size.

 

CAUSE:

When records are deleted in Microsoft Dynamics CRM, the related PrincipalObjectAccess records are not removed.

 

RESOLUTION:

Apply Update Rollup 6, and then execute the script that is documented here. This script must be executed only one time after you apply Update Rollup 6. Update Rollup 6 and future Update Rollups will fix this known issue.

SQL Script To Execute
–Replace the text “Replace With DatabaseName” with your database name

–For Example

–USE [AdventureWorksCycle_MSCRM]
USE [<Replace With DatabaseName>]
GO

BEGIN TRY
BEGIN TRAN t1

IF NOT EXISTS (SELECT * FROM sys.sysobjects

WHERE id = object_id(N'[dbo].[ToDeletePOAEntries]’)

AND ObjectProperty(id, N’IsUserTable’) = 1)

create table ToDeletePoaEntries
(
ObjectId uniqueidentifier,
Otc int
)

IF NOT EXISTS (SELECT * FROM sys.sysindexes si

INNER JOIN sys.sysobjects so ON si.id = so.id

WHERE so.id = OBJECT_ID(N'[dbo].[ToDeletePoaEntries]’)

AND OBJECTPROPERTY(so.id, N’IsUserTable’) = 1

AND si.name LIKE ‘%mainindex%’)

CREATE UNIQUE NONCLUSTERED INDEX [mainindex] ON [dbo].[ToDeletePoaEntries]
(
[ObjectId] ASC,
[Otc] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

—– Insert records to be deleted in ToDeletePoaEntries

— go through all user-owned entities which are not replicated and don’t support duplicate detection
declare entity_cursor cursor local FORWARD_ONLY READ_ONLY
for select distinct e.ObjectTypeCode, e.BaseTableName, a.PhysicalName from EntityView e
inner join AttributeView a on e.EntityId = a.EntityId and a.IsPKAttribute = 1
where e.IsReplicated = 0 and e.IsDuplicateCheckSupported = 0 and e.OwnershipTypeMask & 1 = 1

open entity_cursor

declare @baseTableName sysname
declare @otc nvarchar(20)
declare @primaryKey sysname
declare @totalCollected int = 0
declare @currentCollected int

declare @tempRowCount int = 0
declare @collectstatement nvarchar(max)

fetch next from entity_cursor
into @otc, @baseTableName, @primaryKey

while @@FETCH_STATUS = 0
begin
print ‘Cleaning up POA for ‘ + @baseTableName

set @currentCollected = 0

set @collectstatement = ‘insert into ToDeletePoaEntries(ObjectId, Otc)
select distinct poa.ObjectId, poa.ObjectTypeCode
from PrincipalObjectAccess poa
left join ‘ + @baseTableName + ‘ e on poa.ObjectId = e.’ + @primaryKey +
‘ where e.’ + @primaryKey + ‘ is null and poa.ObjectTypeCode = ‘ + @otc;

print @collectstatement

exec(@collectstatement)
set @tempRowCount = @@ROWCOUNT
set @currentCollected = @currentCollected + @tempRowCount
print CAST(@currentCollected as nvarchar(20)) + ‘ records collected for ‘ + @baseTableName
set @totalCollected = @totalCollected + @currentCollected

fetch next from entity_cursor
into @otc, @baseTableName, @primaryKey
end

close entity_cursor
deallocate entity_cursor

print CAST(@totalCollected as nvarchar(20)) + ‘ total records collected’

— Delete query

— This scripts cleans up orphaned POA records for selected entities

declare @deleteBatchSize int = 50000
declare @deleteBatchSizeNVarChar nvarchar(10) = CAST(@deleteBatchSize as nvarchar(10))
declare @totalDeleted int = 0
declare @currentDeleted int
declare @deletestatement nvarchar(max)

set @currentDeleted = 0
set @tempRowCount = 0

— delete all records of the current entity type which don’t have corresponding object in the base table
set @deletestatement = ‘delete top (‘ + @deleteBatchSizeNVarChar + ‘) from PrincipalObjectAccess
from PrincipalObjectAccess poa
join ToDeletePoaEntries e on poa.ObjectId = e.ObjectId and poa.ObjectTypeCode = e.Otc’

print @deletestatement

— delete PrincipalObjectAccess records in batches
exec(@deletestatement)
set @tempRowCount = @@ROWCOUNT
set @currentDeleted = @currentDeleted + @tempRowCount

while @tempRowCount = @deleteBatchSize
begin
exec(@deletestatement)
set @tempRowCount = @@ROWCOUNT
set @currentDeleted = @currentDeleted + @tempRowCount

print CAST(@currentDeleted as nvarchar(20)) + ‘ records deleted ‘ + cast(getUtcdate() as nvarchar(50))
–cleanup

end

COMMIT TRAN t1

— Cleanup

DROP Table [dbo].[ToDeletePoaEntries]
PRINT ‘EXECUTION SUCCEED’
END TRY
BEGIN CATCH
ROLLBACK TRAN t1

— Cleanup

DROP Table [dbo].[ToDeletePoaEntries]

PRINT ‘EXECUTION FAILED :’ + ERROR_MESSAGE()
END CATCH

 

Note: This script only needs to be run one time after Update Rollup 6 or a future Update Rollup is installed. After the script is run to clean up the PrincipalObjectAccess table, the script does not need to be run after any future Update Rollup installations.

 

This link taken from http://support.microsoft.com/kb/2664150

Pass parameters to Plugin Using Secure or Unsecure Configuration Using Plugin Registration Tool in MS CRM 2011

Pass parameters to Plugin Using Secure or Unsecure Configuration to Plugin:

When you start developing plugins, you often need an input parameter or a configuration for the plugin execution which can be easily updated without having to re-compile and/or re-register the plugin.

For example , i want to read some of the data which may change every time. Rather than creating the custom entity to read the Configuration kind of thing better to use this method to read the Parameters.

Use the plugin step “Configuration”
When you register a plugin step, there is a field where you can specify some configuration parameters for the plugin execution as below:Image

Then in the Constructor of your plugin class you will get the configuration value which you can use later in the Execute method:

Image2

 

In the Quickwatch you can watch the total configuration as follows:

Image1

 

have a glance below for plugin code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xrm.Sdk;
using System.Xml;

namespace ReadPluginConfgInPlugins
{
public class PluginConfg : IPlugin
{
private readonly string _unsecureString;
private readonly string _secureString;

public PluginConfg(string unsecureString, string secureString)
{
if (String.IsNullOrWhiteSpace(unsecureString) || String.IsNullOrWhiteSpace(secureString))
{
try
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(unsecureString);
Guid DefaultQueueGuid = PluginConfiguration.GetConfigDataGuid(doc, “Contact Guid”);
string ContactFullName = PluginConfiguration.GetConfigDataString(doc, “Full Name”);
int MobileNumber = PluginConfiguration.GetConfigDataInt(doc, “Mobile Number”);
bool Gender = PluginConfiguration.GetConfigDataBool(doc, “Gender 0 refer to Male”);
}
catch (Exception ex)
{
throw new Exception(“SoapException” + ex.Message + “########” + ex.StackTrace + “$$$$Inner Exception” + ex.InnerException);
}
}
}

public void Execute(IServiceProvider serviceProvider)
{
//Extract the tracing service for use in debugging sandboxed plug-ins.
ITracingService tracingService =
(ITracingService)serviceProvider.GetService(typeof(ITracingService));

// Obtain the execution context from the service provider.
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

// For this sample, execute the plug-in code only while the client is online.
tracingService.Trace(“AdvancedPlugin: Verifying the client is not offline.”);
if (context.IsExecutingOffline || context.IsOfflinePlayback)
return;

// The InputParameters collection contains all the data passed
// in the message request.
if (context.InputParameters.Contains(“Target”) &&
context.InputParameters[“Target”] is Entity)
{
Entity entity = (Entity)context.InputParameters[“Target”];

}

}
}

}

For this approach also have a Pros and Cons.

PROS:

  • The step configuration is solution-aware so it will be automatically transported with the plugin step.

CONS:

  • You need to use the plugin registration tool or another application to update the step configuration.
  • The configuration is step-specific so you have to provide it and/or update it for every step even if the value is the same for all the steps (the configuration is on each step instead of the assembly or plugin type).
  • the configuration is just an attribute of the plugin step so you cannot control privileges on the configuration independently from privileges on plugin step entity.

*. Use the plugin step “Secure Configuration”
This is similar to the step Configuration except that the configuration data is stored in a separate entity which can be secured.
PROS:

  • The configuration data can be secured as any other entity using the CRM security model. This is useful when the configuration contains sensitive information such as passwords.

CONS:

  • Secure configuration is not solution aware so you will need to configure it for each environment.
  • You need to use the plugin registration tool or another application to update the step configuration.
  • The configuration is step-specific so you have to provide it and/or update it for every step even if the value is the same for all the steps (the configuration is on each step instead of the assembly or plugin type).

*. Use a Web Resource
You can store configuration information in web resources, for example you might have some XML configuration stored in a web resource and have your plugin read the web resource each time it executes.

PROS:

  • Web resources are solution aware and the GUID is preserved across environments so you can hardcode the web resource GUID in your plugin code. You can transport the web resource and the plugin in the same solution.
  • Can be easily updated using the CRM UI.

CONS:

  • You cannot secure the configuration since it depends on the web resource access privileges and most users will need at least read access to web resources.

Hope this may help you.

 

Regards,

Access MS CRM 2011 with IP address ,can get Odata Java Script Query Results

Access MS CRM 2011 with IP address ,can get Odata Java Script Query Results:

 

Some times we may access the CRM with IP address as below.AccessCrmWithIp

 

At this point of time CRM Javascript  Xrm.Page.context.getServerUrl() cant get the Server Url. To over come this use the following Java Script code to get the Server Url.

var serverUrl = document.location.protocol + “//” + document.location.host + “/” + Xrm.Page.context.getOrgUniqueName(); 

This will work fine for the both IP and CRM Serverl Urls.

Please have a glance the below example.

Below i am commenting var serverUrl = Xrm.Page.context.getServerUrl();

function OdataRetrieveMultipleUsingJquery(ODataFilterQuery) {
//var serverUrl = Xrm.Page.context.getServerUrl();

var serverUrl = document.location.protocol + “//” + document.location.host + “/” + Xrm.Page.context.getOrgUniqueName();
var Odata_OrgName = “/xrmservices/2011/OrganizationData.svc”;
var oDataUri = serverUrl + Odata_OrgName + ODataFilterQuery;
var jSonArray = new Array();

jQuery.ajax({
type: “GET”,
contentType: “application/json; charset=utf-8”,
datatype: “json”,
url: oDataUri,
async: false,
beforeSend: function (XMLHttpRequest) {
//Specifying this header ensures that the results will be returned as JSON.
XMLHttpRequest.setRequestHeader(“Accept”, “application/json”);
},
success: function (data, textStatus, XmlHttpRequest) {
if (data && data.d != null) {
jSonArray.push(data.d);
}
},
error: function (XmlHttpRequest, textStatus, errorThrown) {
alert(“Invalid Record Selection or No Record found with the Search Item”);
}
});

return jSonArray;
}

 

Hope this helps you.

 

Regards,

Performance is slow if the AsyncOperationBase table becomes too large in Microsoft Dynamics CRM

Performance is slow if the AsyncOperationBase table becomes too large in Microsoft Dynamics CRM

When you run Microsoft Dynamics CRM 4.0 or Microsoft Dynamics CRM 2011, the AsyncOperationBase table grows to be very large. When the table contains millions of records, performance is slow.

Additionally, errors that resemble the following are logged in the application event log on the server that is running Microsoft Dynamics CRM:

Event Type: Error 
Event Source: MSCRMDeletionService 
Event Category: None 
Event ID: 16387 
Date: 2009/01/26 
Time: 11:41:54 AM 
User: N/A 
Computer: CRMSERVER 
Description: Error: Deletion Service failed to clean up table=CleanupInactiveWorkflowAssembliesProcedure For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.
 

RESOLUTION

To resolve this problem, perform a cleanup of the AsyncOperationBase table by running the following script against the<OrgName>_MSCRM database, where the placeholder<OrgName> represents the actual name of your organization.

Warning Before you clean up the data, be aware that completed system jobs have business value in some cases and have to be stored for a long period. Therefore, you should discuss this with your organization’s administration staff first.

System jobs that are affected:

  • SQM data collection. Software Quality Metrics collects data for the customer experience program.
  • Update Contract States SQL job. This job runs one time per day at midnight. This job sets the expired contracts to a state of Expired.
  • Organization Full Text Catalog Index. Populates full text index in db for searching Microsoft Knowledge Base articles in CRM.

If recurring jobs were canceled, they will be removed. 

Notes

  • For Microsoft Dynamics CRM 4.0 The SQL script in this Knowledge Base article is a one-time effort only. You can add this as a SQL job to run on a recurring nightly, weekly, or monthly basis. As your CRM runs, you have to either apply this article weekly, depending on your business needs, or apply the solution by writing custom BULK DELETE jobs. (Refer to our CRM SDK documentation on the BulkDeleteRequest.QuerySet property, on the BulkDeleteRequest class, and on the order of deletion).
  • For Microsoft Dynamics CRM 2011 The SQL script in this Knowledge Base article is a one-time effort only. You can add this as a SQL job to run on a recurring nightly, weekly, or monthly basis. As your CRM runs, you have to either apply this article weekly, depending on your business needs, or apply the solution by using BULK DELETE jobs by defining a job by using the BULK DELETE wizard.
  • Make sure that the AsyncOperation records for workflows and the corresponding records are deleted from theWorkflowLogBase object.
  • Make sure that all the corresponding bulkdeletefailure records are deleted.
  • Make sure that only the following Async operation types are deleted if the state code of the types is 3 and the status code of the types is 30 or 32:
    • Workflow Expansion Task (1)
    • Collect SQM data (9)
    • PersistMatchCode (12)
    • FullTextCatalogIndex (25)
    • UpdateContractStates (27)
    • Workflow (10)
IF EXISTS (SELECT name from sys.indexes
                  WHERE name = N'CRM_AsyncOperation_CleanupCompleted')
      DROP Index AsyncOperationBase.CRM_AsyncOperation_CleanupCompleted
GO
CREATE NONCLUSTERED INDEX CRM_AsyncOperation_CleanupCompleted
ON [dbo].[AsyncOperationBase] ([StatusCode],[StateCode],[OperationType])
GO

declare @DeleteRowCount int
Select @DeleteRowCount = 2000
declare @DeletedAsyncRowsTable table (AsyncOperationId uniqueidentifier not null primary key)
declare @continue int, @rowCount int
select @continue = 1
while (@continue = 1)
begin      
begin tran      
insert into @DeletedAsyncRowsTable(AsyncOperationId)
      Select top (@DeleteRowCount) AsyncOperationId from AsyncOperationBase
      where OperationType in (1, 9, 12, 25, 27, 10) AND StateCode = 3 AND StatusCode in (30, 32)     
       Select @rowCount = 0
      Select @rowCount = count(*) from @DeletedAsyncRowsTable
      select @continue = case when @rowCount <= 0 then 0 else 1 end      
        if (@continue = 1)        begin
            delete WorkflowLogBase from WorkflowLogBase W, @DeletedAsyncRowsTable d
            where W.AsyncOperationId = d.AsyncOperationId             
 delete BulkDeleteFailureBase From BulkDeleteFailureBase B, @DeletedAsyncRowsTable d
            where B.AsyncOperationId = d.AsyncOperationId
 delete WorkflowWaitSubscriptionBase from WorkflowWaitSubscriptionBase WS, @DeletedAsyncRowsTable d
 where WS.AsyncOperationId = d.AsyncOperationID 
            delete AsyncOperationBase From AsyncOperationBase A, @DeletedAsyncRowsTable d
            where A.AsyncOperationId = d.AsyncOperationId             
            delete @DeletedAsyncRowsTable      
end       
commit
end
--Drop the Index on AsyncOperationBase
DROP INDEX AsyncOperationBase.CRM_AsyncOperation_CleanupCompleted

Improving the performance of the deletion script

  • To improve overall Microsoft Dynamics CRM performance, schedule the Microsoft Dynamics CRM Deletion Service to run during off-peak hours for Microsoft Dynamics CRM. By default, the service runs at the time that Microsoft Dynamics CRM was installed. However, you can set the service to run at 10:00 PM instead of at the default time. To do this, use the Microsoft Dynamics CRM ScaleGroup Job Editor. For more information, visit the following Microsoft Developer Network (MSDN) website:

    Note This action does not directly affect the performance of the script.

  • To improve the performance of the deletion scripts in this article and to improve the Microsoft Dynamics CRM Deletion Service code that runs similar deletions, add the following three indexes to the OrganizationName_MSCRM database before you run the deletion script in this article:
    CREATE NONCLUSTERED INDEX CRM_WorkflowLog_AsyncOperationID ON [dbo].[WorkflowLogBase] ([AsyncOperationID])
    GO 
    
    CREATE NONCLUSTERED INDEX CRM_DuplicateRecord_AsyncOperationID ON [dbo].[DuplicateRecordBase] ([AsyncOperationID])
    GO
    
    CREATE NONCLUSTERED INDEX CRM_BulkDeleteOperation_AsyncOperationID ON [dbo].[BulkDeleteOperationBase]
    (AsyncOperationID)
    GO
    

    Note If you do not add these indexes, the deletion script may take hours to run.

  • Stop the Microsoft Dynamics CRM Asynchronous Processing Service while you run this script.
  • Optional Rebuild the following indexes and update statistics:
    -- Rebuild Indexes & Update Statistics on AsyncOperationBase Table 
    ALTER INDEX ALL ON AsyncOperationBase REBUILD WITH (FILLFACTOR = 80, ONLINE = OFF,SORT_IN_TEMPDB = ON, STATISTICS_NORECOMPUTE = OFF)
    GO 
    -- Rebuild Indexes & Update Statistics on WorkflowLogBase Table 
    ALTER INDEX ALL ON WorkflowLogBase REBUILD WITH (FILLFACTOR = 80, ONLINE = OFF,SORT_IN_TEMPDB = ON, STATISTICS_NORECOMPUTE = OFF)
    
    GO
  • Optional Update Statistics with Full Scan on all the tables that are involved with this query by using the following commands (preferably at off peak hours):
    UPDATE STATISTICS [dbo].[AsyncOperationBase] WITH FULLSCAN
    UPDATE STATISTICS [dbo].[DuplicateRecordBase] WITH FULLSCAN
    UPDATE STATISTICS [dbo].[BulkDeleteOperationBase] WITH FULLSCAN
    UPDATE STATISTICS [dbo].[WorkflowCompletedScopeBase] WITH FULLSCAN
    UPDATE STATISTICS [dbo].[WorkflowLogBase] WITH FULLSCAN
    UPDATE STATISTICS [dbo].[WorkflowWaitSubscriptionBase] WITH FULLSCAN
  • Optional Change the MSCRM database’s recovery model to Simple to avoid excess generation of Microsoft SQL Server logs. For SQL Server 2005, log on to the Microsoft SQL Server Management Studio as Administrator, right-click your <org_name>_MSCRM database, click Properties, click Options, and then click Recovery Model. Mark Simple, and then click OK. After you run this script the first time, the <org_name>_MSCRM database recovery model should be switched back to FULL for the best data-recoverability model.

To determine the number of records to be deleted by the script in this article, run the following count script against the OrganizationName_MSCRM database:


Select Count(AsyncOperationId)from AsyncOperationBase WITH (NOLOCK)
where OperationType in (1, 9, 12, 25, 27, 10)
AND StateCode = 3 AND StatusCode IN (30,32)

Script error

When you run the cleanup script, you may receive an error message that resembles the following: 

The DELETE statement conflicted with the REFERENCE constraint “asyncoperation_workflowwaitsubscription”. The conflict occurred in database “Contoso_MSCRM”, table “dbo.WorkflowWaitSubscriptionBase”, column ‘AsyncOperationId’.The statement has been terminated.

If you receive this error message, stop the cleanup script, and then follow these steps to remove the remaining WorkflowWaitSubscription records that exist for completed or canceled workflows. These records should no longer exist, because they should have been deleted when the workflows were completed or canceled. You should not see any records that are returned from this query. Anything left in the WorkflowWaitSubscriptionBase table that appears in this query is an orphaned record. You cannot delete these records through the UI because the Microsoft CRM Async process is in a canceled or completed state.

The following script will verify how many orphaned WorkflowWaitSubscriptionBase records exist for completed and canceled workflow records:

select count(*) from workflowwaitsubscriptionbase WITH (NOLOCK) 

where asyncoperationid in

(Select asyncoperationid from AsyncOperationBase WITH (NOLOCK)

where OperationType in (1, 9, 12, 25, 27, 10)

AND StateCode = 3 AND StatusCode IN (30,32))

The following script will delete WorkflowWaitSubscriptionBase records for stranded WorkflowWaitSubscriptionBase records for completed and canceled workflow records:

delete from workflowwaitsubscriptionbase 
where asyncoperationid in(Select asyncoperationidfrom AsyncOperationBase
where OperationType in (1, 9, 12, 25, 27, 10) 
AND StateCode = 3 AND StatusCode IN (30,32))

After this delete statement is executed, the AsyncoperationBase and Workflow cleanup script will complete successfully.

 

MORE INFORMATION

For more information, click the following article numbers to view the articles in the Microsoft Knowledge Base:

954929 The AsyncOperation entity consumes a significant part of the [Org]_MSCRM database and causes poor performance in Microsoft Dynamics CRM
957871 The Workflow Expansion Task records cause the AsyncOperationBase table in the MSCRM database to grow too large in Microsoft Dynamics CRM 4.0

For more information about software update terminology, click the following article number to view the article in the Microsoft Knowledge Base:

824684 Description of the standard terminology that is used to describe Microsoft software updates

For more information about Microsoft Business Solutions CRM software hotfix and update package terminology, click the following article number to view the article in the Microsoft Knowledge Base:

887283 Microsoft Business Solutions CRM software hotfix and update package naming standards
 
This information has taken from the Microsoft site . . For ref click this lick http://support.microsoft.com/kb/968520
 
Regards,

Create Fields in MS CRM 2011 using CRM Metadata Service

Create Fields in MS CRM 2011 using CRM Metadata Service

Some times we may have a requirement to create more fields with same data type , so in this way if we try to create from the CRM it will take so much time to create all the fields. Better way i approach is using CRM Meta Data service we can create it easily.

Steps to Create Fields:

Step 1: Create On Console Application “CreateFieldsInCRMUsingMetaDataService” and paste the following code in your console application.

Step 2 : Specify your Schema Name and Display name separated by | (pipe) symbol. The next field must be separated with ,(Comma).

Code will detect the next field with ,(Comma).

Step 3: You may replace your Organization Prefix below as shown “new_”

In this code i am creating the Two Option Sets , you may create any field in the Meta Data Using this Service.

namespace CreateFieldsInCRMUsingMetaDataService
{
class CreateFieldsInCRM
{
static IOrganizationService service = GetOrgService();
public const int _languageCode = 1033;
static void Main(string[] args)
{
CreateBooleanFiledsInCRM();
}
public static IOrganizationService GetOrgService()
{
Uri oUri = new Uri(“http://<servername>/<OrgName>/XRMServices/2011/Organization.svc&#8221;);

//** Your client credentials

ClientCredentials cliCredentials = new ClientCredentials();
cliCredentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;

//Create your Organization Service Proxy
OrganizationServiceProxy _serviceProxy = new OrganizationServiceProxy(oUri, null, cliCredentials, null);
IOrganizationService Service = (IOrganizationService)_serviceProxy;
_serviceProxy.EnableProxyTypes();
return Service;
}
public static void CreateBooleanFiledsInCRM()
{
string SchemaAndDisplayNames = “gender|Gender,age|Age”;

string[] splitSchemaAndDisplayNamesByComma = SchemaAndDisplayNames.Split(new Char[] { ‘,’, ‘.’, ‘:’, });

foreach (string FieldNames in splitSchemaAndDisplayNamesByComma)
{
if (FieldNames.Trim() != “”)
{
string FieldSchemaAndDisplayNames = FieldNames.ToString();
string[] splitSchemaAndDisplayNames = FieldSchemaAndDisplayNames.Split(new Char[] { ‘|’ });

string schemaname = Regex.Replace(splitSchemaAndDisplayNames[0], “[^a-zA-Z0-9_.]+”, “”, RegexOptions.Compiled);
schemaname = “new_” + schemaname;
string displayname = splitSchemaAndDisplayNames[1];

//The below function will create the Fields in MS CRM
CreateAttributeInMsCRMOrgService(“new_entity”, schemaname, displayname, “”);

}
}
}
private static void CreateAttributeInMsCRMOrgService(string EntitySchemaName, string FieldSchemaName, string FieldDisplayName, string FieldDescription)
{
// Create storage for new attributes being created
List<AttributeMetadata> addedAttributes = new List<AttributeMetadata>();

// Create a boolean attribute
BooleanAttributeMetadata boolAttribute = new BooleanAttributeMetadata
{
// Set base properties
SchemaName = FieldSchemaName,
DisplayName = new Label(FieldDisplayName, _languageCode),
RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
Description = new Label(FieldDescription, _languageCode),
// Set extended properties
OptionSet = new BooleanOptionSetMetadata(
new OptionMetadata(new Label(“True”, _languageCode), 1),
new OptionMetadata(new Label(“False”, _languageCode), 0)
)
};

// Add to list
addedAttributes.Add(boolAttribute);

foreach (AttributeMetadata anAttribute in addedAttributes)
{
// Create the request.
CreateAttributeRequest createAttributeRequest = new CreateAttributeRequest
{
EntityName = EntitySchemaName,
Attribute = anAttribute
};

// Execute the request.
service.Execute(createAttributeRequest);
}

}

}
}

Regards,

Update Ownerid in the CRM Form

In some times , we may need to update the Owner Lookup with the Current logged in user in MS CRM 2011.

Wrong Method :

entity[“ownerid”] = new EntityReference(“systemuser”,Guid);

Preferred Method :

For this requirement we need to assign the Record to Current Logged in User in the Owner Look up.

Have a look the below code , it works fine for me.

AssignRequest assign = new AssignRequest
{
Assignee = new EntityReference(“systemuser”,Guid),
Target = new EntityReference(“<entity name>”, Guid)
};
// Execute the Request
service.Execute(assign);

Regards,

Route a QueueItem from one Queue to Another Queue using SOAP Code in MS CRM 2011

Route a QueueItem from one Queue to Another Queue using SOAP Code in MS CRM 2011

Some times we may need to route manually queue item to our personal queue on ribbon button click.

Call the below function on custom ribbon button to assign a queue item to your personal Queue or any other queue by passing the Source Queue guid , Destination queue guid and Queueitem guid.

function AssignEmialToQueueUsingEmailGuid(sourceQueueid ,SystemUserPersonalQueueGuid, QueueItemGuid) {
var header = Xrm.Page.context.getAuthenticationHeader();

var xml = “” +
“<?xml version=\”1.0\” encoding=\”utf-8\”?>” +
“<soap:Envelope xmlns:soap=\”http://schemas.xmlsoap.org/soap/envelope/\” xmlns:xsi=\”http://www.w3.org/2001/XMLSchema-instance\” xmlns:xsd=\”http://www.w3.org/2001/XMLSchema\”>” +
header +
” <soap:Body>” +
” <Execute xmlns=\”http://schemas.microsoft.com/crm/2007/WebServices\”>” +
” <Request xsi:type=\”RouteRequest\”>” +
” <Target xsi:type=\”TargetQueuedEmail\”>” +
” <EntityId>” + QueueItemGuid + “</EntityId>” +
” </Target>” +
” <SourceQueueId>” + sourceQueueid + “</SourceQueueId>” +
” <RouteType>Queue</RouteType>” +
” <EndpointId>” + SystemUserPersonalQueueGuid + “</EndpointId>” +
” </Request>” +
” </Execute>” +
” </soap:Body>” +
“</soap:Envelope>” +
“”;

var xmlHttpRequest = new ActiveXObject(“Msxml2.XMLHTTP”);

xmlHttpRequest.Open(“POST”, “/mscrmservices/2007/CrmService.asmx”, false);
xmlHttpRequest.setRequestHeader(“SOAPAction”, “http://schemas.microsoft.com/crm/2007/WebServices/Execute&#8221;);
xmlHttpRequest.setRequestHeader(“Content-Type”, “text/xml; charset=utf-8”);
xmlHttpRequest.setRequestHeader(“Content-Length”, xml.length);
xmlHttpRequest.send(xml);

var resultXml = xmlHttpRequest.responseXML;
alert(“A Queue Item is Successfully Routed to Your Queue”);
}

Regards,

iframe onSave Events in MS CRm 2011

 

//1.Save record embedded in iframe

//Account form with iframe, that displays contact form. Requirement is that when user press “save” button on account form, contact in iframe should be also saved.

var iframeXrmPage = Xrm.Page.getControl(“IFRAME_contact”).getObject().contentWindow.contentIFrame.Xrm.Page;

// 2. Suppose this is our custom entity named “new_mycustomentity” and we would like to show it in inside iframe within a custom aspx page.

//Users can create the new record from within the custom page.

//So we set the Iframe src to the url for creating new my custom entity record i.e.

//<iframe id=”IFRAME_NEWCUSTOMENTITY” frameborder=”0″ runat=”server”
//src = “http://localhost/Contoso/main.aspx?etn=new_mycustomentity&pagetype=entityrecord&#8221; & gt;

//However this is how it appears within in IFrame with no ribbons in it.

//So the next step would be to hide the blank space on the top as well as left navigation bar.Now we can use the following JavaScript that will hide the left navigation pane and blank ribbon.http://bingsoft.wordpress.com/2010/09/09/mscrm-2011-hide-areas-of-a-form/
function HideArea() {
// Hide the Ribbon Toolbar and move the form Content area to the top of the window

window.parent.document.getElementById(“crmTopBar”).style.display = “none”;

window.parent.document.getElementById(“crmContentPanel”).style.top = “0px”;
// Move Form Content area up to top of window, initial style.top is 135px
// set it to the height of the iframe

window.parent.document.getElementById(‘contentIFrame’).style.height = “400px”;

// Hide Left Hand Nav bar / pane
document.getElementById(“crmNavBar”).parentElement.style.display = “none”;
document.getElementById(“tdAreas”).parentElement.parentElement.parentElement.parentElement.colSpan = 2;
// Hide the Form Footer Bar
document.getElementById(“crmFormFooter”).parentElement.style.display = “none”;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////

// 3. How do I Validate with OnChange?

//Luckily this isn’t really that big of a deal. There are several options and its really whatever is best for you.

//Option 1: Blank the field.

//By far the easiest option is to just clear the field after prompting the user. The only downside is the user has to re-enter all of the data again.

function example(obj){
var rgCell = /[0-9]{3}-[0-9]{3}-[0-9]{4}/;
var sVal = obj.getEventSource().getValue();

if (rgCell.test(sVal)) {
// valid

} else {
// Invalid phone number
alert(‘Please enter a valid phone number (ex. 123-123-1234).’);
obj.getEventSource().setValue(”);
}

}

//Option 2: Utilize the OnSave

//There is a little more effort involved here, but a better experience for the user.

function example(obj){
var rgCell = /[0-9]{3}-[0-9]{3}-[0-9]{4}/;
var sVal = Xrm.Page.getAttribute(“mobilephone”).getValue(); //obj.getEventSource().getValue();

if (rgCell.test(sVal)) {
// valid
} else {
// Invalid phone number
alert(‘Please enter a valid phone number (ex. 123-123-1234).’);
Xrm.Page.getAttribute(“mobilephone”).controls.get(0).setFocus(); // only fires onSave

if (obj.getEventArgs() != null)
obj.getEventArgs().preventDefault();
}
}

 

Regards,

 

Activate/Deactivate CRM Entity Record using JavaScript SOAP Code

Activate/Deactivate CRM Entity Record using JavaScript

function ChangeRecordStatus(RECORD_ID, stateCode, statusCode) {
// create the SetState request
var 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=\”b:SetStateRequest\” xmlns:a=\”http://schemas.microsoft.com/xrm/2011/Contracts\” xmlns:b=\”http://schemas.microsoft.com/crm/2011/Contracts\”>”;
request += “<a:Parameters xmlns:c=\”http://schemas.datacontract.org/2004/07/System.Collections.Generic\”>”;
request += “<a:KeyValuePairOfstringanyType>”;
request += “<c:key>EntityMoniker</c:key>”;
request += “<c:value i:type=\”a:EntityReference\”>”;
request += “<a:Id>” + RECORD_ID + “</a:Id>”;
request += “<a:LogicalName>phonecall</a:LogicalName>”;
request += “<a:Name i:nil=\”true\” />”;
request += “</c:value>”;
request += “</a:KeyValuePairOfstringanyType>”;
request += “<a:KeyValuePairOfstringanyType>”;
request += “<c:key>State</c:key>”;
request += “<c:value i:type=\”a:OptionSetValue\”>”;
request += “<a:Value>” + stateCode + “</a:Value>”;
request += “</c:value>”;
request += “</a:KeyValuePairOfstringanyType>”;
request += “<a:KeyValuePairOfstringanyType>”;
request += “<c:key>Status</c:key>”;
request += “<c:value i:type=\”a:OptionSetValue\”>”;
request += “<a:Value>” + statusCode + “</a:Value>”;
request += “</c:value>”;
request += “</a:KeyValuePairOfstringanyType>”;
request += “</a:Parameters>”;
request += “<a:RequestId i:nil=\”true\” />”;
request += “<a:RequestName>SetState</a:RequestName>”;
request += “</request>”;
request += “</Execute>”;
request += “</s:Body>”;
request += “</s:Envelope>”;

//send set state request

$.ajax(
{
type: “POST”, contentType: “text/xml;charset=utf-8”, datatype: “xml”, url: Xrm.Page.context.getServerUrl() + “/XRMServices/2011/Organization.svc/web”, data: request,
beforeSend: function (XMLHttpRequest) {
XMLHttpRequest.setRequestHeader(“Accept”, “application/xml, text/xml, */*”);
XMLHttpRequest.setRequestHeader(“SOAPAction”, “http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute&#8221;);
}, success: function (data, textStatus, XmlHttpRequest) { Xrm.Page.ui.close(); }, error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(errorThrown);
}
});

}

Call the Above function and pass the Record Guid , Statecode and status code of the Record as parameters as shown below.

ChangeRecordStatus(“new_entity”,1,2);

Regards,

 

Open Existing CRM Record Using Java Script

Open Existing CRM Record Using Script

To Open the exisiting CRM Record , pass the Entity Name and Record guid to the below function , it will open the specified record.

//Open an existing Custom record
function OpenExistingEntityRecord(EntityName, RecordGuid) {
Xrm.Utility.openEntityForm(EntityName, RecordGuid);
}

Call the above funciion is as folows.

OpenExistingEntityRecord(“account”,Guid);

You may call this function any event in the CRM

Regards,