Sticky

This blog has moved to www.dreamingincrm.com. Please update your feed Url. Thank you.

17 July 2014

Broken SVGs while running the Polymer tutorial? Fiddler to the rescue

I am a big fan of Javascript and the Polymer Project. The Webcomponents and ES6 content however generally seem to be targeting the OSX/Sublime setup. So some of the steps in the blogs/tutorials don't work straight away in VS2012/Win8.

The polymer project tutorial specifically says this regarding SVG images rendering:

Note: On Windows, Python’s simple HTTP server may not provide the correct MIME type for SVG images. If the images don’t render, try a different web server.

I am using ASP.Net development server to run the samples and the SVG images are rendered as broken icons.


In order to fix the SVG rending you'll just have to add the following Response Headers when the request is for a SVG.

Content-Type: image/svg+xml
Vary: Accept-Encoding

It is easy to do this Fiddler, instead of trying to install a different HTTP Server. In order to edit the response rules, select Rules -> Customize Rules


Add the following lines inside the OnBeforeResponse method

 if(oSession.uriContains("svg")){
    oSession.oResponse["Content-Type"] = "image/svg+xml";
    oSession.oResponse["Vary"] = "Accept-Encoding";
 }

The SVG images will now be rendered properly. Here is the response with the additional headers injected from Fiddler.

15 July 2014

Highlighting specific records in a view

I recently had a requirement to highlight certain records that are displayed using a System View. It is not possible to use different colours in a supported way to accomplish this. It is possible to rollout your own custom grid using libraries like SparkleXrm and embed this on a form using IFrames. The only problem with this is you still can't highlight a record in System View using SparkleXrm. While it is possible to create a new system view that contains just the records that need to be highlighted, this is not a true highlighting.

A quick solution is to use a simple text attribute, and store a unicode character. These are the miscellaneous symbols in Unicode. You could use the "★" symbol for highlighting the record.

Here is screenshot of what I have done.


All I have done is added a simple text attribute to the entity, and stored "★" character in records that need to be highlighted, and added this to the System View that needs this highlighting. A workflow or business rule could be used to set this attribute based on the highlighting logic. This approach can be used to quickly "highlight" certain records. If you have done this a different way, I would love to hear your approach.

2 July 2014

Setting a Office365 user account password to never expire

Microsoft Dynamics CRM Online user accounts are managed through the Office 365 portal. It might be a requirement is some scenarios, to use some of the user accounts, as service accounts e.g. a customer facing portal talking to CRM using this specific account. The default password policy for Office365 user accounts can be found in the Service Settings area.

The user notification that gets sent after the password expires is not an email notification, as one would expect, but a notification they see after signing in. Here is the relevant bit from Office365 help:

How are users notified that their password will expire? 

Users see a message whenever they sign in, starting at the number of days before password expiration that you specified. The message shows the number of days left before the password expires and gives a link to the Change password page. For more information, see Change your password.

Since the service account is not used for logging in, and is used only for integration with CRMOnline, this message will never been seen. Hence the user account password nearing expiry can go unnoticed, until it is too late. To make a user account password as "Never Expires", please follow this process below:

1.) Install Powershell, if it not already installed
2.) Install Microsoft Online Services SignIn Assistant
      http://www.microsoft.com/en-au/download/details.aspx?id=28177
3.) Install Windows Azure Active Directory Module for Powershell

4.) Open the Windows Azure Active Directory Module for Powershell
5.) Type Connect-MsolService, press Enter and type in your credentials for the CRMOnline instance

6.) Type Get-MsolUser -UserPrincipalName <enter userlogin> | Select PasswordNeverExpires to get the current status of the PasswordNeverExpires setting
7.) Type Set-MsolUser -UserPrincipalName <enter userlogin> -PasswordNeverExpires $true to set the PasswordNeverExpires setting to True.
8.) Confirm if the command has worked correctly.

Here is the screenshot of all the operations:


Now, the password for this user account will not expire, and can be used for integration purposes indefinitely.

4 June 2014

Update Tooltip using XrmToolBox Easy Translator

XrmToolBox is one of my favorite tools, that I use everyday. Among the 20+ tools in XrmToolbox, these are my top three by  usage
1.) Sitemap Editor
2.) Web Resources Manager
3.) View Layout Replicator

