Tuesday, 31 March 2015

Forcing the Save on Read-only Fields

If the value of a filed changes then will always force the save. This get over the issue where read only fields don’t save .

var oldSetValue = Mscrm.AttributeWrapper.prototype.setValue;
Mscrm.AttributeWrapper.prototype.setValue = function(value) {
//   if you are changing the value of a field it should be set to always regardless of access
    if(value != this.getValue())
  {
  this.setSubmitMode("always");
  }
  // Call the function as it would have been called normally:
  oldSetValue.call(this, value);
  // Run stuff after, here.
}

I included it on the form in a separate library called optevia_fieldextentions on the form
You call the SetValue method as normal and it will save regardless if its readonly or not

Xrm.Page.getAttribute('optevia_year2fundingadjustment').setValue(0.00);

Friday, 30 January 2015

CRM 2015 Create a custom Action to Validate Data

The following explains how to take advantage of the Action Feature in 2013 , to validate an entity.
Once the action is in place it can be called from anywhere (Portal , Plugin , Client side JavaScript , Batch job, etc ) via the CRM service. The example below will explain how to validate the contact Record using a custom action.



1. In your project solution in CRM add a new process of type action . The name can be ValidateContact and The entity value can be Contact..  In the process arguments , It needs an Entity type (with contact as the rntity value) as input called "Entity" and  EntityCollection as an Output called "ValidationResults". No steps are required as the executing code will be in the Plugin .


2. Create a new entity called new_validationResult with attributes  Type(option set Error,warning), Feild (string), ValidationMessage(ntext). Refresh the early bound library
3.Publish All Customization's
4. Create a new Plugin with the following Code
 public void Execute(IServiceProvider serviceProvider)
        {
               base.Intialise(serviceProvider);
            EntityCollection collection = new EntityCollection();
            collection.EntityName = new_validationresult.EntityLogicalName;
            collection.MinActiveRowVersion = "-1";
           //To get access to the image of the Quote record
              Contact contact = new Contact();
              if (base.Context.InputParameters.Keys.Contains("Entity") &&                                                                    base.Context.InputParameters["Entity"] != null)
            {
                Entity entityRef = base.Context.InputParameters["Entity"] as Entity;
                contact.Intialise(entityRef);
            }
            if (contact.FirstName == null || contact.FirstName == string.Empty)
            {
                new_validationresult result = new new_validationresult();
                result.new_ValidationMessage = "Please Fill in First Name";
                result.new_Field = "FirstName";
                result.new_Type = (int)new_validationresultnew_Type.Error;
                collection.Entities.Add(result.ToEntity());
            }
            base.Context.OutputParameters["ValidationResults"] = collection;
        }

5. In the Plugin registration tool Register the Plugin . Create a new Step with  the now available "new_ValidateContact" Message. It can Be registered against the Post Execution.
Note for Online you need to restart Plugin Registration Tool in order for the message to be picked up.



6. The new_validateContact action can now be called from anywhere A c# early bound example below. You need to include the /generateActions parameter in the CRMsvcUtil command 

Early Bound Example 
  Contact contact = new Contact();
                contact.LastName = "Cunningham";
                contact.Create();
                new_ValidateContactRequest request = new new_ValidateContactRequest();
                request.Entity = contact.ToEntity();
                EntityReference reference = new EntityReference();
                reference.LogicalName = "contact";
                reference.Id = contact.Id; /// this can be set to a "dummy" contact if you want to validate the                         contact before create
                request.Target = reference;
                new_ValidateContactResponse response = CRMConnection.Service.Execute(request) as                             new_ValidateContactResponse;
                string messages = string.Empty;
                foreach (Entity result in response.ValidationResults.Entities)
                {
                    new_validationresult o = new new_validationresult();
                    o.Intialise(result);
                    messages += o.new_ValidationMessage;
                }
                Console.WriteLine("Errors found:" + messages);
           

 late bound example 
   Entity contact = new Entity("contact");
                contact.Attributes.Add("lastname", "Cunningham Late");
                contact.Id= CRMConnection.Service.Create(contact);
                OrganizationRequest request = new OrganizationRequest();
                request.Parameters.Add("Entity",contact);
                request.RequestName = "new_ValidateContact";
                EntityReference reference = new EntityReference();
                reference.LogicalName = "contact";
                reference.Id = contact.Id; /// this can be set to a "dummy" contact if you want to validate the                         contact before create
                request.Parameters.Add("Target", reference);
                OrganizationResponse response = CRMConnection.Service.Execute(request) as                                         OrganizationResponse;
                string messages = string.Empty;
                EntityCollection collection = (EntityCollection)response.Results["ValidationResults"];
                foreach (Entity result in collection.Entities)
                {
                    messages += result["new_validationmessage"].ToString();
                }
                Console.WriteLine("Errors found:" + messages);
           
 A JavaScript example 

