Search This Blog

Tuesday, January 3, 2012

Microsoft Dynamics CRM 2011 : Your changes have not been saved !!



Hello everyone, I guess the people working on CRM 2011, might have seen this error (a pop up message) either once. Recently I was just going through my contacts within CRM, I just opened the form and just closed it without changing anything, suddenly out of nowhere this pop up message appeared on the screen. 



Initially I over checked my form again & again if I had changed something on the form, later I checked if any script on the form is changing any field, still nothing. I was getting restless, I did not change a thing on the form, but still whenever I try to close the form, this message appeared on the screen.
Later I wrote a javascript function which will show any dirty fields on the form.

function
FindDirty() {
    var message = "The following fields are dirty: \n";
    Xrm.Page.data.entity.attributes.forEach(function (attribute, index) {
        if (attribute.getIsDirty() == true) {
            message += "\u2219 " + attribute.getName() + "\n";
        }
    });
    alert(message);
}



After I put up this script on load of the contact form, I reloaded the form and found that the parent customer id (a lookup field) was dirty
 

After much R & D I found that, the value of the primary attribute of the lookup (generally the name field) contained two consecutive spaces (due to a concatenation issue pre-import).  Any time you have a record with 2 or more characters of white space in the name field, and that record is selected in a lookup, Microsoft CRM will think that lookup is dirty.  The reason is because CRM tries to be clever around removing extra white space between words.  What ends up happening is when it’s checking to see if a lookup is dirty, it checks to see if both the default value and the current value have the same id, typecode, and name.  But when it checks the name part, the default value has the correct spacing, and the current value has the trimmed spacing, and so they don’t match and CRM thinks the lookup is dirty.

Later when I opened my account form, I saw that the name contained more than single consecutive spaces.

 

After I removed these spaces and saved the account. Then when I opened my contact, and tried closing without change, it closed normally as it should without any message.

Hope this helps someone who has faced this weird issue !!!

Thanks for taking time to read my blog J

Tuesday, September 6, 2011

CRM 2011: Jscript to Read Optionset selected text using Metadata service

Hi,
Recently I was working on an assignment where I had to retrieve data of a lookup record using Jscript, I accomplished to retrieve the lookup record's data using RestFul services. But I found that for the optionset field on the lookup record, i got back only the value (integer) of the selected option, whereas i was expecting to get both, value as well as its text. only later i found that to retrieve its text, I had to do a soap request to the organization metadata service.
Here;s the code which will get the optionset's text. You need to supply the entity logical name, attribute logical name & its selected value, to get back the text of selection option.

