Pages

Thursday, April 11, 2013

Love Your UI: Icons for CRM

I’m going to make an unusual break from my normal kind of post to talk about customizing Dynamics CRM with paid utilities, and specifically about sourcing professional-appearing icons for CRM’s UI.  The topic doesn’t occur very often in the forums, and generally the advice has been to search Google.

I can’t discount that method, as I’ve used it in the past to locate royalty-free, attribution-free, and open-licensed sets of icons.  While the quality of many sets are great, the bulk of files are cumbersome to manage, and customizing them requires a significant investment of time and energy.  Looking into “modern” Microsoft interfaces with flattened icons, there are very few free options that match this style and look good doing it.  (However, if you’re looking for a good compilation of options, look no further than Chris Coyier.)

What an illuminating experience working with Axialis IconWorkshop has been!  I inquired about the product about 6 months back, and was very graciously granted a gratis license to their full “Pure Flat” icon sets.  I’ve had a handful of opportunities to use them, since, in conjunction with the IconWorkshop to author and customize the results.  Here’s a breakdown comparison of my previous “Google discovery” experience, and using a professional tool:

Locating an Icon

Using Google:

Generally, I don’t use Google to find a single icon.  There is a significant amount of danger for violating copyright and intellectual-property rights.  Icon authors are hard working people too, and icon theft is one of the unspoken undercurrents of web applications, due in part to lazy people like I used to be.

So, the last few times that I used Google, I went straight for “open-source, royalty-free, copyright-free” icon libraries.  There are many, but obtaining them from reputable sites can take some work.  Then, they are bundled into zip files (typically), and generally contain thousands or tens-of-thousands of icon files.  Filenames are the primary descriptors to search on, so if nothing turns up for a basic term, trying variations… or at worst, scanning through thumbnails, are best bets.

Experience Ratings (1 best – 5 worst)  
Time Consumption 4
Skill Required 2
Efficiency of Desired Outcome 5

Finding icons that are legal to use can be a struggle, and sorting and managing the various packing and naming conventions often leave much to be desired when it comes to cataloging or describing collections.

Using IconWorkshop:

Searching through icons that are imported into Axialis Librarian is a fast process, and only made faster, I think, due to indexing of the files.  This indexing extends to metadata keywords, but unfortunately the Axialis icon sets don’t come preloaded with any (at least not by my sampling).  Adding your own keywords takes time, but can certainly help improve it.  For the basis of rating this experience, though, I will not consider it an advantage.

When it comes to the image you want to use, Axialis has many libraries with an impressive number of icons, but they don’t yet have a “full set” purchase experience—unless you use their in-site contact form to inquire about it.  Their prices are fair for long-term use, and more importantly, they include “base” icon images and “overlay” images that can be easily combined to create new permutations easily.  Searches will generally turn up both, however variety is going to cost you.  That said, it’s generally easy to figure out which set likely contains the candidate icon you want.

Thankfully, you can import assets from other libraries (especially any “free” sets you may already have), and the IconWorkshop can be useful for searching those, as well.  Depending on how you look at it, Axialis icon sets are not given first-class status over other libraries--and that’s either noble, or a lost opportunity.

Experience Ratings (1 best – 5 worst)  
Time Consumption 4
Skill Required 2
Efficiency of Desired Outcome 4

While IconWorkshop helps with searching and organizing, Axialis’ icon sets are hamstringed by lack of useful keyword metadata accompanying their files.  They could have taken a “2” or “1” rating in the efficiency department, and probably lower in other areas.  However, the improved organization and the search capabilities maintain a slight edge over searching through the file system with something like Agent Ransack.

Icon Set Quality

Using Google:

“Free” icon sets come in varying styles and quality, so it’s hard to judge them collectively.  Often, it’s difficult to find a icon that comes in several native sizes.  Most “free” sets offer one or two sizes, and are often capped at 32x32, so scaling up or down impacts quality by producing pixelated or blurry results, respectively.  Within Dynamics CRM, 32x32 and 16x16 are used throughout the ribbons, grids, and menus; however, custom controls and pages can benefit from larger or smaller icons.  I have often found myself repeating the searching phase to find several icons that closely match each other in the various sizes.

File formats are another issue, although generally minor given a good image editor.  Sets generally come in one or two formats, and they may or may not implement transparency.  It becomes important to check and convert, where necessary, to meet your needs.  (JPEG and GIF to PNG, for example.  Maybe that’s only my need, so your mileage may vary.)

Experience Ratings (1 best – 5 worst)  
Time Consumption 3
Skill Required 3
Efficiency of Desired Outcome 3

Across the board, for most cases, if you find an icon you want, and are either lucky enough to have it looking good in every size you need it, or content with visual scaling effects, this is not a bad option.  In my experience, however, it tends to be fairly mediocre.

Using Axialis Icons:

The best thing I can say:  256x256 all the way down to 16x16 of hand-crafted icon goodness.  Each set comes in ICO, BMP, and PNG formats, which covers the Web and Windows spectrum nicely.  On top of this, overlays are separated into their own files with transparency masks as companions.  These only factor into the ratings of this category insofar as they also come in native resolutions that are clean, well-scaled, and visually appealing at all sizes; and also that Axialis has pre-combined many “obvious” overlay and base image permutations.

Experience Ratings (1 best – 5 worst)  
Time Consumption 1
Skill Required 1
Efficiency of Desired Outcome 2

Having pre-built ranges and formats adds a tremendous amount of space to the icon libraries, but the convenience of always having a size and format that works without additional thought is hard to trade away after experiencing it.  The quality and appearance of each image is strikingly good.  However, I do wish the files had an SVG or font-based format—I haven’t needed those for CRM yet, so that doesn’t affect my rating.

Customizing an Icon

Using GIMP:

I’m not going to throw Google under the bus in the image editing department.  There are lots of icon editors available, and image manipulation suites.  My personal favorite is GIMP.  It has many of the features I need for advanced image editing, and it’s open source.  After 10 years, I’m fairly comfortable performing a wide variety of tasks.

Unfortunately, small images don’t feel comfortable in suites meant for larger ones, but it works.  Layers are especially handy for putting together transparency masks and overlays… but overlays are uncommon to find in free icon sets, so most overlays I’ve used were custom produced, adding a lot of time for clean results.

GIMP’s main advantage is its tremendous image editing capabilities—professional caliber features.  However, its learning curve is equally tremendous, and I never quite found the time to automate some repeated tasks.  It does, however, produce superior quality.

Experience Ratings (1 best – 5 worst)  
Time Consumption 5
Skill Required 4
Efficiency of Desired Outcome 4

Unfortunately, GIMP really just helps me “limp” with free icons, helping me cleanup scaling quirks, add custom overlays, or modify palettes.  The time investment is not insignificant, though.  I just didn’t realize it could be so much better.

Using IconWorkshop and Axialis Icons:

IconWorkshop has a feature that will compile and combine in all permutations, the overlays and base images you specify, to automatically produce an array of sizes and decorations without additional effort.  This is one of the faster ways to simply knock-out the 32x32 and 16x16 sizes I desire for CRM 2011. 

The image editing capabilities of IconWorkshop are lackluster, and just advanced enough to satisfy the needs of basic manipulation.  Thankfully, I find myself working within their base+overlay formulas well enough that I haven’t had to step outside of IconWorkshop for anything more advanced.  It’s a borderline comfort, but it fits well for the purpose.

It’s obvious that combining images is IconWorkshop’s strong suit, and that’s why Axialis’ icon sets are amazing within it.  The sets can stand alone, and IconWorkshop can do its deal with any source, but together they offer a purpose-built system that streamlines the whole process of tailoring icons—if you require it.  Again, Axialis has taken the liberty of combining common base and overlay permutations and included them in their large icon set files, so that reduces the need for customizing in the first place (or simplifies recombinant decoration).

Experience Ratings (1 best – 5 worst)  
Time Consumption 2
Skill Required 3
Efficiency of Desired Outcome 2

By using a simpler tool and products that are built to work with it in an optimized fashion, I have shaved a lot of time from the process of building a slick-looking, custom UI within Dynamics CRM.

Average Scores:

 

“Free” Axialis
Time Consumption 4 2.33
Skill Required 3 2
Efficiency of Desired Outcome 4 2.66

I’m starting to understand the adage: “It’s not nobler to do by hand, what can be better and faster done with a tool, when lunch is on the line.”

Thursday, February 28, 2013

High Availability Workflows

Since joining Avtex, I have been able to expand my horizons and gain exposure to customers with unique needs.  I try, as hard as possible, to incorporate or build on top of CRM’s out-of-box experience, and refrain from writing code I don’t have to.  To that end, I’d like to share a simple solution to making Workflows trigger while they’re deactivated for updating.

It’s no secret that business processes change on-the-fly.  Implementing changes to active Workflows can be tricky, from an availability standpoint.  Most companies adopt a routine of modifying Workflow designs afterhours, or with operations momentarily held until the modification is complete.  This presents a dynamic and potentially troubling hurdle for “always on” companies.

Because Workflows are listeners to CRM operations, rather than direct participants, any downtime with a particular Workflow means that it’s no longer listening to events.  This allows for the potential of unapplied business logic, and can be very difficult to diagnose or troubleshoot.

Though the space of downtime can be reduced to mere minutes—by developing in an alternate environment and shipping the updated Workflow in as a Solution—the window of opportunity for actions to tip-toe past a disabled Workflow still exists.  For some companies, this is simply unacceptable.