function ExecuteValidationActionCreateProject()
{
var target1 = Sdk.EntityReference("contact",Xrm.Page.data.entity.getId().replace('{', '').replace('}', '') ,null);
var entity1 = null;
   var request =  Sdk.new_ValidateContactRequest(entity1,target1);
    Sdk.Async.execute(request, successCallBack, errorCallBack, passThruObj );
}
function successCallBack(data)
{
var entityCollection = data.getValidationResults();
var validationResults = entityCollection.getEntities();
var message = "" ;
for ( i = 0 ; i < validationResults.getCount(); i++)
{
var entity = validationResults.getByIndex(i);
var attributes = entity.getAttributes().getAttributes();
for ( r = 0 ; r < attributes.getCount(); r++)
{
var attribute = attributes.getByIndex(r);
if (attribute.getName() == "new_validationmessage")
{
message= message.concat(attribute.getValue());
}
}
}
if(message != "")
{
alert("Errors:"+message);
}
}
function errorCallBack(data)
{
alert("Error");
}
function passThruObj(data)
{
}

Note: In this example "Contact " was used as the target entity(see step one). If you choose contact you have to pass an existing contact guid as the target when using this custom action. If you don't the action request will fail. Using "none" will allow you to bypass this check. This would get over the problem where for example you wanted to validate a contact  before creating that contact.(contact would have no guid so you have no guid to pass to the target)

Wednesday, 28 January 2015

Consolidation of Dll references Using ILMerge For CRM 2015 Online

In CRM 2015 online you can only register a self contained plugin with no references to any other DLLS. The following outlines how to to consolidate mutable plugins together so it is fit to be registered online.
The Scenario Example used is a DLL called ContactPlugin creates a letter on the update of a Contact.
It has a reference another DLL called VS.RSACPC.CRM.DataModel which is an early bound CRUD operation plugin which allows any component to manipulate data in CRM.


1. Download and instal ILmerge form the following link ILMerge. The Compent will automattically be installed at the following path:  C:\Program Files (x86)\Microsoft\ILMerge\
2. Create the ContactPlugin , add a reference to the VS.RSACPC.CRM.DataModel and implement the code to create a letter on update. The code below passes the service connection to the CRUD using the base.Intialise method BusinessRuleBase class and then creates a letter in CRM:
using Microsoft.Xrm.Sdk;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VS.RSACPC.CRM.DataModel;
namespace ContactPlugin
{
public class ContactUpdate : BusinessRuleBase, IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
base.Intialise(serviceProvider);
Letter letter = new Letter();
letter.Subject = "Test Letter"+ DateTime.Now;
Entity entity = base.Context.PostEntityImages["PostImage"];
letter.RegardingObjectId = new EntityReference("contact", entity.Id);
letter.Create();
}
}
}

3. Set up the project so all DLLs copied to the to a one location (S drive)/ On successful build there will be two Dlls.
ContactPlugin.dll
VS.RSACPC.CRM.DataModel.dll

4. In CMD Use the following command to Merge the two dlls together with the desired name. It includes a reference to the .net framework and a keyfile which is required for all CRM plugins  . Also required for the cloud is s:\Microsoft.Xrm.Client.dll and Microsoft.Xrm.Sdk.Deployment.dll if you require them as they are not available in the cloud
"C:\Program Files (x86)\Microsoft\ILMerge\ILMerge.exe"  /keyfile:s:\Vulcan.snk /target:library  /targetplatform:v4,"C:\Windows\Microsoft.NET\Framework\v4.0.30319" /out:"s:\SelfContainedPlugin.dll" "s:\NewContactPlugin.dll" "s:\VS.RSACPC.CRM.DataModel.dll" "s:\Microsoft.Xrm.Client.dll"  "s:\Microsoft.Xrm.Sdk.Deployment.dll"

Note:Its worth putting this into a bat file so it can run over and over

5. Once you have the DLL you can register it with plugin registration tool


6. Register the Step and the required Images
7. Test the plugin




Monday, 9 June 2014

Using LinqPad to write Linq Queries

