CRM 2011 – how to update read only fields with Javascript

I have had an annoying problem which had me pulling out my hair in frustration when I was testing some javascript.

I had created a field called arranged by and it was a user lookup which was read only because I didn’t want people to set it, I wanted to set it when someone booked in a date and then fill in the field.

What was happening was I was setting the field, which you can read about here but then it saved but on the reload the field was blank, AGHGHGHGG.

I then read this forum question – read only field isn’t updated after javascript save

So it turns out that read only fields are not submitted to the database to be saved.  Which in one way is good because it means less traffic going up the pipe to the database but very annoying for me who is trying to set the read only value.

So if you want to save a read only field you need to set the SubmitMode to be always, which ensures the value is sent to the database.

Xrm.Page.getAttribute("fieldName").setSubmitMode("always");

Advertisement

CRM 2011 – Setting a state and status of an entity using a plugin

I had created a charge entity.  I was creating charge entities of certain values when certain things had happened on regarding cases.  When a case was created it created a charge entity linked to the case, account and product etc for a certain value.

Then when other status were reached a workflow would fire off and create more charge entity’s.  Then at a certain point the user wanted to create an invoice for all the charge entities which had not been assigned to an invoice.

So I created a plugin which when a new invoice is created it goes off and searches for all the charge entities which are not been associated with an invoice.  It then assigns the newly created invoice, adds a date and then I wanted to make the charge entity inactive.  I created a new inactive state called Invoiced.  The reason I wanted to do this was because I didn’t want the charge entity being associated with any other invoices and you can’t change inactive records.

updating the charge entity was no problem, I did this by doing a service.update(entity) but I got errors if I tried to change the state of the entity.  I recalled the state being some what different.

To change the state and status you have to a setStateRequest, it took me a while to work this out.

Another unusualish thing is the state of active is 0 and inactive is 1.  I’m not sure that’s unusual or not.

The status is the status value you want, I had to look up my new status and then assign the value.  The reason you use numbers is because the state and status are optionSet which are set using numbers.  My new status had the value of 951850001 and the default of inactive I think has the value of -1.

Here is the code

public void updateChargeState(Guid chargeId)
{

SetStateRequest setState = new SetStateRequest();

setState.EntityMoniker = new EntityReference();

setState.EntityMoniker.Id = chargeId;

setState.EntityMoniker.Name = "Charge";

setState.EntityMoniker.LogicalName = new_charge.EntityLogicalName;

setState.State = new OptionSetValue(1);
setState.Status = new OptionSetValue(951850001);
SetStateResponse setStateResponse = (SetStateResponse)service.Execute(setState);
}

CRM 2011 – Update Rollup 7 for Microsoft Dynamics CRM 2011 (KB 2600643)

The rollups keep rolling up for CRM 2011 and this means we are closers to R8 and the big enhancements coming our way.

I have updated the wiki page with the all the rollup numbers and version which you can see by clicking the link below

CRM 2011 Build and version numbers

 

To download rollup 7 click the release below

http://www.microsoft.com/download/en/details.aspx?id=29221

Version: 05.00.9690.2165

The KB article is KB2600643

Just to remind you, you will need to have rollup 6 installed to use this.

It seems to have a lot of fixes in this release but I can’t really make out any new major functionality.

Enjoy

CRM 2011 – QueryExpressions where a field is null

I had to write some code today which retrieved some entities which didn’t have a value in a field, so basically I had to write a query to find all the entities which had a null value.

I finally found some sample code on the Microsoft SDK

FilterExpression null_filter = new FilterExpression(LogicalOperator.And);
null_filter.FilterOperator = LogicalOperator.And;
null_filter.AddCondition("leadid", ConditionOperator.Null);

below is my full code.  I am selecting my custom charges entity where the invoice lookup value is null

</pre>
public IEnumerable<meta_charge> getCharges(IOrganizationService service)
{
try
{

ConditionExpression condition1 = new ConditionExpression();

condition1.AttributeName = "new_invoice";
condition1.Operator = ConditionOperator.Null;
FilterExpression filter1 = new FilterExpression();
filter1.Conditions.Add(condition1);

QueryExpression query = new QueryExpression(new_charge.EntityLogicalName);
query.ColumnSet = new ColumnSet(true);

query.Criteria.AddFilter(filter1);

EntityCollection result1 = service.RetrieveMultiple(query);

IEnumerable<new_charge> charges = result1.Entities.Cast<new_charge>();
return charges;

}
catch (Exception)
{
// You can handle an exception here or pass it back to the calling method.
return null;
}
}
<pre>

CRM 2011 – Setting a user lookup with the logged in user with Javascript

Sometimes you need to log the current user in a User Lookup.

Xrm.Page.context.getUserId()

