Form Message for Dynamics CRM

Download Form Message for Dynamics CRM on Codeplex

The form message solution can be found on CodePlex, it allows you to place custom messages onto a CRM form where you can define text and the image icon such as Success, Error, Information, Warning and Alert.

You can also choose to display the 2 buttons that can be customised with your desired label for example OK, Cancel, or Submit, Cancel, etc… and attach JavaScript functions as call back events for each one.

Form Message with Buttons displayed
Form Message with buttons.png

Available Message Icons

alert_16.png error_16.png info_16.png success_16.png warning_16.png

Adding Form Message web resource to CRM Form
WebResource on Form.png

You can add initial/static text and an icon by supplying Custom Parameters such as text and type like this.

WebResource on Form Custom Parameters.png

Usage

Form Message Functions include

showFormMessage(message, type, iFrame, iframeLoadedCallback)
setFormMessageVisible(iFrame, isVislble)
showMessageConfirmation(iFrame, successCallBack, cancelCallBack, successLabelOverride, cancelLabelOverride)

Form Message Types include

success
alert
warning
error
info

Display Form Message

DXTools.FormMessage.showFormMessage("This is a test Message.", "success", "WebResource_HeaderMessage", function () { });

Display Form Message with Buttons

DXTools.FormMessage.showFormMessage("This is a test Message.", "info", "WebResource_HeaderMessage", function () {
        DXTools.FormMessage.showMessageConfirmation("WebResource_HeaderMessage", function () { alert("yes") }, function () { alert("no"); }, null, null);
    });
});

Download Form Message for Dynamics CRM on Codeplex

Prepare your JavaScript for Dynamics CRM 2013

The CRM Team have posted a very good article on what to look out for with regards ensuring you are ready for Dynamics CRM 2013 form script changes. Take a look at this article to help prepare for your upgrade http://blogs.msdn.com/b/crm/archive/2013/08/23/check-your-javascript-code-to-prepare-for-your-upgrade.aspx .

You can also find the Microsoft Dynamics CRM 2013 Custom Code Validation Tool here http://www.microsoft.com/en-us/download/details.aspx?id=30151. This will help you prepare for your upgrade to Microsoft Dynamics CRM 2013. It is possible that some code will stop working or cause an error when you upgrade from CRM 2011 to 2013 so it is worth putting the time in to investigate. The Microsoft Dynamics CRM Custom Code Validation Tool helps identify potential problems so that any potential issues can be resolved before upgrading. the tool will help identify potential issues with custom JavaScript in JavaScript libraries and HTML web resources. It will detect issues in web resources that will no longer work after you upgrade from CRM 2011 to 2013. Areas that the tool will cover include CRM v4 client SDK calls, CRM 2007 end points and Common DOM manipulations.

if you haven’t already you should go take a look at What’s Changing in the Next Major Release of Dynamics CRM http://msdn.microsoft.com/en-us/library/dn281891.aspx for a broad overview of the new release.

You can download the Microsoft Dynamics CRM 2013 Software Development Kit (SDK) here http://www.microsoft.com/en-us/download/details.aspx?id=40321 to get up to speed regards the fantastic capabilities coming with CRM 2013. The Microsoft Dynamics CRM 2013 Software Development Kit (SDK) is for developers, system customisers, and report writers.

A great site to keep up to date with all the goodness is the Dynamics CRM Develop Center on msdn. http://msdn.microsoft.com/en-us/dynamics/crm/jj937218 where you can get all of the information you need to develop, design, and distribute solutions for Microsoft Dynamics CRM.

CRM Online to SharePoint Online Integration using REST and ADFS

Accessing SharePoint Online 2013 REST services with SSO via ADFS (Active Directory Federation Services) from CRM Online provides loads of potential opportunities, especially now that SharePoint offers a huge REST API. You can call REST from a CRM Online Plugin or Custom Workflow activity with no dependencies on SharePoint Client dll’s or Azure getting in the way, It is fairly awesome I must say.

I use the HttpWebRequest class to perform SOAP requests to perform the authentication part of this integration, which is totally supported within Sandboxed Plugins and Custom Workflow Activities. You can read more about the restrictions of the CRM Sandboxed environment here http://msdn.microsoft.com/en-us/library/gg334752.aspx. Once you get authenticated and obtain the cookies you are free to fire REST calls off by simply providing the cookies along with the request.