The following are steps on how to query data using Linqpad against an entity Framewok
1. Download and Install Linqpad from http://www.linqpad.net/
2. When you run linqpad you get the following screen
3. Click Add connection, choose Your data context as Entity Framework(db context..
4. Browse to your assembly that contains the edmx framework file. The full name of they typed DBcontext should be automatically populated
5. Choose the Path to the configuration file(should be same folder)
6. Write your query


Tuesday, 29 April 2014

List of Reports and Workflows

Workflows- Run against the *_MSCRM database 

SELECT name , createdbyname,createdon,statuscodename
    FROM FilteredWorkflow

Reports run against the ReportServer database 
Select   [Name],
               [Description],
               SubString([Path],1,Len([Path]) - (CharIndex('/',Reverse([Path]))-1)) As [Path],
               Case
                        When [Hidden] = 1
                        Then  'Yes'
                        Else    'No'
               End As [Hidden]
From    [Catalog]
Where  [Type] = 2
Order By SubString([Path],1,Len([Path]) - (CharIndex('/',Reverse([Path]))-1)),
               [Name]

Wednesday, 9 April 2014

Increase the attachment size to 10mb CRM 4

The default attachment file size limit in Microsoft Dynamic CRM 4.0 is 5 MB.  There is good reason for this - as a general rule you should be placing some restrictions on the amount of file data that can enter CRM so that the database can maintain a reasonable size and so that performance is optimized. However, your business may find the need to increase this size a little in order to handle larger file attachments.  Here are the instructions to increase the file size limit to 10 MB.  You can go larger than this, but pay close attention to the table size and performance over time as you want to keep CRM running as well as possible. Note - even though the System Settings option looks like this it would apply to email attachments only, it does apply to "notes" type attachments as well.  Finally, this procedure to change the max attachment size is not an officially published recommendation, so use this at your own risk. How to increase the max attachment size in CRM 4.0:

1.           Open the application web.config (C:\Inetpub\CRM\web.config).

2.           Locate the <httpRuntime> key within the <system.web> element and change the values to the following:
<httpRuntime executionTimeout="9999" maxRequestLength="10240"/>
3.           Locate the <httpRuntime> key within the <system.web> element of the <location path='MSCRMServices"> element, and change it to the following:
<httpRuntime maxRequestLength="10240"/>
4.           Save and close the web.config.

5.           Open the CRM web application (http://crm).

6.           Navigate to Settings | Administration | System Settings.

7.           Click the E-mail tab.

8.           Change the maximum file size (in kilobytes) field to 10240.

9.           Click Ok to save the changes.


10.        Perform IISReset. 

Tuesday, 1 April 2014

CRM 2013 Javascript Special Functions


  • Xrm.Page.context.client.getClient() – Returns client type i.e. outlook, web or mobile.
  •  Xrm.Page.context.client.getClientState() – Returns client state i.e. online or offline.
  • Xrm.Page.data.refresh() – This is one interesting as it refreshes the data on the form without even reloading the page. This also enables developers to pass a callback method.
  • Xrm.Page.data.save() – Save the form
  •  Xrm.Page.data.getIsValid() – Returns true is form is valid for save else false
  •  Xrm.Page.data.setFormDirty() – Sets the form dirty for force save.
  •  Xrm.Page.data.entity.getPrimaryAttributeValue() – Returns the value of primary attribute
  • Xrm.Page.ui.setFormNotification(message,level,uniqueId) – Sets the notification on top of the form.
  • Xrm.Page.ui.clearFormNotification() – Clears the form notification
  • Xrm.Page.ui.refreshRibbon() – Refreshes the ribbon. This method does not work on CRM for tablets.
  •  Xrm.Page.getControl(“field_name”).setNotification(“Notification”) – Sets the notification for a specific field right next to the field label. This can often be used as a custom tool tip.
  • Xrm.Page.getControl(“new_name”).clearNotification() – Clears the notification
  •  Xrm.Page.getAttribute(“new_precision”).setPrecision(2) – Override field precision
  •  Xrm.Page.getControl(“createdon”).setShowTime(true) – Toggle show time at form
  •  Xrm.Page.getControl(“field_name”).addCustomFilter(fetchFilter, entityType) – Allows developer to add custom filter to a lookup view.
  • Xrm.Page.getControl(“field_name”).addPreSearch(handler) – adds pre trigger filter to the lookup.
  • Xrm.Page.getControl(“ownerid”).removePreSearch(handler) – removes the trigger
  •  Xrm.Utility.openWebResourceDialog(webResourceName, webResourceData, width, height) – opens a sepecified webresource as a web dialog window.