Tuesday, August 26, 2014

Setting up CRM Online with Exchange Online using Server Side Synchronization

I was trying to setup Server Side Synchronization using CRM Online and Exchange online as part of the Office 365 offerings. For some reason, I found the process to be somewhat confusing.

After several trial and error sessions, I have documented the below process that has always worked for me since. Hope this helps someone out there as well :)

1. First, create a CRM Online Trial Account
2. Then from the portal (https://portal.microsoftonline.com/), under Admin - Select Office 365

3. Choose Purchase Services and choose Trial for Office 365 Enterprise E3 trial or above.
4. Choose all the services and wait for approx. 10 mins for the services to get activated.

5. After purchasing the E3 Trial, we need to ensure that all the users in the organizations are also assigned to the purchased subscription. To do that, click on “Users and Groups” and select the users in your organization and then click on Edit


6. Then navigate to “Licenses” and then select all the subscriptions licenses and then click on Submit.

7. Wait until all your subscriptions in the command bar and under the Admin section get enabled as shown below:

8. Login into CRM. Click on Settings and go to System Settings. In the email tab, set everything to Server Side Synchronization and click on OK

9. Then click on Settings and choose Email Server Profiles

10. Open the currently Active Email Server Profile

11. Set the Auto-Discover to “No” and specify the Incoming and the Outgoing Server location as shown below (This should ideally work with “Auto Discover” set to “Yes” but for some reason it was not working for me unless I give the credentials as specified below).

12. Click on Mailboxes->Select all the mailboxes and then click on “Apply Default Email Settings”

13. Then click on “Test and Enable Mailboxes”. Ensure that the status for Incoming and Outgoing is successful.

14. (Optional): Finally, go to the user’s Personal Options page. Set the Track emails options to track “All email messages”. That’s it.

Wednesday, June 4, 2014

Exception message: Table alias is not unique amongst all top-level table and join aliases CRM 2013

Recently I was trying to create a bunch of different views and I was using an existing view to "Save As" another view.
However, after publishing my new views, I would keep getting the error "Exception message: Table alias a_d8c7aa10e688e31180c200155d53e454 is not unique amongst all top-level table and join aliases" in the Event Viewer

When I looked into the FetchXml in SavedQueryBase table for the view that I just created, I would see that there were indeed two "linked entity" tags in the FetchXml.
Searching the internet, I found mostly 2 dirty work around's and 1 perfect work around (perfect for me) to resolve this issue.

Dirty Work Around

1. Export the Solution with the entity inside it. Open the customization.xml and remove the duplicate reference to the "linked entity" tag. Import the solution.
2. Get the FetchXml for the view from the SavedQueryBase table and remove the duplicate reference to the "linked entity" tag. Update the FetchXml back into the SavedQueryBase table for that view and then Publish the Entity from CRM.

Perfect Work Around (Perfect for my situation)

I just happened to accidentally read the comments left by one of the users in one of the blogs while researching a fix for this issue. I can't remember the blog or the commenter but all thanks to him for the issue resolution.

Root Cause
This is a bug in the product and apparently there was a fix released for this in CRM 2011 UR 12 but no fix has been released so far for CRM 2013 until UR 2.
The Root Cause is that if you already have columns from a "linked entity" in your "Entity Advanced Find View", any further views that you create that reference columns from a linked entity will throw an error.

Resolution
1. Go to the Entity Customization
2. Click on Views
3. Open the Entity Advanced Find View (Ex. Contact Advanced Find View)
4. Remove any references to columns that may have been added from another entity. i.e these fields do no exist inside the current entity.
5. Save and Publish the entity.

Thats it! Now, I was able to create all my views as usual without getting any errors. Hope this helps someone.

Thursday, February 20, 2014

Retrieve CRM Form Metadata Xml

The below method helps us to retrieve the FormXml of a CRM Entity
        private string GetFormXml(string websiteName, string entityName, IOrganizationService service)
        {
            string formXml = "";

            try
            {
                RetrieveEntityRequest mdRequest = new RetrieveEntityRequest()
                {
                    EntityFilters = EntityFilters.Attributes,
                    LogicalName = entityName,
                    RetrieveAsIfPublished = true
                };
                // Execute the request
                RetrieveEntityResponse entityResponse = (RetrieveEntityResponse)service.Execute(mdRequest);
                //EntityMetadata entityData = entityResponse.EntityMetadata;y

                var entityTypeCode = entityResponse.EntityMetadata.ObjectTypeCode.Value;

                QueryExpression query = new QueryExpression("systemform");
                query.ColumnSet = new ColumnSet("formxml");
                query.Criteria.AddCondition(new ConditionExpression("name", ConditionOperator.Equal, websiteName));
                query.Criteria.AddCondition(new ConditionExpression("objecttypecode", ConditionOperator.Equal, entityTypeCode));

                RetrieveMultipleRequest retrieveRequest = new RetrieveMultipleRequest();
                retrieveRequest.Query = query;

                var results = (RetrieveMultipleResponse)service.Execute(retrieveRequest);
                formXml = results.EntityCollection.Entities[0].Attributes["formxml"].ToString();

                return formXml;

            }            
            catch (FaultException ex)
            {
                throw new FaultException("Error occured while instantiating the CRM Service " + ex.ToString());
            }
            
        }

Wednesday, February 19, 2014

Retrieving the optionset label

The below code helps us to retrieve the label of the option set. Please note that the "optionValue" is the integer value of the label that you want to retrieve.
        public static string GetOptionSetLabel(string entityName, string attributeName, int optionValue, IOrganizationService service)
        {
            try
            {
                RetrieveAttributeRequest retrieveAttributeRequest =
                            new RetrieveAttributeRequest
                            {
                                EntityLogicalName = entityName,
                                LogicalName = attributeName,
                                RetrieveAsIfPublished = true
                            };

                // Execute the request.
                RetrieveAttributeResponse retrieveAttributeResponse =
                    (RetrieveAttributeResponse)service.Execute(retrieveAttributeRequest);

                // Access the retrieved attribute.
                PicklistAttributeMetadata retrievedPicklistAttributeMetadata = (PicklistAttributeMetadata)retrieveAttributeResponse.AttributeMetadata;

                // Get the current options list for the retrieved attribute.
                OptionMetadata[] optionList = retrievedPicklistAttributeMetadata.OptionSet.Options.ToArray();

                foreach (OptionMetadata option in optionList)
                {
                    if (option.Value == optionValue)
                    {
                        return option.Label.UserLocalizedLabel.Label;
                    }
                }
            }
            catch(Exception ex)
            {
                WriteErrorLog(entityName, "Error while retrieving the optionset labels " + ex.ToString(), service);
            }

            return String.Empty;
        }

Retrieve the image saved in an Entity Record

The below method can be used to retrieve the image that is stored in an entity record.

        public static byte[] GetEntityImage(string entityName, Guid entityId, IOrganizationService service)
        {
            try
            {
                QueryExpression query = new QueryExpression(entityName);
                query.ColumnSet = new ColumnSet("entityimage");
                query.Criteria = new FilterExpression(LogicalOperator.And);
                query.Criteria.AddCondition(entityName + "id", ConditionOperator.Equal, entityId);
                EntityCollection collection = service.RetrieveMultiple(query);
                if (collection.Entities[0].Contains("entityimage"))
                {
                    return collection.Entities[0]["entityimage"] as byte[];
                }

            }
            catch (Exception ex)
            {
                //WriteErrorLog(entityName, ex.ToString(), service);
            }
            return null;
        }