However, you can use the out-of-box Workflow abilities to create high availability Workflows that can be taken offline, modified, and then reactivated, all without missing a single event that was triggered while the Workflow was offline.  This works by splitting the Workflow’s functionality into two separate Worfklows:

  1. An event listening “Dispatcher” Workflow; and
  2. A “Business Logic” application Workflow

By isolating the business logic into a “child Workflow” which is called by its corresponding Dispatcher, one can take the Business Logic offline, while leaving the Dispatcher functional.  This allows the configured triggers of the Dispatcher to operate continuously, though the step which calls the Business Logic counterpart will fail during the downtime.

Though the Dispatcher jobs enter a “Waiting” state, they will be easy to identify (especially if you allow them to delete themselves when they’re successful) in order to resume.  This behavior is generally sufficient enough to allow a wider window for Business Logic adjustment, without requiring additional intervention to process the new logic against records that are awaiting to execute the new logic.  That brings up another excellent advantage to this pattern:

With Dispatchers, you can immediately terminate existing logic and immediately register all further processing against future logic.

Note:  You cannot retarget a different workflow, as that would require taking the Dispatcher offline—which defeats the purpose.  The System Job acts as a cloned instance of a Workflow, so the Dispatcher will always target a specific, business-logic Workflow.  You can approximate a retargeting scenario with Dispatcher juggling, but it would involve trigger overlapping mitigation.

Here’s an example scenario that uses a Dispatcher to update an Account using the Dispatcher and Business Logic pattern:

First, create the Business Logic workflow, and for “Available to Run” select “As a child process”.  Remove all selections from “Options for Automatic Processes”.

image

Then, create the Dispatcher workflow with the “Options for Automatic Processes” setting you desire, and configure it to call your Business Logic workflow.

image

You may now activate both.  Your Dispatcher is diligently watching the events, and the Business Logic is processing your rules.

Here is what happens when you deactivate the Business Logic workflow to make modifications:

image

My example uses a Dispatcher that listens to Account creation, so when I create a new account, here is what I see in the “Workflows” associated to it:

image

As you can see, the Dispatcher caught the event, and then entered a “Waiting” state.  If we examine the job, we can see the error:

image

It failed on the step that calls my Business Logic.  This job will remain in this state until I resume it.  After completing my modifications to Business Logic, I’ll reactivate it.  Then, I need to identify all my outstanding Dispatcher jobs:

image

Then, resume them with the confidence that I have missed no important triggers while my Business Logic was momentarily offline:

image

That said, I always perform a quick validation, just to be sure:

image

Monday, February 11, 2013

A Potent Cocktail: ExecuteMultiple and LINQ

I love it when technologies using the same framework marry together like peaches and cream.  Today, I want to cover the intersection of CRM 2011’s new ExecuteMultiple capabilities and my love of LINQ.  Just to be clear, I’m not talking about using LINQ provider for CRM, though you can certainly use that to produce a collection of records upon which to perform some operation in bulk.

Instead, I’d like to show you an elegant snippet of code that demonstrates the power of ExecuteMultiple with the cleanliness of succinct LINQ.  Given an EntityCollection —someRecords— suppose that you need to increment some integer —my_integer— on each of the contained records.  For the purposes of this example, I’ll be using the late-bound Entity type.

// Start our request with some basic initialization
ExecuteMultipleRequest bulkIncrementRequest = new ExecuteMultipleRequest()
{
    Settings = new ExecuteMultipleSettings()
    {
        ContinueOnError = true,
        ReturnResponses = true
    },
    Requests = new OrganizationRequestCollection()
}

// Compile the collection of requests
bulkIncrementRequest.Requests.AddRange( from record in someRecords.Entities
                                        where record.Contains( "my_integer" )
                                        select new UpdateRequest() 
                                        { 
                                            Entity = new Entity( "someRecord" )
                                            {
                                                Id = record.Id,
                                                Attributes = {
                                                    new KeyValuePair( "my_integer",
                                                        ( ( Int32 ) record[ "my_integer" ] ) + 1 )
                                                }
                                            }
                                        } );

// Excute the requests
ExecuteMultipleResponse bulkIncrementResponse = ( ExecuteMultipleResponse ) service.Execute( bulkIncrementRequest );

// Check "IsFaulted" to determine if any of the submitted requests failed
if ( bulkIncrementResponse.IsFaulted )
{
    Int32 errorCount = ( from incrementResponse in bulkIncrementResponse.Responses
                         where incrementResponse.Fault != null
                         select incrementResponse ).Count();
}

By using LINQ to inject the AddRange method of Requests, I was able to compound the code that loops through each record, selects the original value, increments it, and produces a request to update the record. 

Keen observers notice that I created a new Entity object from the old one; this is a best-practice to avoid triggering updates on attributes undesirably.  However, it also allows me to perform the increment operation inline.  I’m sure you could inject this operation into a secondary where statement, but I think that makes the query logic less readable.  But your mileage may vary.  :)