function RetrieveAttributeSync(EntityLogicalName, LogicalName, MetadataId, RetrieveAsIfPublished, attributeValue) {

    var ODataPath;
    var serverUrl = Xrm.Page.context.getServerUrl();
    ODataPath = serverUrl + "/XRMServices/2011/Organization.svc/web";

    var request = "<Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
    request += "<request i:type=\"a:RetrieveAttributeRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">";
    request += "<a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
    request += "<a:KeyValuePairOfstringanyType>";
    request += "<b:key>EntityLogicalName</b:key>";
    request += "<b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + EntityLogicalName + "</b:value>";
    request += "</a:KeyValuePairOfstringanyType>";
    if (MetadataId == null)
    { MetadataId = "00000000-0000-0000-0000-000000000000"; }
    request += "<a:KeyValuePairOfstringanyType>";
    request += "<b:key>MetadataId</b:key>";
    request += "<b:value i:type=\"ser:guid\"  xmlns:ser=\"http://schemas.microsoft.com/2003/10/Serialization/\">" + MetadataId + "</b:value>";
    request += "</a:KeyValuePairOfstringanyType>";
    request += "<a:KeyValuePairOfstringanyType>";
    request += "<b:key>RetrieveAsIfPublished</b:key>";
    request += "<b:value i:type=\"c:boolean\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + RetrieveAsIfPublished + "</b:value>";
    request += "</a:KeyValuePairOfstringanyType>";
    request += "<a:KeyValuePairOfstringanyType>";
    request += "<b:key>LogicalName</b:key>";
    request += "<b:value i:type=\"c:string\"   xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + LogicalName + "</b:value>";
    request += "</a:KeyValuePairOfstringanyType>";
    request += "</a:Parameters>";
    request += "<a:RequestId i:nil=\"true\" /><a:RequestName>RetrieveAttribute</a:RequestName></request>";
    request += "</Execute>";
    request = _getSOAPWrapper(request);

    var req = new XMLHttpRequest();
    req.open("POST", ODataPath, false);
    req.setRequestHeader("Accept", "application/xml, text/xml, */*");
    req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
    req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
    req.send(request);

    if (req.responseXML != null) {
        var attributeData = req.responseXML.selectSingleNode("//b:value");
        if (attributeData != null) {
            var attributeType = attributeData.selectSingleNode("c:AttributeType").text;

            switch (attributeType) {
                case "Picklist":
                    return getPickListTextValue(attributeData, attributeValue);
                    break;
                default:
                    break;

            }


function getPickListTextValue(attributeData, attributeValue) {
    var options = attributeData.selectSingleNode("c:OptionSet//c:Options");
    for (var i = 0; i < options.childNodes.length; i++) {
        var value = options.childNodes[i].selectSingleNode("c:Value").text;
        if (value == attributeValue['Value']) {
            var text = options.childNodes[i].selectSingleNode("c:Label").selectSingleNode("a:UserLocalizedLabel").selectSingleNode("a:Label").text;
            return text;
        }
    }
}


Thus by using the above code, you will be able to retrieve all the items (text & value) of the option set  in JScript.

Hope this post will be helpful to someone, as I struggled with this functionality !!

Good Luck :)



Tuesday, July 19, 2011

CRM 2011: Plugin Registration Tool Error - Unable to load assembly !!


Recently I wrote a custom workflow to create a direct URL for a record within CRM & output the formatted URL, so that it can be used in email alerts to the users.
I faced this peculiar problem while I was registering the custom workflow assembly using the new Plugin Registration tool on my client server. I was unable to load my custom workflow assembly onto the plugin registration tool, whenever I choose to load the assembly on the tool, it gave me an error message:
Unhandled Exception: System.IO.FileLoadException: Could not load file or assembly 'file:///C:\Plugin Registration Tool\PluginRegistration.exe' or one of its dependencies. Operation is not supported. (Exception from HRESULT: 0x80131515)
   at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoadFrom(String assemblyFile, Evidence securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm, Boolean forIntrospection, Boolean suppressSecurityChecks, StackCrawlMark& stackMark)
   at System.Reflection.Assembly.LoadFrom(String assemblyFile, Evidence securityEvidence)
   at System.Activator.CreateInstanceFromInternal(String assemblyFile, String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, Evidence securityInfo)
   at System.AppDomain.CreateInstanceFrom(String assemblyFile, String typeName)
   at System.AppDomain.CreateInstanceFromAndUnwrap(String assemblyName, String typeName)
   at System.AppDomain.CreateInstanceFromAndUnwrap(String assemblyName, String typeName)
   at PluginRegistrationTool.AppDomainContext`1..ctor() in C:\pluginregistration\AssemblyReader.cs:line 41
   at PluginRegistrationTool.RegistrationHelper.RetrievePluginsFromAssembly(String pathToAssembly) in C:\pluginregistration\RegistrationHelper.cs:line 40
   at PluginRegistrationTool.PluginRegistrationForm.btnLoadAssembly_Click(Object sender, EventArgs e) in C:\pluginregistration\PluginRegistrationForm.cs:line 166
Inner Exception: System.NotSupportedException: An attempt was made to load an assembly from a network location which would have caused the assembly to be sandboxed in previous versions of the .NET Framework. This release of the .NET Framework does not enable CAS policy by default, so this load may be dangerous. If this load is not intended to sandbox the assembly, please enable the loadFromRemoteSources switch. See http://go.microsoft.com/fwlink/?LinkId=155569 for more information.
The reason I got this error was on the client server was that, the file was blocked on the server !!
Yes, now on some new server OS’s, this feature is enabled by default i.e. any external file that you deploy on the server will be blocked. You have to exclusively unblock the file & then use it to deploy!!
On suggestions from one of my peers, I unblocked the files (workflow assembly & all the files within the plugin registration tool) & then it worked like a charm!!  Everything went smooth later on!!
Unblocking the files: Right click on the file & if you see a unblock button on the properties dialog, then unblock it, else the file is already unblocked!!

I had a day wasted due to this small thing!! hope this helps someone !!

Thanks !!

Friday, July 15, 2011

CRM 2011 Custom workflow


Today I was working on custom workflow activities for CRM 2011. There are lot of changes,  the way you write custom workflow code w.r.t CRM 2011. First thing, you need VS2010 on your system to start working with your project.
Choose a workflow activity library project on your VS 2010.
Add Microsoft.Xrm.sdk & Microsoft.Xrm.sdk.Workflow in your references to your project, when you add this, your project needs to be in .Net framework v 4.0.
Now comes the actual change !
Your workflow activity class needs to derive from a class named: CodeActivity ( a class present in System.Activities, remember to add this assembly in your project references and remove system.workflow.Activities from your directives else this will cause ambiguous error).
We have a new service which can be used for tracing your workflow code or plugin code, called ITracing service.  You can use this service to trace through your code at runtime, you can write messages to it.
You can see how to use this service at the below link:
 
Now coming back to our custom workflow code, there are changes in the way you declare your input & output properties. In CRM 4.0 we used to declare a dependency property for an input or output properties, but in CRM 2011 it’s as shown below:
[Input("Input Value")]
        [Default("Hello")] // this default value will be used if nothing you have specified in your input
        public InArgument<string> ServerName { get; set; }

        [Output("Output value")]
        public OutArgument<string> OutputValue { get; set; }

For more on how to declare your inputs & outputs, refer below link:
After this the usual, strong name your assembly & go on to register your workflow assembly using the new Plugin registration Tool for CRM 2011.
List of changes between CRM 4.0 custom workflow & CRM 2011 Custom workflow code is well explained in the below link:

Hope with this information you can go ahead and build custom workflow activities for CRM 2011.
Good Luck!!

Friday, July 1, 2011

Microsoft Dynamics CRM 2011 – Filtered Lookups

In CRM 4.0, creating a “Filtered Lookup” was… well… kind of a pain. It required quite a bit of JavaScript on the Form in order for the filter to work correctly and if you needed to make additional modifications later on… !
In CRM 2011, the filtered lookups are simple, and you don’t have to know JavaScript to create them.
Example 1: I would like the “Out of the box” Primary Contact lookup on the Account, to ONLY show the contacts that are related to that particular Account. (Very Common request)
Step 1: Access the Account form (From your Solution or Main Customization Area)


Step 2: Open the Form and “Double Click” the Primary Contact field to access the Attribute Properties, then scroll to the bottom of the Field Properties window to adjust the properties of the Lookup!


In addition to being able to filter on Related Records, you can create Filtered views and have the Lookup use it as the default!
Example 2: In CRM, I have multiple “Account Types“. The Account Type field is a Picklist (Option Set) with the following choices: Hospital and Surgery Center. I would like to add an additional Lookup field on the Account form that looks up all Accounts with the “Account Type” of “Surgery Center“.
Step 1: Create the View that filters all Accounts where the Account Type = Surgery Center


Step 2: Create a new Lookup field on the Account Form. (Account to Account)
  1. Access the Account form (Customization Area)
  2. New to CRM 2011 – Create the Lookup directly from the Form!– At the bottom of the Account form, click “New” to create a new Field.

  3. Add your display name and choose the Field “Type” of Lookup.

  4. After the field has been created, add the field to the form using the new “Drag and Drop” functionality.

  5. Double click the field to open its properties

  6. Change the “Default View” to your new View!
As always, make sure to publish your changes to make them available to the users!

Orginal Post:
http://www.powerobjects.com/blog/2011/02/17/microsoft-dynamics-crm-2011-%E2%80%93-filtered-lookups/

Other posts:
http://crmconsultancy.wordpress.com/2011/05/17/filtered-lookups-in-crm-2011/

Thursday, June 9, 2011

Microsoft Dynamics CRM 2011 Virtual Machine is now available !!

The Microsoft Dynamics CRM 2011 Virtual Machine (VM) is now available for Microsoft Dynamics CRM partners to download from the PartnerSource website.
This VM is intended to address these main objectives:
  • Accelerate customer-facing demonstrations by providing baseline infrastructure, enhanced data, and rich scenarios.
  • Enable development and testing of Microsoft Dynamics CRM 2011 demos and solutions in an offline environments where an Internet connection is not readily available.
The Microsoft Dynamics CRM 2011 VM bill of materials consists of two separate VMs:
  • Microsoft Dynamics CRM 2011 VM-01: DC, SQL, CRM
  • Microsoft Dynamics CRM 2011 VM-02: Exchange (optional)
Included in Microsoft Dynamics CRM 2011 VM-01 are the following deployments:
Microsoft Dynamics Core CRM 2011 Environment
A basic CRM environment that contains sample data and preconfigured SharePoint integration.
Microsoft Dynamics CRM Demo Scenarios Environment
More comprehensive demonstrations illustrating core CRM capabilities in expanded scenarios.
  • Marketing, Sales, and Service scenarios
  • Enhanced data, dashboards, customisations, processes (workflows, and dialogs), SharePoint integration, and customer and partner portals
  • End-to-end script that ties each scenario together
xRM Environments
Configured examples of how Microsoft Dynamics CRM can be extended to vertical solutions.
  • Facility Management
  • Employee Management
  • Vendor Management
The VM can be downloaded from here: http://bit.ly/jcqY5i

Wednesday, February 2, 2011

SQL Server Login failed for user 'domain\Administrator'


SQL Login failed for user 'domain\Administrator' or 'sa' or any other user.
This happens for a lot of reason, one of the reasons may be, you have changed the domain controller of your server, where SQL was already installed.
When this happens, you cannot login to the SQL server with any account.
Then the resolution would be running the SQL instance in single-user mode.
How to do this , follow the below steps :
  1. In SQL Server Configuration Manager, click SQL Server Services.
  2. In the right pane, right-click SQL Server (<instance_name>), and then click Properties.
  3. On the Advanced tab, in the Startup Parameters box, type the parameters separated by semicolons (;).
    For example, to start in single-user mode, insert -m; in front of the existing startup options, and then restart the database. (When you start SQL Server in single-user mode, first stop SQL Server Agent. Otherwise, SQL Server Agent might connect first and prevent you from connecting as a second user.)
    Important noteImportant note: "After you are finished using single-user mode, you must remove the -m; from the Startup Parameters box before you can restart the server instance in the normal multi-user mode. "
  4. Click OK.
  5. Restart the Database Engine.
 Now when you have logged in to the SQL management studio, follow the below steps:
1. Expand the security node.
2. Right click on logins, create a new login for the new domain account.
3. Also, you can reset the SA password.

There you go, now your SQL server works fine.

Hope this hepls.