Saturday, December 22, 2012

Strange behaviour when using security roles with the teams in CRM2011

I was trying to setup the security roles on teams instead of assigning security role to the individual users. The end result is that it does not work very well.

Here are the details of what happened.

I had a user with security role named “Manager”. Everything was working as expected. The user was able to create and update the entities defined in the security role. We decided to the create a team named “Manager” and assign the  role to the team. I added the user to the team and remove the security role from the user. Here is what happened after that

I was able to open , create and update the entities as defined in the security roles until we created a new for form for an existing entity.

When I tried to  open the newly created form for the entity, I received the following error message.

image

I had a look in the event viewer. It was showing the following warning message.

Exception message: SecLib::AccessCheckEx failed. Returned hr = -2147187962, ObjectID: 3be48aca-0f39-e211-bce1-005056b8253f, OwnerId: 9cc2541a-9137-e211-bce1-005056b8253f,  OwnerIdType: 8 and CallingUser: 9cc2541a-9137-e211-bce1-005056b8253f. ObjectTypeCode: 2500, objectBusinessUnitId: bf221f51-8537-e211-bce1-005056b8253f, AccessRights: WriteAccess

The object type code 2500 represents the entity “User Entity UI Settings”. I checked the permissions on the entity. The user had the required permissions on the entity. The most annoying part was that I was able to open the existing form without a problem.

So I decided to look a bit deeper into the problem and here are my findings.

1. I created a new user and add the user to the team without assigning any role to the user.

I received an error message “Access Is Denied” every time I tried to open any entity form.

2. I added the same security role to the user as security role assigned to the team.

I tried to open account and contact entity form and I was able to open them without an error.

3. I removed the security role from the user again

I was able to open the entity forms I tried in step 2 but, I was unable to open the form for any other entity or different  form for the same entity.

Conclusion:

You have to have a security role assigned to the user to open any entity form minimum for the first time.

Tuesday, December 11, 2012

CRM fields and "Duplicate Field Name” error

Every time you create an option set or a lookup field in CRM, the system creates 2 fields. For example if you create a lookup field named “new_contact”, the system will create the following 2 fields:

  • “new_contact”
  • “new_contactname” ( the second field will have “name” at the end)

The first field is created as expected. But the system creates the second field automatically. If you ever looked into the filtered views, you must have noticed the extra name columns for lookup and option set fields. If you open a FilteredAccount view, you will notice primarycontactid and primarycontactidname columns. The primarycontactid column contains the guid of the primary contact and primarycontactidname contains the actual name of the contact.

In case of optionset field, the first field contains the integer value of the optionset and second field contains the optionset text value.

The problem is that the CRM UI does not display the second field. You won’t find primaryconactidname in the field’s grid of account entity.

To verify this behaviour, I created a lookup field name “new_contact” and then I tried to create a new field “new_contactname”. I received the following error message.

image

If you receive the “Duplicate Field Name” error, the reason can be a existing lookup or optionset field as explained above.

Friday, November 30, 2012

Error on load of queue form in CRM 2011

I was setting up a new dev environment. It was working perfectly and suddenly, I can’t create a new queue or modify the existing queues.
I was getting the following error message.
image
I had a look in the event viewer. It was showing a warning message as shown in the screen shot.
image
I could not figure out the problem. I tried to repair the CRM. This happened after I setup the email router.
So start looking what I did. I found out that I was using “User Specified” access credential for incoming profile. By default, it is not allowed if you are not using SSL (HTTPS). But there is workaround as explained on TECHNET. The article mentioned that I have to manually add registry key DisableSecureDecryptionKey with value 1.  That’s what I did and that was a problem. I created a key instead of creating a DWORD value. To make this work, it should be a “DWORD” not a “Key”.
image
The DisableSecureDecryptionKey entry should look like following screen.
image
I made the change and it worked like a charm….

Thursday, November 22, 2012

My experience with Microsoft Dynamics CRM 2011 Custom Code Validation Tool

 

