Twitter Image

On Implicit sharing, team ownership and reparenting

Friday, 20 December 2013 08:42
MSCRM 2011 introduced the notion of team ownership and it's more and more used as the base paradigm for implementing the security model 
However, there's a not well known hidden effect of using team ownership which is called implicit sharing.

When a record is linked to another via a cascading relationship, if the reparenting option is set and if the owner of the parent record is not the owner of the child record, an automatic sharing record will be created.
A typical case is activities linked via the regarding field as the OOB default relationship is parental, so with a full cascade.


Let's take an example where we have an account which is team owned and create a task which is user owned (a quite typical scenario)

If now we look in the PrincipalObjectAccess table, you can see a new record is created which shares the Task record with the Team owning the account.
This happens even if the owner is member of the owning team.


Note that the AccessRightMask field is 0, which is the reason why the sharing window of the task don't show you any sharing, the actual rights are to be found in the field InheritedAccessRightsMask



This behavior may be what you want, but in lot of cases it just add extra records in the POA table and we all know this impact performance in a (very) bad way.
The good news, it's quite easy to remove that behavior, just change the cascading relationship between the involved entities.
In that case, we adapt the parental relationship from account to task by changing the reparenting cascade setting.


If we now remake the same test, no record is created in the POA table.
Here's the results of a test where test1 and test 3 had cascading reparenting ans test 2 add none.

The conclusion is that the OOB default relationship cascade setting, especially relating to activities, should not be taken as granted and should be always reviewed at design time.
 
nb:There's also a Post CRM2011 UR11 organization setting called  DisableImplicitSharingOfCommunicationActivities which could be helpful in that situation.

Manually Reindexing a MSCRM Database

Wednesday, 07 August 2013 09:52

We recently faced an issue where the automatic reindexing job was failing with a timeout 
<MSCRMAsyncService$maintenance. Job Scheduler has executed tasktype=30, organizationid=, starttime=6/08/2013 22:29:22, endtime=6/08/2012 22:40:22 PM, resultcode=1, errormessage=System.Data.SqlClient.SqlException (0x80131904):Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.

This timeout at 600sec seems to be hardcoded in the async maintenance service both in the oledb connection and in the stored procedure (the actual statement being executed is p_reindexall 1,600 with 600 the max seconds). After reading this blog article from the Microsoft Dynamics CRM PFE team, it seems the preferred option is to handle this job in an Sql maintenance plan. As this procedure was not yet documented, I thought it would be useful to do it here.

First, start the SQL Server Management Studio and Connect it to the SQL Server instance hosting the Mscrm database you want to Manually Reindex, then Go the SQL Server Agent/Jobs and Right Click to get New Job

Then in the General Tab, Specify the Name of the Job and the Owner (usually the same service account which runs the MSCRMAsync Maintenance Service)

Then Click on Steps..

and specify a name, the actual MSCRM database you want to reindex and enter the following command : exec p_reindexall 1,<Number of seconds for timeout>.
Nb: here's the full list of parameters you can use in this stored procedure

  • AllIndexTypes, Default=0; 0=Clustered Index only, 1=Clustered and Non Clustered indexes
  • MaxRunTime, NO Default;  Maximum allowed running time (in seconds)
  • FragRebuildPct, Default=30;  Percentage of fragmentation at which indexes are rebuilt
  • MinPages, Default=25; Avoid tables less than MinPages amount of pages  
  • Verbose, Default=0; 1=Print progress messages and detailed results

 

Then click on schedules and specify the running times

Go back to the General Tab, verify that the Job is enabled and click OK.

