I'm sure by now that you've seen the new hierarchical visualisations in Dynamics CRM 2015. By clicking on the little icon in lists or on a form you can see the records graphically laid out. In true Dynamics CRM style anything you can do through the user interface is accessible through the SDK and so we now have the ability perform fetchXml queries using the above, eq-or-above, under & eq-or-under conditions. These new search criteria will find records up to a maximum of 100 recursions for a single hierarchical relationship. Take a look at the excellent SDK topic Query hierarchical data on the subject.
I have found that when some users see the cool looking Dynamics CRM Online logon page they will ask 'Can I do that?!' I thought I would answer that question with a new SparkleXRM sample solution. Take a look:
Installing Network Visualisations (CRM 2015)
Import SparkleXRM - SparkleXRM723managed.zip
Import NetworkView - NetworkView104alpha_managed.zip
Usual MIT license applies!
For a list of known issues and reporting new ones please use the GitHub repository.Thanks to CRMCAT and Jukka Niiranen for all the help and feedback so far.
I've just published the latest version of SparkleXRM on NuGet to make it easier to use from within Visual Studio.
You can simply add a NuGet reference to SparkleXRM and the dependancies will be pulled in as well.
PM> Install-Package SparkleXRM
Once installed, the Sparkle XRM assemblies will be referenced in your project and the latest managed solution can be found in the '\packages\SparkleXRM.7.2.3\content' folder.
Currently there is the CRM2015 version 7.2.3 available but I'll add the 2011/2013 version as well shortly.
I've just committed an update to SparkleXRM with CRM2015 support and the process client API. One of the design decisions I made early on with SparkleXRM was to stick with a CRM2011 solution format to allow installation on both CRM2011 and CRM2013. Now that CRM2015 does not support installing CRM2011 solutions I've had to branch and make both CRM2011 and CRM2015 versions available. The code base still remains the same but they are distributed through two separate solution files depending on your target version. You can download the new CRM2015 SparkleXRM solution from github.
The new client side process control API is such a welcome addition. The latest version of SparkleXRM contains support for this so that you can:
Write code to run when the stage is changed or the user selects a process tab (such as hiding/showing sections on the form.
// Add On Process Stage change
// Stage Stepped forwards backwards
// Add On Process Stage change
// Stage Tab Selected
Write code to get the current process and stage so that onload functions can show/hide sections on the form.
// Get Current Process
Process process = Page.Data.Process.GetActiveProcess();
Stage stage = Page.Data.Process.GetActiveStage();
Script.Alert("Process = " + process.GetName() + " Stage = " + stage.GetName());
Write code to get the stages and steps of the current process and find the attributes that are referenced – I've not found a use for this yet!
// Get Stages
ClientCollection stages = process.GetStages();
if (stages.GetLength() > 0)
// Get Steps
Stage stage0 = stages.Get(0);
ClientCollection steps = stage0.GetSteps();
steps.ForEach(delegate(Step step, int index)
Script.Alert(step.GetName() + " " + step.GetAttribute());
Write code to show/hide or collapse/expand the process ribbon:
// Show/Hide Process
Write to advance/step back the stage or change the process/stage completely:
// Change stage
// Change process
Stage currentStage = stages.Get(0);
Page.Data.Process.SetActiveStage(currentStage.GetId(), delegate(SetActiveStageResult result)
// Change process to the first available process that the user has access to.
// If the same as the current process, this does nothing.
Page.Data.Process.SetActiveProcess(processes.Keys, delegate(SetActiveProcessResult result)
Along with the server side branching support for processes – I think this really finishes off this feature nicely. The business process flow feature is now by far my favourite in terms of innovation, business usefulness and developer API. First it was gold in CRM203 RTM, then green in SP1 - now with CRM2015 I especially like the calming cool blue that the process ribbon is now rendered with!
Whilst pushing a recent commit on SparkleXRM I recieved the following error:
An error was raised by libgit2. Category = Net (Error). Error while copying content to a stream.
I turned it off again (rebooted), and used fiddler to trace what was going with no luck. In a last ditch attempt I changed the networking on my virtual machine from NAT to Bridged and hey presto it worked agiain.
So it seems that Git doesn't like NATed connections from Virtual Machines.
Hope this helps someone else!
Sparkle XRM provides a great way of creating grids and forms that look and work similar to Dynamics CRM but sometimes you need to create a responsive user interface that is a little different. Luckily there is a wealth of jQuery plugins out there that provide a great starting point. For this post I'm going to show you how to use FreeWall to create a dynamic grid layout of contact cards but the same approach would apply for any other plugin that isn't included in the core Sparkle XRM dependencies library. This sample creates an HTML web resource that lays out your contacts in a responsive grid that resizes depending on the size available.
Create the Script# Import
Create the View Model
It is a good idea to start with the View Model since this defines all the functionality that the View must expose as well as communicating with the server. For this sample we have a simple view model that simply loads a list of contacts into a list so that FreeWall can be bound to it to display our contact cards. It also provides a function to get the Image Url of the contact and return a placeholder image if no image is defined. The contact image can be found by returning the attribute with logical name 'entityimage_url'
Include the library JS
Once you've selected the library you want to use, you'll need to include it in your Crm Solution project under the js folder, and give it a UniqueName and Display Name similar to dev1_/js/freewall.js
Create the HTML View
The HTML View should be added to the html folder and must contain the scaffolding to hook the jQuery library into and initialise the View code. The data binding is done using Knockout's built in templating engine using the 'template' binding.
Create the View Class
The view class's job is to instantiate the View Model and initialise the binding.
Notice the OnAfterRender call back – this is called every time a new contact card is rendered because of the binding afterRender: Client.InlineSubGrids.Views.ContactCardView.onAfterRender in the HTML. If this is not done then the freewall grid will not layout until the window is resized.
The result is a nice and responsive layout that optimises the fill the available space and has variable height blocks.
I've just published an update to my Multi-Entity Search Solution (after being encouraged by my friend and fellow Dynamics CRM MVP Gus Gonzalez!).
Search across multiple entities at once.
Uses the same configuration as the mobile client 'Quick Find' (Settings->General ->Set Up Quick Find). This allows you to select which entities you would like to search across.
Virtual Scrolling with new records loaded as you scroll rather than all loaded at once.
Shows the primary entity image of returned records (if there is one) in the search results.
In the new version you'll find:
A search button added to the top navigation bar* rather than using a Command Bar button.
Auto searching as you type the search term
Mouse Wheel horizontal scrolling support
*Since there is no supported way of doing this, I've had to do a little DOM shenanigans to get this to work the way Gus wanted!
To try it out you'll need to install the following 2 managed solutions:
If you like this, you might also like to check out my Start Menu Navigation for CRM2013!
If you are doing Sparkle XRM development then you'll find these code snippets I've created for VS2012 very useful. You can grab them from the master repository: https://github.com/scottdurow/SparkleXrm/tree/master/SnippetsTo start using these snippets you simply need to copy the contents of the Snippets directory and paste it into your profile directory at Users\<username>\Documents\Visual Studio 2012\Code Snippets
Using the snippets in Visual Studio is easy – When you are creating a new view HTML page just select all the default code and then type 'sparkle-view-page' followed by TAB. This will add the page snippet and allow you to TAB around the highlighted variable parts of the template which in this case are the name of your Client library (default Client.js) and the name of your View Class:
Once you've finished updating the parameters press Escape to exit the snippet edit.
You can then move the cursor to the line marked <!--TODO--> and add in your form by typing 'sparkle-view-form'. This allows you to enter the name of your view model instance and the title of your form section. Now you're ready to move to the TODO line and add the fields by typing the name of the field snippet and again pressing TAB and filling in the parameters.
Here is a list of all the snippets included:
sparkle-view-page – Adds the standard HTML View template
sparkle-view-form – Adds the standard Sparkle XRM Form scaffolding
sparkle-view-grid – Adds a Sparkle XRM grid
sparkle-view-text – Adds a text field
sparkle-view-numeric – Adds a numeric field and allows setting the max/min to a constant or view model field.
sparkle-view-optionset – Adds a optionset field and allows specifying the entity and attribute to grab the optionset metadata from.
sparkle-view-datetime – Adds a datetime field
sparkle-view-lookup –Adds a lookup field and allows specifying the search command to return the available records to select. The sparkle-viewmodel-searchcommand can be used to create the search command in the ViewModel Script# code.
There are also some snippets to add a View and ViewModel:
sparkle-view-class – Used to create a template view class that is referenced by your html view page.
sparkle-viewmodel-searchcommand – Used to create a command that is used to bind to a sparkle-view-lookup to be used when searching within the lookup field.
You'll find that using this snippets will speed up writing your code and reduce errors. Hope it helps!
When I blogged about my CRM 2013 Start Menu solution I said I would also post about how it caches metadata on the client – so here is that post!
Metadata is the information that describes other data and in the case of CRM 2013 metadata describes entities, relationships and attributes as well as other configuration elements such as the sitemap. The Start Menu solution needed to read the sitemap in order to dynamically display it in the drop down command bar button. Initially the solution read the site map from the server every time the menu was displayed. This wasn't too bad but the solution also then had to make additional requests for entity metadata to retrieve the localised display name, image and object type code. What's more is the solution then had to retrieve the user's privileges and iterate over the sitemap to decide if the user had access or not. This is a common scenario with any webresource development for Dynamics CRM – it could be option set labels or view layoutxml - all need by the client every time the page is displayed. Since this metadata doesn't change very often it makes it a very good candidate for caching.
Caching isn't the problem
Whenever designing a cache solution – the first thing to think about is how to invalidate that cache. It's no good being able to store something for quick access if you can't tell if it is stale and needs to refresh – this could lead to problems much worse than poor performance!
Dynamics CRM neatly already provides us with a client side caching mechanism it uses for Web Resources. I blogged about this back in the CRM 2011 days – but it really hasn't changed with CRM 2013. The general principle is that if you request a Web Resource in the following format then you will get the HTTP headers from the server that means that the browser/proxy server can cache the file.
The net result is that the next time that the browser requests this file, provided it has the same number before the WebResources folder then the file will not be requested from Dynamics CRM but served from the cache.
Every time you publish a web resource the number that is used to request web resources is changed so that the client browser gets a new copy and then caches that until the next change of number.
So we have a very effective caching mechanism for static content – but how do we make use of this for dynamic content? What we need is a way of storing the sitemap and all the other metadata needed into a web resource so that it will be cached – but we don't want to have to update a webresource with this information – what we need is something similar to ASP.Net where we can dynamically generate the web resource when requested and then cache the result on the client.
Dynamic 'Ghost' Web Resources
Varying content by language/LCID
Varying content by record id
Varying content by user
Varying content by other parameters such as date
Check out the code for this web resource plugin to see how it's done.
Invalidating the cache
Since we now can cache our server side generated JSON on the client – we need to know how to clear the cache when something changes. In the case of the 'Start Menu' solution that something changing is the sitemap.xml or entity names. The cache key number that is used by the client will change whenever a web resource is added or updated so to clear the client cache we simply need to update a dummy web resource. Part of the solution publishing that contains a sitemap or entity name change should always include a web resource update so that the client will reflect the updates.
Be careful with caching of sensitive data
Caching of metadata is the most common use of this technique, but it could also be used for caching commonly used reference data such as products or countries. This cache can be invalidated easily by making a simple request for the most recent modified on date – but make sure you don't cache any sensitive data since this would be accessible by anyone with access to the client machine.
Making things easier
A future update of SparkleXRM will contain a client side metadata caching framework that I'm working on that uses the techique I describe here, but in the mean time I hope this helps you get better performance from your client side code.
When Windows 8 didn't have a 'Start Menu' there was so much fuss that we saw it return with Windows 8.1 (sort of). If you miss the navigation style of CRM 2011 you might find my CRM 2013 Start Menu solution very helpful.
The solution provides a 'Start menu' on most screens that provides drop down menu with a security trimmed sitemap and a link to Advanced Find from wherever you are (very useful!):
It also provides form navigation when you are on a record form – this is similar to the way the navigation would have looked in CRM2011:
The solution is a SparkleXRM sample if you are interested – I'm going to do a post soon on the techniques I've used to provide client side metadata caching.
First you'll need to install SparkleXRM 0.1.4 or later
Then you can install the Start Menu Managed Solution (be sure to leave the activate checkbox checked upon import of the solution)
Any language resources that are accessible via the SDK will be automatically used but the resources in the sitemap are not all accessible to code and so if you want to provide translations you just add a new web resource with the name - /dev1/js/QuickNavigationResourcesLCID.js. You can use the QuickNavigationResources_1033.js one as a template to translate. If you do create a translation, please let me know so we can add it to the solution.
There is a short delay on first use as the site map is cached
When a user doesn't have access to some elements of the sitemap, the links are removed, but if all subareas are removed, the parent group isn't.
Thanks to Jukka Niiranen, Damian Sinay & Mitch Milam for testing and feedback.
Those of you who've attended an event that I've been speaking at will know that I quote often talk about my kids…My daughter is absolutely mad about Moshi Monsters. Right about the time I was dreaming up SparkleXRM, my daughter was just beginning her obsession and insisting that I spend quality time with her debating the relative merits of each character. It seems I may have been subliminally influenced by one particular Moshling…
Meet Roxy the Moshling…
Any similarities are not intentional and are a mere coincidence. Coincidence or Subliminal? I'll leave you to decide ;)