Microsoft released the “Microsoft Dynamics CRM 2011 Custom Code Validation Tool”  in May 2012. The purpose of this tool is to detect the potentials issues in  HTML and JavaScript web resources when  CRM2011 starts supporting multiple browsers. 

The cross browser functionality was supposed to be released in Q2 2012 but, that did not happen. The next release of CRM2011 code name Polaris is coming out in December 2012. One of the many features included in Polaris is cross browser compatibility. This blog lists  “What’s included in Polaris?”.

After reading about Polaris, I decided to try “CRM 2011 Custom Code Validation Tool”. Here is the link to download the tool. Here are my findings. The results are mixed but you can make up your own mind.

The following screen shot displays the results from the tool. To check the results, the user has to scroll down the list of web resources one by one.

image

Issues found by the tool

I included some old and unsupported code in the libraries to test the tool. Here are some of the screen shots of potential issues found by the tool.

image

image

So far so good. Here is the screen shot of the JavaScript webresource with most issues.

image

The thing that shocked me the most is that this code is straight from the CRM SDK sample provided by Microsoft.

Issues ignored by the tool

I intentionally added some unsupported code to the JavaScript web resource. But the tool did not identify this code as potential issue.

Here is the screen shot of one such unsupported code. I am using code to attach the custom CSS on form onload.

image

Conclusion

This is very good to identify the potential issue. But I can’t say how reliable it is.

Anyway  don’t use any unsupported code intentionally.

Monday, November 5, 2012

List of Currencies in CRM2011

To create a new currency in CRM, we have an option to select currency type of “System” or “Custom” as shown in the screen shot.

image

If we choose “system” for currency type which is the default selection, we can select  currency code from a look up view as shown in the following screen shot.

image

The selection from the lookup will fill all the required fields (“currency name”, “currency precision”, “currency symbol”) for the currency. We have to manually provide the value for the “exchange rate” field.

Now if you want all the currencies in your system then you have to repeat this process hundred plus times.

I had a look around to find a list of currencies to import into the system instead of creating these record one by one.There is a URL in  currency lookup view with the view id. Here is the URL from my environment.

http://servername/orgname/_controls/lookup/lookupinfo.aspx?AllowFilterOff=1&DefaultType=9105&DefaultViewId=%7b1A364391-BF41-407B-B91F-5C326BAF0A3B%7d&DisableContextMenu=1&DisableQuickFind=0&DisableViewPicker=1&LookupStyle=single&ShowNewButton=1&ShowPropButton=1&browse=1&objecttypes=9105

I looked into the database and found a saved query record with a name  “Currency List” with the viewid shown in the above URL. But the “Query API” field value of the record was showing “TransactionCurrency.RetrieveDotNetCurrencies”. It suggested me that this currency list is not stored in the database table. It may be residing in the database but I did not find it.

I used “Fiddler” and  internet “Developer tools”  and compile the list of currencies in the lookup view. The list is XML spread sheet 2003 format.  Here is the link to download the file. This file can be imported into the system using data import tool. Here is screen shot of some sample data from the file.

image

The “regionname” does not get stored in the currency record. You need to provide the exchange rate for the currencies against your base currency.

When you import this file into CRM map the fields of this file to the currency entity of the system. The mapping screen will look like this.

image

Import process will import 102 records and 62 records will fail. The reason for the failed records is duplicate currency code.

If you look into the currency list, there are a lot of duplicate currency codes. For example “CAD” currency code is repeated 4 times.

image

INR, EUR and some other currencies are repeated multiple time too.

Make the changes to the file as required and import it into CRM using built-in import tool.

I hope this helps. 

Tuesday, October 30, 2012

Workflow assembly to cancel waiting workflows - Part 2