if you wanted to set a user lookup field you would need to do this


var setUservalue = new Array();
 setUservalue[0] = new Object();
 setUservalue[0].id = Xrm.Page.context.getUserId();
 setUservalue[0].entityType = 'systemuser';
//setUservalue[0].name = retrievedUser.FullName;

Xrm.Page.getAttribute("meta_aurarrangedby").setValue(setUservalue)

meta_aurarrangedby is a user lookup field

This will set the correct guid but the user name will be blank until the page is reloaded if you want to add the user name then you need to retrieve the user name using the guid the example code below will do this using an OData query but you will have to add the json2.js file to the entity so it can be called from your javascript.

function Getinfo() {
 var context;
 var serverUrl;
 var UserID;
 var ODataPath;
 context = Xrm.Page.context;
 serverUrl = context.getServerUrl();
 UserID = context.getUserId();
 ODataPath = serverUrl + "/XRMServices/2011/OrganizationData.svc";
 var retrieveUserReq = new XMLHttpRequest();
 retrieveUserReq.open("GET", ODataPath + "/SystemUserSet(guid'" + UserID + "')", true);
 retrieveUserReq.setRequestHeader("Accept", "application/json");
 retrieveUserReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");
 retrieveUserReq.onreadystatechange = function () {
 retrieveUserReqCallBack(this);
 };
 retrieveUserReq.send();

}

function retrieveUserReqCallBack(retrieveUserReq) {
if (retrieveUserReq.readyState == 4 /* complete */) {

if (retrieveUserReq.status == 200) {
 var retrievedUser = this.parent.JSON.parse(retrieveUserReq.responseText).d;
 if (retrievedUser.FullName != null)

var setUservalue = new Array();
 setUservalue[0] = new Object();
 setUservalue[0].id = Xrm.Page.context.getUserId();
 setUservalue[0].entityType = 'systemuser';
 setUservalue[0].name = retrievedUser.FullName;

Xrm.Page.getAttribute("meta_aurarrangedby").setValue(setUservalue)
 }

else {

 }
 }
}

The Xrm.Page.context has quite a few useful functions the functions are listed on this page

The getServerUrl is very useful as is the getUserRoles

Xrm.Page.context provides access to the following functions:

  • getAuthenticationHeader: A deprecated method that returns the encoded SOAP header necessary to use Microsoft Dynamics CRM Web service calls using JScript.
  • getCurrentTheme Returns a string representing the current Microsoft Office Outlook theme chosen by the user.
  • getOrgLcid: Returns the LCID value that represents the Microsoft Dynamics CRM Language Pack that is the base language for the organization.
  • getOrgUniqueName: Returns the unique text value of the organizations name.
  • getQueryStringParameters: Returns an array of key value pairs representing the query string arguments that were passed to the page.
  • getServerUrl: Returns the base server URL. When a user is working offline with Microsoft Dynamics CRM for Microsoft Office Outlook, the URL is to the local Microsoft Dynamics CRM Web services.
  • getUserId: Returns the GUID value of the SystemUser.id value for the current user.
  • getUserLcid: Returns the LCID value that represents the Microsoft Dynamics CRM Language Pack that is the user selected as their preferred language.
  • getUserRoles: Returns an array of strings representing the GUID values of each of the security roles that the user is associated with.
  • isOutlookClient: Returns a Boolean value indicating if the user is using Microsoft Dynamics CRM for Microsoft Office Outlook.
  • isOutlookOnline: Returns a Boolean value indicating whether the user is connected to the Microsoft Dynamics CRM server while using Microsoft Dynamics CRM for Microsoft Office Outlook with Offline Access. When this function returns false, the user is working offline without a connection to the server. They are interacting with an instance of Microsoft Dynamics CRM running on their local computer.
  • prependOrgName: Prepends the organization name to the specified path.

CRM 2011 – defaulting the Customer lookup to contacts on the case form

There are a few lookups in CRM call Customer lookups and can be either Accounts or Contacts.

I have to say I often find these annoying.  Often on the Case form I have to add an account lookup so the user can specify an account and a contact.  The problem is when I use the Customer lookup it defaults to account lookup.

The Customer record is locked onto the form so you can’t get rid of it (you can hide it and assign it a value if you wanted but that’s a bit messy and extra fields etc.)

So on this form I added an account lookup and then used the customer lookup to specify a contact and I wanted a way to default the lookup to be a contact lookup.

I found some code shown below on the blog MSCRM Bing’d which is written by CRM MVP Rhett Clinton.

document.getElementById("customerid").setAttribute("defaulttype", "2");
<pre>Xrm.Page.getControl("customerid").setDefaultView("a2d479c5-53e3-4c69-addd-802327e67a0d");