Among all these tools, which are all exceptional, Easy Translator is one I never used, as I work only on CRM Deployments with English as the primary language and no requirement from any of the users for alternate languages. There is a interesting usecase for this tool, apart from translation. You can use this to update the tooltip text is CRM 2013. Tooltip text in CRM 2013 is picked up from the description on the field property.


The account name field will show the tooltip text as "Type the company name or business name" when the user hovers over the label.


If we want to setup meaningful tooltips for lot of fields, it is easier to do this via Easy Translator. First export the selected entity to Excel using Easy Translator. I this case I have just chosen Account. We just want to export only the Attributes.


Next open the file in Excel and update Description for the attributes that require a different tooltip text, I this case I am going to change the tooltip text only for the Account Name field to "Type the organisation name or business name".

Save the Excel file and import it.

The tooltip text should now reflect your changes.



2 June 2014

Deployment Manager exception after installing UR17 in CRM 2011

I recently encountered an issue with an existing CRM 2011 environment after installing Rollup 17. The deployment manager would crash with this following error.

Type is not resolved for member 'Microsoft.Crm.CrmSecurityException,Microsoft.Crm.Core, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.

I turned on CRM tracing and this seems to be the underlying error.

at CrmException..ctor(String message, Exception innerException, Int32 errorCode, Boolean isFlowControlException)  ilOffset = 0x0
at CrmException..ctor(String message, Exception innerException, Int32 errorCode)  ilOffset = 0x0
at SecurityUtils.GetActiveDirectoryEntry(String searchItem, String searchFilter, String searchItemLogInfo, Boolean throwIfNotFound, String domainName)  ilOffset = 0x44
at SystemUserService.GetCaseSafeName(String domain, String accountName)  ilOffset = 0x188
at SystemUserService.GetCaseSafeName(String name)  ilOffset = 0x50
at SystemUserService.GetIdsFromName(String userName)  ilOffset = 0xB
at SecurityRoleService.TryVerifyUser(String userName, SecurityRole role)  ilOffset = 0xC
at SystemUserController.TryVerifyUser()  ilOffset = 0xD
at DMSnapInHelper.DisplayMessageBoxIfCurrentUserIsNotSystemUser(Console console)  ilOffset = 0x0
at DMSnapIn.OnInitialize()  ilOffset = 0x27
at SnapInBase.Initialized()  ilOffset = 0x41
at SnapInClient.Microsoft.ManagementConsole.Internal.ISnapInClient.Initialize(ISnapInPlatform snapInPlatform)  ilOffset = 0x14
at UnsafeNativeMethods.DispatchMessageW(MSG& msg)  ilOffset = 0xFFFFFFFF
at ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)  ilOffset = 0x18E
at ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)  ilOffset = 0x1F7
at ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)  ilOffset = 0x13
at SnapInMessagePumpProxy.Microsoft.ManagementConsole.Internal.ISnapInMessagePumpProxy.Run()  ilOffset = 0x34
>Crm Exception: Message: Could not find AD entry for : 09283477 with SearchFilter: samAccountName, ErrorCode: -2147214038, InnerException: System.DirectoryServices.ActiveDirectory.ActiveDirectoryObjectNotFoundException: The specified domain does not exist or cannot be contacted.
at System.DirectoryServices.ActiveDirectory.Domain.GetDomain(DirectoryContext context)
at Microsoft.Crm.SecurityUtils.GetActiveDirectoryEntry(String searchItem, String searchFilter, String searchItemLogInfo, Boolean throwIfNotFound, String domainName)

After much troubleshooting with CRM tracing, Netmon, LDAP Tracing and Wireshark I was able to ascertain that this exception is thrown right after Deployment Manager sends a NbtNs packet before crashing.
 I wrote a small console application to see if this could be a Domain Controller issue. There was no NbtNs packet sent out in my console application and it was successfully able to query the user details.

I posted this in CRM forums and it seems that others also are having the same issue, after moving to Rollup 17. This seems to be a bug in UR17, which cannot handle more than 15 characters in Domain Name (according to the poster). Here is the forum post https://community.dynamics.com/crm/f/117/t/128100.aspx

The was also an additional issue I encountered when I tried to uninstall UR17. The uninstall process would crash with a owner_importlogs key violation on ImportLogBase table. It seems the uninstall process wants to insert two rows with Owner Id = Guid.Empty in the ImportLogBase table.

I had to disable this constraint, allow the uninstall process to finish and later delete these two rows.

