Deleting a relationship with Field Level Security applied on the field will not delete Field Level Security details from database


This seems to be a bug in Microsoft Dynamics CRM 2011. To reproduce the bug, follow these steps:

1.       Create a relationship for an entity. I have created a new N to 1 relationship from Account to Contact and Enable “Field Level Security”.

2.       Create a “Field Security Profile” and give Read, Write, Update access for this field. In my case I have two field security profiles. One profile has no access to this field and other profile has full access.

3.       Publish your customizations.

4.       Now, delete the relationship that you have created.

5.       Publish your customizations again.

6.       Navigate to the Field Security Profile and open one your Field Security Profile and click on “Field Permissions”. You can see the below error message.


Note: I have update rollup 8 installed on my server.

Reason & Resolution:

Whenever you enable Field Level Security on any field in Microsoft Dynamics CRM, multiple rows will be created in the “FieldSecurityBase” table in your organization database. These records are not deleted once you delete your relationship. This problem happens only for the field created by CRM while creating a relationship.

To resolve this, Open your organization database from Microsoft SQL Server Management Studio and delete the records from “FieldSecurityBase” table. You can use the below query to delete the rows.

DELETE FROM FieldPermissionBase where AttributeLogicalName = 'schema name of the field'

Be careful while deleting the data form the database directly. It is always recommended to take a backup before performing any actions on the database directly.

Invalid Action - The Selected Action was not valid


I came across the below error when I am trying to browse my Microsoft Dynamics CRM 2011 url.


Exception message from Event Viewer:

Exception information:
    Exception type: CrmException
    Exception message: The key specified to compute a hash value is expired, only active keys are valid.  Expired Key : CrmKey(<RemovedTheKey>, ScaleGroupId:00000000-0000-0000-0000-000000000000, KeyType:CrmWRPCTokenKey, Expired:True, ValidOn:06/18/2012 03:35:21, ExpiresOn:07/21/2012 03:35:21, CreatedOn:06/18/2012 03:35:21, CreatedBy:NT AUTHORITY\NETWORK SERVICE.


I found that my CRM Asynch Service is not running. This exceptions is gone by starting the CRM Async Service.

Plugin to remove data for a field from Views in Dynamics CRM 2011

Remove specific column data in a view for a security role using Plugin in Microsoft Dynamics CRM 2011
One of the requirements that we come across very frequently in every Dynamics CRM implementation is to restrict few columns for a specific security role. CRM does offer a great flexibility of “Field Level Security” (FLS) to achieve this. But there are some limitations for FLS.
As of now FLS doesn’t support out of the box fields. Which means you cannot apply field level security for the field that will come out of the box. For example, Primary Contact field on Account entity.
Scenario:
Very recently I came across a requirement where my business wants Salesperson to see Account Information but not Contact information.
Approach:
My first step for this is to remove the access to “Contact” for the “Salesperson” security role. This will solve my purpose to restrict the “Salesperson” from seeing the Contacts but he can still see the name id the contact from “Primary Contact” Field of Account form.  
I cannot enable Field Level Security on this field as this is a system filed.
If I delete the existing relationship between Account and Contact and recreate it then it will become a custom field and I can apply Field Level Security. Unfortunately CRM does not allow you to delete system relationships and fields, especially in this case.
So I have created role based forms and do not add the “Primary Contact” field for the form that is accessible for Salesperson. Still there one more component we are missing, Views. We have to remove the information from the views.
So I left with the final option to manipulate the data using Plugin. I can write a plugin on “RetrieveMultiple” message of the account entity and remove the “Primary Contact” field from the Query.
Solutions:
Solution is simple. Write a plugin on “Account” entity for “RetrieveMultiple” in “PreOperation” stage.
*Note: I am using Developer Toolkit for developing my plugin. So your code can differ a little if you writing the plugin as a class library. Give a try with Developer Toolkit for Microsoft Dynamics CRM which can drastically improve your productivity and I am sure you will love it.
var pluginContext = localContext.PluginExecutionContext;

           
IOrganizationService service = localContext.OrganizationService;


QueryExpression query = new QueryExpression()
{
       EntityName = "role",

//Link definition and filter condition
LinkEntities = 
{                            
new LinkEntity
       {
                     LinkFromEntityName = "role",
                     LinkFromAttributeName = "roleid",
              LinkToEntityName = "systemuserroles",
                     LinkToAttributeName = "roleid",
                     LinkCriteria = new FilterExpression
              {
                            FilterOperator = LogicalOperator.And,
              Conditions = 
{
                     new ConditionExpression
                                  {
                                         AttributeName = "systemuserid",
                           Operator = ConditionOperator.Equal,
                                        Values = { pluginContext.UserId }
                                  }     
}
}
}
}
};

query.ColumnSet = new ColumnSet("name");

EntityCollection userroles = service.RetrieveMultiple(query);
bool isSalesPerson = false;

//Check is he is part of salesperson role. Your login can differ based on requirement.
foreach (Entity entity in userroles.Entities)
{
if (entity.Attributes["name"] != null && entity.Attributes["name"].ToString().ToLower() == "salesperson")
       {
              isSalesPerson = true;
              break;
}
}
 
//Manipulate input parameters.         
ParameterCollection collectoin = pluginContext.InputParameters;

if (collectoin["Query"] is QueryExpression && isSalesPerson == true)
{
QueryExpression expression = (QueryExpression)collectoin["Query"];

       ColumnSet columns = expression.ColumnSet;

       //Each column in the view is coming twice. Not sure why.
while (columns.Columns.Contains("primarycontactid"))
       columns.Columns.Remove("primarycontactid");
              
}

Deploy your plugin. Now salesperson will still see the “Primary contact” filed in the view but it will be blank.
If you have any suggestions please leave a comment.