To get this solution to work I had to go and get the guid of the contact view and in this case I wanted the Active Contacts and replaced the SetDefaultView guid with my guid and then I put the code into the onload event.

Then when I clicked on the customer lookup it defaults to contacts and the view I specified in the guid.

The only downside is if you search in the box without pressing the lookup button it does still search contacts and accounts.

So a big thanks to Rhett for helping resolve a problem which had annoyed me for quite a while.


CRM 2011 – Solutions and publisher prefix

When I modify an organisation I usually make a new Publisher with Metaphorix the company I work for and other details.

I also change the prefix on the publisher to meta, so I can easily tell all the fields I have added.

When you create an organisation CRM automatically creates a publisher called default publisher <name of organisation>

So after I had made my Publisher I would then make a solution and add the entities I would be customizing.

The problem is if you want to use the functionality of using the customization buttons on a form (which you only see if you have the role of System Administrator or System Customizer). If you edit a form and add a field then it uses the default publisher prefix which is new.

I also thought initially changes to entities in my solution would only be recorded if I made them inside my solution but the reality is if you have the account entity in your solution and you edit it using the system customization rather than going through the solution interface then these changes will still be shown in your solution, the only difference is any fields you would have added will have the prefix of new.

well the easy and obvious way around this is to just change the prefix on the default Publisher in your CRM system and then hey presto all your fields will now have the same prefix.

CRM 2011 – CRM was down after power cut

We had a power cut today in the office.  Initially you think woohooo, I can relax and have a cup of tea for the 30 minutes and then you realise you can’t make a cup of tea because the power is down.

Then you realise the only work you can do is documentation, AHGHGHGHGG

The power cut happened whilst I was at lunch having a walk, I initially thought it was either some kind of alien invasion or a particular efficient burglar because at least 6 houses had their house alarms going off.

After an hour the power came back up but the company CRM was still down and when I tried to open CRM I was getting  a rather nasty error, mentioning Priv User group and a lot of active directory messages.

This was unusual,

I check the CRM server, fine

I checked the Async services, fine

SQL Database, MSCRM_CONFIG, org database, fine

So all the obvious stuff seemed to be ok.

I then looked at the error message and noticed the localSystemAdGuid was a blank guid of all zero’s.

I was speaking out loud, mentioning active directory errors and then one of the developers said try rebooting the CRM server because if it had come up before the Domain controller then the it would affect CRM because it needs active directory.

so I rebooted the CRM server and this resolved the problem.

So there we go, tuck that piece of information and I hope it doesn’t happen to you.

CRM 2011 – Pending Email warning

I was getting the Pending email warning message today when I logged into CRM.  This message will appear if you have some emails which haven’t been sent.

After a week of this message I finally decided to do something about it, I couldn’t figure out what emails I might have in CRM which wouldn’t have been sent.

I then remembered I was trying to set up an automatically email workflow, which sent a reply to customers when they emailed the support email address.  I had been using my email address for testing.

So where do you find these pending email messages?

I first did an advanced find for emails message with a status of open.

I then put on my thinking cap and realised these would be system jobs which have been suspended.

So I went to Settings –> System Jobs and changed the view to Suspended System Jobs.

I had four email messages postponed until 30/12/9999

I have no idea why Microsoft has set this mad postpone date for a date so far in the future, why doesn’t it just cancel them or perhaps try them again a day later.

You can select the message and choose resume or if you aren’t bothered about them you can cancel them.  If you are really annoyed you can even delete them but it’s better to cancel them because then you will still have some evidence of them if you delete them all traces of them are lost forever.

You will then be rid of the annoying message, unless you haven’t got email settings setup correctly and then they will soon get back into suspended state.  If that is the case you need to check the email settings for the user who is trying to send the email or the user the workflow is trying to send the email on behalf off, you can either choose to set them up using an email router or outlook.

CRM 2011 – adding validation to the Resolve Case button

I had a scenario where the customer wanted the helpdesk user to fill in some call analysis fields when a case was resolved.

Initially I made a new status called Completed, I created some new fields for the users to fill in regarding customer satisfaction, if they resolved the case within the time period and some other fields.

When the user changed the status to completed, some JavaScript made those fields required so the user had to fill them.

This worked fine unless the user press the Resolve Case button and this just closed the case without them having to fill in call analysis fields.

I initially looked into changing the case resolution form.  The case resolution form pops up when you press the case resolved button and you have to fill in a few fields, the perfect place for some call analysis.  Perfect except you can’t modify it, Microsoft don’t let you modify this Activity.  I have no idea why but there you go.

I briefly thought about adding some rules to enable the case resolution button only when you clicked on the status completed.

I then saw some Javascript which did the job.  It’s quite clever and I learnt some thing new in CRM.