The Last point is that you need to disable the job in the normal MSCRM Async Service Maintenance. To do this, download the CRM 2011 Maintenance Job Editor, install it in your \Program Files\Microsoft Dynamics CRM\Tools directory and start CRM2011JobEditor (note that there's a post UR12 and pre UR12 version). Then select the Organization for which you enabled the manual reindexing, select the "Reindex All" Job and Change the next Run date to something far in the future (ie: 2099)

MSCRM 2011 Critical Update for UR11

Tuesday, 30 July 2013 07:30

On July 27th, Microsoft released the Critical Update for UR11.
What this update contains is all COD updates part of UR12, UR13, UR14 and some fixes from the CRM2013 branch and is intended to be installed when you don't want to install UR12 for compatibility reasons (UR12 being more a minor release than an update)

There're some differences in upgrade paths between server and clients:

For Server 
If you did not install UR11 beforehand, you just need to install the Critical Update as it contains all changes part of UR11. you need to install UR11 beforehand (which itself needs the UR6 codebase) and then apply the CUR11
You can afterward upgrade to the newer rollups (12+),  note that you only need to apply the last rollup, not all intermediates.

For Client
The client needs to be at UR11 level before the Critical Update is applied; so you need to downgrade existing clients that are past UR11; or upgrade existing clients that are pre UR11.
Afterward, the following update to apply would be UR15+, not UR12, UR13 or UR14.

The KB Article can be found here, the direct downlad link here and a very detailled article by the Microsoft Dynamics CRM PFE team can be found here.

Getting the CRM Server Time

Wednesday, 19 June 2013 14:31

I got the query on how to get the current MSCRM server time in order to synchronize some security tokens between applications.
Unfortunately, I couldn't find any API from MSCRM to get this time (ie: Whoami only returns credentials information and the ...LocalTime.. functions only translate a given time from/to UTC), furthermore the solution had to work for CRM online which forbid deploying custom .svc or .asmx endpoints.
As the proposed pattern could be used for other information, I thought it could be useful to explain it here.

We start by creating a new entity "GetSystemInformation" with a datetime attribute

Then we create a plugin registered on the Post Retrieve event of that entity; the purpose of that plugin is to inject the current server time on the fly 

We create a record and when opening it, we can validate the current server time is fetched.

 

Then, we can call the organization web service with the Retrieve Method on that record to get the server time.

 

Note: The Server time depends on where the code actually runs; on CRM Online; you will get the Sandbox server time; not the Organization Server time.

Open a specific form based on a record attribute

Wednesday, 29 May 2013 12:48

MSCRM 2011 allows multiple forms on the same entity and allows to assign certain forms to the user's security roles; so a certain function can use a given form, another function can user other one and switch between them if the user has access to more than one.
However, if your different forms are record based, meaning a certain status or attribute of your record drives the corresponding form, and not role based, it's a bit more tricky to implement.
You can force a given form via the formid url parameter (http://msdn.microsoft.com/en-us/library/gg328483.aspx), or use the javascript FormSelector (http://msdn.microsoft.com/en-us/library/gg328253.aspx) so this gives a couple of supported paths:

1) Via Javascript
You can add a code like this one to the form Onload event:
var theCurrentFormId = Xrm.Page.ui.formSelector.getCurrentItem().getId( );
var theStatuscode = Xrm.Page.getAttribute("statuscode").getValue();
var theFormid;
if (theStatuscode==1)
 theFormid='GUID1';
 else
 theFormid='GUID2';

if( theFormid!=theCurrentFormId )
{
Xrm.Page.ui.formSelector.items.get(theFormid).navigate();
}

The big drawback is that the form may be loaded twice (most of the time if you have a lot of forms) which is slow and cause a very annoying flicker effect to the end user.

2) Via a specific entity attribute as url
You can add a new ntext attribute of type url to the entity and, when the record is created or updated, compute the url for the record with the valid formid parameter (ie: http://crm/theOrganization/main.aspx?etn=account&pagetype=entityrecord&extraqs=formid%3D7009c1fe-ae99-4a41-a59f-a6f1cf8bfdaf%0D%0A) then store the url in the new attribute. You can easily implement this as a plugin on the form Create and Update events.
Afterwards, if the new field is displayed in a grid; the user can click on that field and get direct access to the valid form for that record.

The issue with that option is that nothing forbids the user to click on other links to this record, which would or give an invalid form, or trigger a flicker if option 1 is implemented. Furthermore, the link url is quite long and there's no way in a grid to have a friendly name for that link.

As neither options fully satisfied the customer, we proposed another option based on url rewriting.
Note this third option is unsupported as this changes some settings on the CRM Web site.

3) Via IIS Url Rewrite
This option uses the Url Rewrite module which is part of IIS.
As this never displays anything to the user until the valid form is displayed; there's not flicker effect and as we only uses one web service call and redirects; the actual final opening is only slowed by less than half a second, vs quite a few seconds in a javascript redirect.

Here's a summary schematic of the url flows

In the below example, the implemented rule redirects the forms for the incident entity.

and here's a sample of the Custom application on 7777 (note that the valid formid is already stored in a custom attribute of the record for that example).

<< Start < Prev 1 2 3 4 5 6 7 8 9 10 Next > End >>
Page 2 of 21