The best diagram I found to describe the authentication process visually was from Wictor Wilen’s blog http://www.wictorwilen.se/

Auth Process

I wanted to explore the issue of authentication between CRM Online and SharePoint Online from a server to server perspective and as you can imagine authentication is a big hurdle for this direct type of communication as every example I have seen so far includes Azure. Well at least until I started to look at what others were doing with Windows 8 Apps and Active Authentication. Omar Venado http://blogs.msdn.com/b/omarv/ and fellow MVP Wictor Wilen http://www.wictorwilen.se/ had some really great articles to help me build out a solution focused on this scenario. The code attached to this blog is heavily derived from Omar’s Windows 8 App code though now is useable in non Windows 8 App projects such as C# Console, SSIS Packages and of course CRM Plugin/Workflow projects. I have added some background reading at the bottom of this post so you can see the articles I used to get my code to work.

An example of how simple this code is to use

Uri spSite = new Uri(https://myOrg.sharepoint.com/sites/mySite”);

bool success = SpoAuthUtility.Create(spSite, username@domain.com, WebUtility.HtmlEncode(“Pword123″), false);

string odataQuery = “_api/web/lists”;

Uri url = new Uri(String.Format(“{0}/{1}”, SpoAuthUtility.Current.SiteUrl, odataQuery));

// Send a json odata request to SPO rest services to fetch all list items for the list.

byte[] result = HTTPHelper.SendODataJsonRequest(

url,

“GET”, // reading data from SP through the rest api usually uses the GET verb

null,

(HttpWebRequest)HttpWebRequest.Create(url),

SpoAuthUtility.Current // pass in the helper object that allows us to make authenticated calls to SPO rest services

);

string response = Encoding.UTF8.GetString(result, 0, result.Length);

You can authenticate using corporate credentials if inside your network, username/password if outside your network (e.g CRM Online O365) and you can also use your onmicrosoft.com accounts. Remember that my primary focus was on server to server integration possibilities, not user to server contexts such as in the current SharePoint CRM List Component model.

The attached C# Console app contains 3 files to provide you with an example of how to use the 2 cs classes HTTPHelper and SPOAuthUtility. To authenticate and start calling REST from CRM Plugins/Workflows simple include the HTTPHelper and SPOAuthUtility cs files into your Plugin/Workflow project.

Example App is available here https://skydrive.live.com/redir?resid=492A170E77E43399!830

Background reading

http://blogs.msdn.com/b/omarv/archive/2012/10/25/windows-8-store-apps-office-365-enterprise-preview-sharepoint-online.aspx

http://blogs.msdn.com/b/omarv/archive/2012/11/15/developing-windows-store-apps-for-sharepoint-online-with-sso-single-sign-on.aspx

http://www.wictorwilen.se/Post/How-to-do-active-authentication-to-Office-365-and-SharePoint-Online.aspx

http://allthatjs.com/2012/03/28/remote-authentication-in-sharepoint-online/

CRM 2011 SDK version 5.0.16 available

The MS CRM Team have released an updated CRM 2011 SDK version 5.0.16 which can be downloaded here http://www.microsoft.com/en-us/download/details.aspx?id=24004 or viewed on MSDN here http://msdn.microsoft.com/en-us/library/gg309408.aspx Check out the SDK Release History notes here http://msdn.microsoft.com/en-us/library/dn198205.aspx

 

What’s Changing in the Next Major Release – This new topic outlines features that will be changing in the upcoming Orion release and provides a tool you can use to help you prepare your organizations for these changes.

 

New and updated topics Description of changes
Microsoft_Dynamics_CRM_2011_SDK_Readme.htm Updated the readme for this version of the SDK package.
Active Directory and Claims-Based Authentication

Authenticate Office 365 Users with Microsoft Dynamics CRM Online Web Services

OrganizationServiceProxy

DiscoveryServiceProxy

Updated these topics to remove the restriction on using the service proxy classes when authenticating with the Microsoft online services identity provider of Microsoft Dynamics CRM Online. You can now use these proxy classes with all deployment types and identity providers.
BulkDeleteRequest

BulkDetectDuplicatesRequest

Added in Remarks that you can run the bulk delete job or bulk detect duplicates job daily or without recurrence.
Create, Export, or Import an Unmanaged Solution

Create, Install, and Update a Managed Solution

Added a note to these topics saying “Installing a solution can interfere with normal system operation. We recommend that you schedule solution imports when it’s least disruptive to users.”
Form XML Reference The following FormXml elements have been updated to indicate that they are for internal use only: <ControlMode> (FormXml), <QuickFormRelationshipName> (FormXML), <QuickFormRelationshipRoleOrdinal> (FormXml), and <UniqueId> (FormXml). These elements are used only in a quick form, which is not customizable. These elements will be removed from the schema in the next major release.
Handle Exceptions in Plug-Ins Clarified how plug-in exceptions are handled and where error message are written or displayed.
Introduction to Activity Feeds Corrected the maximum number of characters in the posts created programmatically. The correct value is 2000 characters.
Introduction to Solutions Added the Enterprise Solution Lifecycle Management section introducing the ALM for Microsoft Dynamics CRM 2011: CRM Solution Lifecycle Management white paper.
Open Forms, Views, Dialogs and Reports with a URL Appended to an existing note to include:

Microsoft Dynamics CRM forms are not designed to be opened as dialogs using either showModalDialog or showModelessDialog.

Uninstall or Delete a Solution Added an Access the Solutions List with a URL section.
What’s Changing in the Next Major Release Added a new topic to provide information about what is changing in the next major release of Microsoft Dynamics CRM.
Write Custom Code for Microsoft Dynamics CRM for Outlook

GoOffline               GoOnline

Added a note that these methods cannot be used in a plug-in because they cause a UI interaction with the user.
Xrm.Page.data.entity Attribute Methods Added a missing getFormat return value: textarea.
Xrm.Page.ui Control Methods Added a remark to the addCustomView method to show that this method does not work with Owner lookups.
Xrm.Utility Reference Corrected an error for the openEntityForm method. This method returns a Boolean value rather than a window object.

Toolbox for Dynamics CRM 2011 by Tanguy MVP

Tanguy has developed a toolbox to house his existing Windows based tools developed for Dynamics CRM 2011. You can read more here and also download it from CodePlex at http://xrmtoolbox.codeplex.com/

Here is the list of available tool plugins.

  • Attribute Bulk Updater
  • Iconator
  • Role Updater
  • Scripts Finder
  • SiteMap Editor
  • Solution Import
  • View Layout Replicator
  • WebResources Manager

Tanguy has designed the toolbox so you can develop your own plugin tools and include them in the toolbox. https://xrmtoolbox.codeplex.com/documentation

 

 

Troubleshoot and analyse CRM 2011 using Log Parser

Sometimes you have issues that you want to troubleshoot and other times you may choose to investigate/analyse/review your CRM 2011 environment.  Often performing health checks is necessary and I suggest necessary if you haven’t already thought of this. One of the tools I promote for searching and crunching logs is Log Parser. This awesome tool is a powerful, versatile tool that provides universal query access to text-based data such as log files, XML files and CSV files, as well as key data sources on the Windows® operating system such as the Event Log, the Registry, the file system, and Active Directory®. If that doesn’t sound awesome enough for you how about if you could write a sql type query against the server’s Application Event Log to find where lock is found in the message attribute like so.

SELECT * FROM \\server1\APPLICATION where message like ‘%lock%’

or lets look at the Application and System Event Log entries for server1

SELECT * FROM \\server1\APPLICATION, \\server1\SYSTEM where message like ‘%lock%’

but wait there, what if I have 2 front end CRM servers, server1 and server2.

SELECT * FROM \\server1\APPLICATION, \\server1\SYSTEM, \\server2\APPLICATION, \\server2\SYSTEM where message like ‘%lock%’

This is just touching the surface of what this tool can do to dig through information held in your environment, this is also all from my own desktop machine, there is no need to log on to various servers to gather this information. So command line is so yesterday I hear you say, well there is also Log Parser Studio which presents a library of ready to go queries for various sources. You need to install Log Parser first and then you’re ready to go.

You can also take a look at Log Parser Lizard by Dimce Kuzmanov, a free GUI tool for managing queries and exporting results to Excel and charts. In addition, you will find input filters for RegEx and log4net input log formats (with support for regular expressions) and SQL server T-SQL queries.

Here is a useful article from MS Support regarding some useful Log Parser queries http://support.microsoft.com/kb/910447

So what about CRM Trace Files

SELECT top 2 * FROM C:\Temp\server1-w3wp-CRMWeb-20120210-1.log where Text like ‘%Error%’

As you can see this is fairly awesome stuff and there is so much more that you can use this tool for. Hopefully this has introduced you to something new and useful for your future discovery.

CRM 2011 Validate User Security Roles using JavaScript/REST

This example I’m sharing today is demonstrating a few techniques which promote JavaScript and REST, along with using namespaces and creating a library of functions/properties. This example declares a library Security.UserInRole and defines a number of properties and functions. The general idea is to allow the data access via REST to be asynchronous which then offers a valid and invalid function callback option to be defined to handle the outcome. You can specify an array of security roles to check against the current user and then with the callback functions you can perform the actions that you require.

Ideally I want to call a function that is easy to use and it will look like this.
Security.UserInRole.checkUserInRole(
["System Administrator", "System Customizer", "Custom Role Name"],
function(){alert("valid"); // The user is in one of the specifed roles.
},
function(){alert("invalid"); // The user is not in one of the specifed roles.
}
}

To define the library namespace and object we use
//If the Security namespace object is not defined, create it.
if (typeof (Security) == "undefined")
{ Security = {}; }
// Create Namespace container for functions in this library;
if (typeof (Security.UserInRole) == "undefined") {
Security.UserInRole = {
__namespace: true
};
}

 

The library functions and properties declared include the following
Security.UserInRole = {
isInRole: null,
roleIdValues: [],
validFunction: null,
invalidFunction: null,
checkRoles: [],
checkUserInRole: function (roles, validFunc, invalidFunc) {},
getAllowedSecurityRoleIds: function () {},
validateSecurityRoles: function () {},
querySecurityRoles: function (queryString) {},
__namespace: true
};

 

The entire library is implemented so that you call a function, it performs the processing asynchronously and then gives you the outcome to handle the response. Whether you want to show/hide form elements or disable fields etc, you can handle this in the callback function parameters validFunc and invalidFunc defined in the checkUserInRole function. The entire library content can be placed in a CRM webresource and added to a form. The full library is as shown below.

//If the Security namespace object is not defined, create it.
if (typeof (Security) == "undefined")
{ Security = {}; }
// Create Namespace container for functions in this library;
if (typeof (Security.UserInRole) == "undefined") {
Security.UserInRole = {
isInRole: null,
roleIdValues: [],
validFunction: null,
invalidFunction: null,
checkRoles: [],
checkUserInRole: function (roles, validFunc, invalidFunc) {
validFunction = validFunc;
invalidFunction = invalidFunc;
checkRoles = roles;
Security.UserInRole.getAllowedSecurityRoleIds();
},
getAllowedSecurityRoleIds: function () {
var filter = "";
for (var i = 0; i < checkRoles.length; i++) {
if(filter == "") {
filter = "Name eq '" + checkRoles[i] + "'";
}
else {
filter += " or Name eq '" + checkRoles[i] + "'";
}
}
Security.UserInRole.querySecurityRoles("?$select=RoleId,Name&$filter=" + filter);
},
validateSecurityRoles: function () {
switch (Security.UserInRole.isInRole) {
//If the user has already been discovered in role then call validFunc
case true:
validFunction.apply(this, []);
break;
default:
var userRoles = Xrm.Page.context.getUserRoles();
for (var i = 0; i < userRoles.length; i++) {
var userRole = userRoles[i];
for (var n = 0; n < Security.UserInRole.roleIdValues.length; n++) {
var role = Security.UserInRole.roleIdValues[n];
if (userRole.toLowerCase() == role.toLowerCase()) {
Security.UserInRole.isInRole = true;
// Call function when role match found
validFunction.apply(this, []);
return true;
}
}
}
// Call function when no match found
invalidFunction.apply(this, []);
break;
}
},
querySecurityRoles: function (queryString) {
var req = new XMLHttpRequest();
var url = "";
// Try getClientUrl first (available post Rollup 12)
if (Xrm.Page.context.getClientUrl) {
url = Xrm.Page.context.getClientUrl();
}
else {
url = Xrm.Page.context.getServerUrl();
}
req.open("GET", url + "/XRMServices/2011/OrganizationData.svc/RoleSet" + queryString, true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.onreadystatechange = function () {
if (this.readyState == 4 /* complete */) {
req.onreadystatechange = null; //Addresses memory leak issue with IE.
if (this.status == 200) {
var returned = window.JSON.parse(this.responseText).d;
for (var i = 0; i < returned.results.length; i++) {
Security.UserInRole.roleIdValues.push(returned.results[i].RoleId);
}
if (returned.__next != null) {
//In case more than 50 results are returned.
// This will occur if an organization has more than 16 business units
var queryOptions = returned.__next.substring((url + "/XRMServices/2011/OrganizationData.svc/RoleSet").length);
Security.UserInRole.querySecurityRoles(queryOptions);
}
else {
//Now that the roles have been retrieved, try again.
Security.UserInRole.validateSecurityRoles();
}
}
else {
var errorText;
if (this.status == 12029)
{ errorText = "The attempt to connect to the server failed."; }
if (this.status == 12007)
{ errorText = "The server name could not be resolved."; }
try {
errorText = window.JSON.parse(this.responseText).error.message.value;
}
catch (e)
{ errorText = this.responseText }
}
}
};
req.send();
},
__namespace: true
};
}

 

To use the library in the onload event of an entity form simply add the Security.UserInRole library webresource to the form and create a another JavaScript web resource to hold the onload function. The onload function may look like this. You define the roles to check as an array and pass this to the checkUserInRole function along with the valid and invalid callback functions. You don’t have to define the functions as anonymous functions like my example below but it can sometimes feel cleaner.

function onload()
{
Security.UserInRole.checkUserInRole(
["System Administrator", "System Customizer", "Custom Role Name"],
function(){alert("valid"); // The user is in one of the specifed roles.
},
function(){alert("invalid"); // The user is not in one of the specifed roles.
}
);
}

 

I would like to mention Jim Daly from the MS CRM Team for his examples of namespace and library structure along with his REST query code as this example I have created is derived from his outstanding work.

Happy Coding..

CRM 2011 Multi Browser Support

CRM 2011 from Rollup 12 now support multiple browsers, but which ones and on what operating system? See below for a quick reference.

OS Internet Explorer Firefox Chrome Safari
Windows 8 IE 10 (Desktop mode) 16+ 21+ Not Supported
Windows 7/Vista IE 8/9 16+ 21+ Not Supported
Windows XP IE 7/8 16+ 21+ Not Supported
Mac OS-x 10.7 (Lion) Not Supported Not Supported Not Supported 6+
Mac OS-x 10.8 (Mountain Lion) Not Supported Not Supported Not Supported 6+

Microsoft Dynamics CRM 2011 web application and mobile device requirements

Support with Microsoft Dynamics CRM 2011 and Windows 8

Support with Microsoft Dynamics CRM 2011 and Internet Explorer 10

Note: IE7 is not supported with CRM Online

CRM 2011 Rollup 12 now available

The Microsoft Dynamics CRM Sustained Engineering (SE) team have been hard at work to get the UR12 release to us on Jan 7 2013.

You can find the related Rollup 12 items here

Rollup 12 Build Number: 5.0. 9690.3218

Quick Summary

http://msdn.microsoft.com/en-us/library/gg309589.aspx#BKMK_UR5

  • Extended Browser Support
  • Enhancements to Activity Feeds
  • Updated User Experience for Sales and Customer Service and Product Update Functionality
  • Custom Workflow Activities for Microsoft Dynamics CRM Online
  • Developer Toolkit Support for Microsoft Visual Studio 2012
  • Retrieve and Detect Changes to Metadata
  • Use Execute Multiple to Improve Performance for Bulk Data Load