In my last blog, I posted a code for a custom workflow assembly that updates the status of waiting workflow to “Cancelled” when a new instance of the workflow is created.
I did not like the fact that I need to pass the name of workflow as a parameter to the assembly. Then this thought across my mind that I may be able to use this workflow for some other scenarios. For e.g What will happen if I deactivate an account which have one or more workflows in a waiting status?
Personally, I would like to cancel all waiting workflows if I deactivate the account. So I change the code.
Now this workflow assembly can be used in 2 different scenarios.
  1. If I pass the name of the workflow to the assembly. It will update the status of waiting instance of the workflow to “Cancelled” .
  2. If I pass nothing, then it will update the status of all the waiting workflows to “Cancelled” for an entity regardless, of the name of the workflow. In the following screen shot, I am leaving the work flow name empty.
image_thumb[10]
Click here to download the workflow.zip. I have uploaded the whole solution.

Workflow assembly to cancel waiting workflows - Part 1

Sometimes we need recursive workflows with waiting condition in the system. For example a workflow that fires on creation and on change of follow up date of the task. This workflow may wait for few days after “follow up” date and create a new task or send an email. If the follow up date is updated, the system will start a new instance of the workflow. It results  in multiple waiting workflows in the system. It will effect the performance of the system.

The ideal situation will be a workflow that can cancel any waiting workflows on start of a new  instance of the workflow.  The original idea is from Ayaz Ahmed’s blog. I took that idea and came up with this  CRM 2011 workflow assembly. It checks for any waiting instances of the workflow and update their status to “Cancelled”. Here is the code.

using System;
using System.Activities;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Workflow;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Client;

namespace Workflow
{
    public class KillWaitingWorkflows: CodeActivity
    {
        protected override void Execute(CodeActivityContext executionContext)
        {

            //Get the tracing service
            //ITracingService tracingService = executionContext.GetExtension<ITracingService>();

            //Get the context
            IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
            IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
            IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

            //get workflow name from the input property
            string sWorkflow = workflowName.Get<string>(executionContext);

            //Get a service context to use linq queries and 
            var ServiceContext = new OrganizationServiceContext(service);

            try
            {
                QueryExpression query = new QueryExpression("asyncoperation");

                //get columns
                ColumnSet cols = new ColumnSet(new string[] { "asyncoperationid", "statecode" });

                //create conditions
                ConditionExpression c1 =
                    new ConditionExpression("name", ConditionOperator.Equal, sWorkflow); // name of the workflow -input property
                ConditionExpression c2 =
                     new ConditionExpression("regardingobjectid", ConditionOperator.Equal, context.PrimaryEntityId);// entity id
                ConditionExpression c3 = 
                     new ConditionExpression("statecode", ConditionOperator.Equal, 1);//statecode of waiting

                //create the filter
                FilterExpression filter = new FilterExpression();
                filter.FilterOperator = LogicalOperator.And;
                filter.AddCondition(c1);
                filter.AddCondition(c2);
                filter.AddCondition(c3);

                query.ColumnSet = cols;
                query.Criteria.AddFilter(filter);

                //get the collection of results
                EntityCollection colResults = service.RetrieveMultiple(query);

                foreach (Entity async in colResults.Entities)
                {
                    Entity e = async;

                    //change the status of the system job
                    e["statecode"] = new OptionSetValue(3); //cancelled

                    //update the object             
                    service.Update(e);
                }
 
            }//end try
            // Catch any service fault exceptions that Microsoft Dynamics CRM throws.
            catch (Exception ex)
            {
                // You can handle an exception here or pass it back to the calling method.
                throw;
            }
            }
        
    [Input("Work Flow Name")]
    [Default("workflow name")]
    public InArgument<string> workflowName { get; set; }
               
    }
}
  
  • Compile the workflow assembly and register it using plugin registration tool.
  • If everything goes smoothly, you can see this workflow assembly available in workflow. It will look like the following screens.
image

  • I am calling the assembly before the waiting condition. Click on the “View properties” link next to assembly name highlighted in yellow to specify the name of the workflow.
image

  • Activate the workflow and test it.
The problem with this code is that we have to pass “workflow name” as input parameter to the assembly. Then an ideas came to me to use this for my advantage. Wait of my next blog “Workflow assembly to cancel waiting workflows Part 2”.