The solution to my problem was some javascript which is triggered on the OnSave event on the Case form, it checks what type of save has happened and if it was triggered from pressing the Case Resolution it validated the form.

The answer although was shown on many forums originated from the blog post below.  The blog post has a link to the javascript file you can download so I would definitely go there to get it.  Also this is a great site for CRM developers with lots of other great blog posts like how to trigger a workflow using javascript

The original Javascript and example is taken from this blog post but has now been created as a wiki page blog post below, you need to look at the original article because it explains the whole solution ands walks you through it which I am not going to do.

http://social.technet.microsoft.com/wiki/contents/articles/4122.dynamics-crm-2011-dynamics-crm-2011-perform-jscript-validations-on-entity-form-before-execution-of-special-events.aspx

// Use the following function on Form Save Event,
// CRM will pass the execution context in function parameter prmContext

function FrmOnSave(prmContext) {
 // Local variable to store value indicating how the save event was initiated by the user.
 var wod_SaveMode, wod_SaveEventVal;

// Change the Save Event Value as per required Save Event
 wod_SaveEventVal = <Value>;

if (prmContext != null && prmContext.getEventArgs() != null) {

wod_SaveMode = prmContext.getEventArgs().getSaveMode();

// 1 will pass on Recalculate button click
 if (wod_SaveMode == wod_SaveEventVal) {
 // Write your validation code here

alert("Write your validation code here");

// Use the code line below only if validation is failed then abort function save event
 prmContext.getEventArgs().preventDefault();

}
 }
}

You can download the code from the blog link to a skydrive, click here for that

The code above is a neat solution to the problem.  In the OnSave event it gets the code to pass variables, this then passes the context.  Using the context you can then get the save mode prmContext.getEventArgs().getSaveMode()  this gives you a number.  If the number is 5 then you know the save has been triggered by pressing the resolve case button.

This was interesting because I didn’t know that save events had different numbers depending on where they were triggered.  The blog post has a list of all the save events

Entity
Event Mode
Value
Activities
Save as Completed
58
Activities
Close Activity Note 2
5
Activities
To Opportunity Note 2
5
Activities
To Case Note 2
5
Activities
To Lead Note 2
5
All
Save Note 2
1
All
Save and Close
2
All
Deactivate
5
All
Reactivate
6
Article
Submit
10
Article
Approve
12
Article
Reject
11
Article
Unpublish
13
Campaign Activity
Close Campaign Activity
5
Campaign Activity
Distribute Campaign Activity
4
Campaign Response
Convert Campaign Response (Create new lead or Create new record for a customer)
54
Campaign Response
Convert Campaign Response (Convert Existing Lead -> Qualify)
16
Campaign Response
Convert Campaign Response (Convert Existing Lead-> Disqualify)
15
Campaign Response
Close Response
5
Case
Resolve Case
5
Case
Cancel Case
40
Case
Reactivate Case
6
Contract
Invoice Contract
38
Contract
Copy Contract
39
Contract
Recalculate Note 2
1
Contract
Hold Contract
31
Contract
Renew Contract
34
Contract
Cancel Contract
33
E-mail
Send
7
Goal
Recalculate
66
Goal
Close Goal
5
Invoice
Invoice Paid
57
Invoice
Cancel Invoice
27
Invoice
Recalculate
1
Invoice
Get Products
44
Invoice
Lock Pricing
52
Lead
Qualify
16
Lead
Disqualify
15
Opportunity
Close as Won Note 2
5
Opportunity
Close as Lost Note 2
5
Opportunity
Recalculate Opportunity Note 2
1
Order
Create Invoice
19
Order
Fullfill Order
56
Order
Cancel Order
26
Order
Recalculate Note 2
1
Order
Get Product
43
Order
Lock Pricing
50
Product
Convert to Kit
35
Product
Convert to Product
36
Queue
Approve E-mail Note 1
4
Queue
Reject E-mail Note 1
4
Quote
Recalculate Note 2
1
Quote
Get Products
28
Quote
Activate Quote
29
Quote
Create Order
17
Quote
Revise
24
Quote
Close Quote
25
User
Approve E-mail Note 1 & Note 2
4
User
Reject E-mail Note 1 & Note 2
4
User
Change Business Unit Note 1
4
User or Team Owned Entities
Assign
47

 

Although I was capturing the save event, when I changed some fields to be required it didn’t seem to stop the page from saving, so I had to add some Javascript which stopped the Case form from saving and popped up a javascript message warning the user to fill in some Call analysis fields.  I added some validation which checks to see if certain fields are null, if they are then I stopped the form from saving.

prmContext.getEventArgs().preventDefault();
alert(“You must enter Call Analysis information”);

 

There are probably other ways to do this but it shows you the power of CRM 2011 that you have quite a few options