So if are having similar issues with Deployment Manager after installing UR17, downgrade to UR16 or wait for UR18.

UPDATE: Issue tracked in Connect -> https://connect.microsoft.com/dynamicssuggestions/feedbackdetail/view/883263/bug-ur17-deployment-manager-domain-resolution



21 May 2014

Quick Tip: Don't use underscore character in CRM webservices URL

Recently I was setting up CRM for Outlook client on a existing environment that we took over. CRM for Outlook would always display the following error after entering the organisation url details in the configuration screen.


The underlying cause seems to be the underscore character in all the crm service urls. The relevant KB316112 article says:

Security patch MS01-055 prevents servers with improper name syntax from setting cookies names. Domains that use cookies must use only alphanumeric characters ("-" or ".") in the domain name and the server name. Internet Explorer blocks cookies from a server if the server name contains other characters, such as an underscore character ("_").

Since CRM for Outlook cannot set the cookies, the client cannot be configured.

7 May 2014

Executing QuickFind using CRM SDK

Global search in CRM for Tablets executes Quickfind view across the entities specified in the System Settings.



Internally the tablet client uses ExecuteQuickFindRequest to perform this quick find search. We can perform the same request using OrganizationRequest. Let's look at the code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Tooling.Connector;
using System.Net;

namespace ExecuteQuickFind
{
    class Program
    {
        static void Main(string[] args)
        {
            var crmConnection = new CrmConnectionHelper(new NetworkCredential("[username]","[password]","CRM"),AuthenticationType.AD, "crm1","80","Contoso");
            if(crmConnection.IsReady)
            {
                var executeQuickFindRequest = new OrganizationRequest("ExecuteQuickFind");
                executeQuickFindRequest.Parameters = new ParameterCollection();
                var entities = new List { "contact", "lead","opportunity","systemuser","competitor","activitypointer", "incident" };
                //specify search term
                executeQuickFindRequest.Parameters.Add(new KeyValuePair("SearchText","maria"));
                //will cause serialisation exception if we don't convert to array
                executeQuickFindRequest.Parameters.Add(new KeyValuePair("EntityNames", entities.ToArray()));
                
                var executeQuickFindResponse = crmConnection.OrganizationServiceProxy.Execute(executeQuickFindRequest);
                var result = executeQuickFindResponse.Results.FirstOrDefault();
                if (executeQuickFindResponse.Results.Any())
                {
                    var quickFindResults = result.Value as QuickFindResultCollection;

                    if (quickFindResults != null)
                    {
                        foreach (var quickFindResult in quickFindResults)
                        {
                            if (quickFindResult.ErrorCode != 0)
                            {
                                Console.WriteLine("Quickfind for {0} errored with code {1}",
                                                  quickFindResult.Data.EntityName,
                                                  quickFindResult.ErrorCode);
                                continue;
                            }
                            Console.WriteLine("***Entity {0} returned {1} record(s)***", quickFindResult.Data.EntityName,
                                              quickFindResult.Data.Entities.Count);
                            foreach (var entityRow in quickFindResult.Data.Entities)
                            {
                                foreach (
                                    var attribute in
                                        entityRow.Attributes.Where(
                                            attribute => !entityRow.FormattedValues.Any(x => x.Key == attribute.Key)))
                                {
                                    Console.WriteLine("{0} = {1}", attribute.Key, ExtractValue(attribute.Value));
                                }
                                foreach (var formattedAttributes in entityRow.FormattedValues)
                                {
                                    Console.WriteLine("Formatted: {0} = {1}", formattedAttributes.Key,
                                                      formattedAttributes.Value);
                                }
                                Console.WriteLine("-----------------------------------------");
                            }
                        }
                    }
                }               
            }
        }

        private static object ExtractValue(object attributeValue)
        {
            var attributeType = attributeValue.GetType().Name;
            object returnValue = attributeValue;
            switch (attributeType)
            {
                case "OptionSetValue":
                    returnValue = ((OptionSetValue) attributeValue).Value;
                    break;
                case "EntityReference":
                    returnValue = ((EntityReference)attributeValue).Name;
                    break;
                case "Money":
                    returnValue = ((Money)attributeValue).Value;
                    break;
            }
            return returnValue;
        }
    }
}

Here is the result after executing this code.



The maximum number of entities you can specify in the EntityNames parameter for this ExecuteQuickFindRequest is 10.