HOME ABOUT
I AM HERE
  • Twitter icon
  • Facebook icon
  • Technorati icon
Bookmark and Share

Using generic handlers in Dynamics CRM

July 28, 2010 10:58 by Aidan

Sometimes you need to add functionality to Microsoft Dynamics CRM that cannot be easily achieved by simply adding JavaScript to form and field events.

One way to add extra complex functionality to CRM is to use a generic handler .ashx code file.

For example if you want to copy a quote and it's quote products this is not easily achieved using JavaScript and is not possible using the standard CRM workflows.

To make use of a .ashx generic handler is a 3 step process:

  1. Create the .ashx handler that performs the required functions and deploy it to your CRM server
  2. Add a JavaScript function to a form that will call the .ashx and handle the returned result
  3. Update the ISV.config to add a button to the relevant entity so that the user can trigger the functionality

1. Create .ashx handler

To create the handler you will need a new Visual Studio project. Add a Generic Handler (.ashx) code file to the project and then add references to the CRM web services.

Add your code to provide the desired functionality.

Click this link to download the .ashx code files for copying a Dynamics CRM quote 

The application then needs to be deployed to IIS.

2. Add a JavaScript function to call the handler and display the returned result

Add the JavaScript to the onload event of the form where this functionality will be called. In this example of copying a quote add the function to the onload event of the Quote main form.

CopyQuote = function()
{
InitXmlHttp();
xmlhttp.onreadystatechange= XMLHttpRequestCompleted;
// use the url to your generic handler project here - in this case I have deployed the project to the website that is running CRM
xmlhttp.open("GET", "http://YourCRMServer/CRM.GenericHandlers/CopyQuote.ashx?id="+crmFormSubmit.crmFormSubmitId.value , true );
xmlhttp.send(null);
function InitXmlHttp() {
  // Attempt to initialize xmlhttp object
    try
    {
        xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch (e)
    {
        // Try to use different activex object
        try
        {
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
        catch (E)
        {
            xmlhttp = false;
        }
    }
   
    // If not initialized, create XMLHttpRequest object
    if (!xmlhttp && typeof XMLHttpRequest!='undefined')
      {    
            xmlhttp = new XMLHttpRequest();
      }
      // Define function call for when Request obj state has changed
      xmlhttp.onreadystatechange=XMLHttpRequestCompleted;
}
function XMLHttpRequestCompleted()
{
        if (xmlhttp.readyState==4)
    {
        try
        {
            alert(xmlhttp.responseText);
        }
        catch (e)
        {
        }
    }
}
}

3. Update ISV.config to add a button to call the CopyQuote() JavaScript

Export the ISV.config file and add the following to the Quote section:

<Button JavaScript="CopyQuote();">
    <Titles>
            <Title LCID="1033" Text="Copy Quote" />
          </Titles>
              <ToolTips>
                <ToolTip LCID="1033" Text="Copy Quote" />
              </ToolTips>
        </Button>

Save the updated ISV.config file and import it back into CRM.

The result of this is that you now have a button on the Quote form called Copy Quote. When this button is clicked the JavaScript calls the .ashx file which copies the quote and then sends a message back to the JavaScript to let the user know if the operation has been successful.


Create Dynamics CRM entity mapping for lookup field

July 20, 2010 14:32 by Aidan

When editing attributes on CRM entities it is often necessary to pass that attribute through to the entity in the next stage in the sales process.

For example you add a contact name to the quote entity and you want that contact to be passed through to the order that is created from the quote.

To do this for standard fields it is simply a case of opening the customisation screen for the entity, adding a new attribute and then adding a new mapping to the relevant relationship. In the case of quotes and orders this would be the N:1 quote to order relationship.

Where things become a little bit trickier is if you want to create a mapping between two entities for an attribute that is a lookup. This is because it is not possible to simply add a lookup field as an attribute.

To do this for the case of the contact lookup being passed from quote to order do the following:

  • Create a new N:1 relationship on the order entity. The Primary Entity for the realtionship will be Contact.
  • Give it a display name of Contact and leave all the other fields as default.
  • Click Save and Close - this will have created a new attribute called Contact which we can now use to map the Quote Contact attribute to.
  • Edit the Quote to Order N:1 relationship and add a new mapping between Contact in the source and target entities.
  • Click OK.
  • Now you can add Contact to the forms and views where it needs to be visible.

Tags:
Categories: CRM
Actions: E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

Getting started with JavaScript in Dynamics CRM 4.0

June 19, 2010 09:39 by Aidan

This is a blog that is usually about SharePoint and SharePoint development but recently I have been starting to do some work with Microsoft Dynamics CRM 4.0. Initially this work was about integrating SharePoint document libraries with CRM but has now gone beyond that into actual customisation and development of CRM itself.

CRM 4.0 has been around for a while now and many companies who have CRM will also have a SharePoint deployment so although it is a bit off topic I'm sure there are plenty of SharePoint people who will find a bit of CRM information helpful.

As with SharePoint there are lots of options for customising CRM. The first option is customisation of existing entities and forms. This allows you to add attributes to the various objects in CRM such as customers or orders. It is also possible to add JavaScript to the forms to add logic, validation or additional calculations into the forms and this is what this post will take a look at. Finally it is possible to add aspx pages or use ashx handlers in conjunction with the CRM web services to create virtually any extra complex business logic or functionality that is required - later posts will deal with this.

When customising CRM forms it is possible to easily add JavaScript to the on load and on save events of each form or to the on change event of any field.

A few hints and tips:

  • To reference an attribute on a form use crmForm.all.attributename.
  • If the attribute is not a string use .DataValue to return the value held in the attribute. e.g. crmForm.all.attributename.DataValue.
  • DataValue should also be used when creating comparison statements. E.g. if(crmForm.all.isapproved.DataValue == true)
  • If you have a calculated field that is set to read only on the form then you will need to make sure that it is set to ForceSubmit = true otherwise it will not be saved. To do this use the following - crmForm.all.attributename.ForceSubmit = true;
  • To hide a field or menu item use crmForm.all.attributname.style.display = "none";
  • To disable a field use - crmForm.all.attributename.Disabled = false; or use true; to disable the field.

It is possible to set the default for a lookup field. The following example script sets a default price list for the price list field:
 
if(crmForm.all.pricelevelid.DataValue == null)
{
//Create an array to set as the DataValue for the price list lookup control.
var lookupData = new Array();
//Create an Object add to the array.
var lookupItem= new Object();
//Set the id, typename, and name properties to the object.
lookupItem.id = '{0049EC3B-1257-DF11-8A46-00155D025108}';
lookupItem.typename = 'pricelevel';
lookupItem.name = 'Test Price List';
// Add the object to the array.
lookupData[0] = lookupItem;
// Set the value of the lookup field to the value of the array.
crmForm.all.pricelevelid.DataValue = lookupData;
}

Use the following JavaScript to call CRM web services to return information on the current user - this is then used to set a user lookup field to be the current user:

var xml = "" +
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<soap:Envelope xmlns:soap=\"
http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" +
GenerateAuthenticationHeader() +
" <soap:Body>" +
" <RetrieveMultiple xmlns=\"
http://schemas.microsoft.com/crm/2007/WebServices\">" +
" <query xmlns:q1=\"
http://schemas.microsoft.com/crm/2006/Query\" xsi:type=\"q1:QueryExpression\">" +
" <q1:EntityName>systemuser</q1:EntityName>" +
" <q1:ColumnSet xsi:type=\"q1:ColumnSet\">" +
" <q1:Attributes>" +
" <q1:Attribute>businessunitid</q1:Attribute>" +
" <q1:Attribute>firstname</q1:Attribute>" +
" <q1:Attribute>fullname</q1:Attribute>" +
" <q1:Attribute>lastname</q1:Attribute>" +
" <q1:Attribute>organizationid</q1:Attribute>" +
" <q1:Attribute>systemuserid</q1:Attribute>" +
" </q1:Attributes>" +
" </q1:ColumnSet>" +
" <q1:Distinct>false</q1:Distinct>" +
" <q1:Criteria>" +
" <q1:FilterOperator>And</q1:FilterOperator>" +
" <q1:Conditions>" +
" <q1:Condition>" +
" <q1:AttributeName>systemuserid</q1:AttributeName>" +
" <q1:Operator>EqualUserId</q1:Operator>" +
" </q1:Condition>" +
" </q1:Conditions>" +
" </q1:Criteria>" +
" </query>" +
" </RetrieveMultiple>" +
" </soap:Body>" +
"</soap:Envelope>" +
"";

var xmlHttpRequest2 = new ActiveXObject("Msxml2.XMLHTTP");

xmlHttpRequest2.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xmlHttpRequest2 .setRequestHeader("SOAPAction", "
http://schemas.microsoft.com/crm/2007/WebServices/RetrieveMultiple");
xmlHttpRequest2.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xmlHttpRequest2.setRequestHeader("Content-Length", xml.length);
xmlHttpRequest2.send(xml);

var resultXml = xmlHttpRequest2.responseXML;
var entityNode = resultXml.selectSingleNode("//RetrieveMultipleResult/BusinessEntities/BusinessEntity");

var firstNameNode = entityNode.selectSingleNode("q1:firstname");
var lastNameNode = entityNode.selectSingleNode("q1:lastname");
var fullNameNode = entityNode.selectSingleNode("q1:fullname");
var systemUserIdNode = entityNode.selectSingleNode("q1:systemuserid");
var businessUnitIdNode = entityNode.selectSingleNode("q1:businessunitid");
var organizationIdNode = entityNode.selectSingleNode("q1:organizationid");

//Create an array to set as the DataValue for the the lookup control.
var lookupData = new Array();
//Create an Object add to the array.
var lookupItem= new Object();
//Set the id, typename, and name properties to the object.
lookupItem.id = systemUserIdNode.text;
lookupItem.typename = 'systemuser';
lookupItem.name = fullNameNode.text;
// Add the object to the array.
lookupData[0] = lookupItem;
// Set the value of the lookup field to the value of the array.
crmForm.all.approvedby.DataValue = lookupData;
crmForm.all.approvedby.ForceSubmit = true;

Using JavaScript is a great way to customise CRM as any script you add is saved as part of the form so when you come to deploy them they are included in the export customisations file. In my customisation of CRM I have tried to use this approach wherever possible but sometimes what you want to achieve cannot be done without cracking open Visual Studio and this is what I plan on taking a look at in my next post.


Twitter SharePoint Web Part With OAuth

June 9, 2010 20:08 by Aidan

As Twitter are about to stop allowing use of Basic Auth I have updated the Twitter friends timeline web part to use OAuth.

When you add the web part to the page you will be directed to the Twitter OAuth login page once. After that the authentication token and secret are persisted in the properties of the web part although only the token is browsable.

To change the account being displayed simply clear the Token property in the Miscellaneous section of the web part properties and you will be prompted for a new set of credentials.

As a bonus I have also included a Twitter search web part. This does not require authentication but does require you to provide a search term in the Miscellaneous section of the web part properties.

To download the .wsp SharePoint solution file visit this page.

Thanks to Shannon Whitley for his OAuth Twitter example


Tags:
Categories: SharePoint 2010
Actions: E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

North East SharePoint user group meeting - Wednesday 16th June

May 27, 2010 16:57 by Aidan

TSG is teaming up with SUGUK to present the next user group session in the north east.

Tony Hughes from Microsoft Partner TSG who will lead us through methods to exploit Sharepoint functionality in the small to medium Sharepoint Enterprise.
 
This session bridging the technical, development and business audience will be both interactive and enlightening.  It will cover how list enhancements in Sharepoint 2010 can be deployed to allow integrated data solutions,  dip into the exploitation of Excel to create Business Intelligence, show us how to take advantage of Key performance Indicators and dashboards in Sharepoint, delve into how we can use Sharepoint Designer to create valuable data views and step into the critical realm of document management to show the importance of and approaches to document Version Control and Approval Routing.

For more information and to sign up follow this link.


JQuery Library for SharePoint

April 17, 2010 09:11 by Aidan

Up until now I have tended to agree with people like Jeremy Thake who warn against the use of jQuery in your SharePoint deployment. **UPDATE** - see comments from Jeremy below clarifying his position on who should be using jQuery.

However, a common requirement from users is to provide cascading drop down boxes in the new and edit item forms which SharePoint just doesn't provide out of the box.

I then came across Marc Anderson's excellent jQuery library for SharePoint which provides a solution for creating cascading drop downs as well as several other very useful functions.

Although this does not address all the issues of using jQuery I think that it helps to overcome some of them.

  1. The cascade function has already been tested for SharePoint 2010 so I know it won't break when we upgrade.
  2. It is a library which can be reused across SharePoint with minimal additional script needing to be added to individual pages so it can be maintained and updated centrally.
  3. It is a Codeplex project that is relatively popular so I can have some confidence that it will continue to be updated and even if it isn't I have a copy of the library that I can update myself if anything ever became broken in future versions of SharePoint.

 

For more information on the library and the SPCascadeDropdowns functionality take a look here.


CSS3 - rounded corners and drop shadow fun!

March 4, 2010 11:26 by Aidan

As IE9 is going to provide support for CSS3 I thought that it was about time I took a quick look at some of what is going to be available.

The following html and css demonstrates just how easy it is to produce rounded corners, drop shadows and gradient borders without an image file in sight -brilliant!

HTML File

<html>
<head>
<link rel="stylesheet" href="css3.css" media="screen" />   
</head>
<body>
<div class="box"></div>
<br/><br/><br/>
<div class="box2"></div>
<br/><br/><br/>
<div class="box3"></div>
<br/><br/><br/>
<div class="box4"></div>
<br/><br/><br/>
<div class="box5"></div>
</body>
</html>

CSS File

body
{
padding:20px 20px 20px 20px;
}

.box
{
-moz-border-radius-bottomleft:50px;
-moz-border-radius-bottomright:200px;
border:orange 20px double;
-moz-border-radius-topleft:100px;
-moz-border-radius-topright:66.66px;
padding:24px 24px 24px 24px;
width:320px;
height:50px;
}

.box2
{
-moz-border-radius: 1.6em;
border-radius: 1.6em;
border:black solid 1px;
height:100px;
-moz-box-shadow:-10px 10px 20px gray;
width:400px;
}

.box3
{
-moz-box-shadow:10px 10px 20px red;
-moz-border-radius: 1.6em;
border-radius: 1.6em;
border:red solid 1px;
height:100px;
width:400px;
}

.box4
{

background-color: #DAE8EC;
-moz-border-radius-topleft: 10px;
-moz-border-radius-bottomright: 10px;
border: 2px solid #B8CB99;
padding: 10px;
width:380px;
height:70px;
}

.box5
{
border: 8px solid #000;
-moz-border-bottom-colors: #555 #666 #777 #888 #999 #aaa #bbb #ccc;
-moz-border-top-colors: #555 #666 #777 #888 #999 #aaa #bbb #ccc;
-moz-border-left-colors: #555 #666 #777 #888 #999 #aaa #bbb #ccc;
-moz-border-right-colors: #555 #666 #777 #888 #999 #aaa #bbb #ccc;
padding: 5px 5px 5px 15px;
height:100px;
width:370px;
}

If you save these files and open them with Firefox 3.5 or above you should see something similar to:

 


Tags:
Categories: CSS
Actions: E-mail | Permalink | Comments (1) | Comment RSSRSS comment feed

SharePoint Custom Workflow Visual Studio Solution

January 16, 2010 10:57 by Aidan

There are loads of articles and blog posts about creating SharePoint 2007 custom workflows using Visual Studio but most of them only tell part of the story or have certain steps missing. Nick Swan has probably come closest with his post for Visual Studio 2005 but even with a post as comprehensive as this it is clear from the comments that it is something people still struggle with. Rather than rehash all of those posts I thought it would be more useful to provide an example Visual Studio 2008 solution that is already set up and ready to go.

This article does not aim to be a comprehensive guide to setting up a custom workflow. It is aimed at a .net developer audience who are already familiar with SharePoint and InfoPath development but who just need a bit of help bring all the bits of SharePoint custom workflow development together into a working solution.

This solution was created using STSDev v1.4 which gives a good starting point for a sequential workflow solution and automatically creates a .wsp file whenever the project is built. If you are not familiar with STSDev projects the .wsp can be found in the Deployment folder of the project.

In the project I have included the more common generic elements for a custom SharePoint workflow:

  • An InfoPath initiation form that allows the user to provide information to the workflow task. In this case the workflow task title is set and a property is stored to be displayed later on the task form.
  • An InfoPath task form that displays information from the initiation form and allows the user to approve or reject the the item.
  • The sequential workflow itself - wiring this up is often a place where people miss something or make mistakes.
  • A WorkflowTestInitForm.cs file that is used to make the information typed into the initialisaton form available in code. See comments in this file to generate your own.
  • An ItemMetaData.xml file that is used by the InfoPath task form as a secondary data source so that the information supplied by the initiation form can be displayed.

The code has been commented to provide additional information and guidance on how to set up your own workflows. For the solution to work the only thing you have to change before building and deploying the .wsp is line 62 in SequentialWorkflow01.cs - the task assigned to property must be set to a user that is valid for your environment.

To open the solution just save this zip and extract in your development environment - AidanWorkflowTest.zip (91.97 kb)


Tags:
Categories: InfoPath | MOSS 2007
Actions: E-mail | Permalink | Comments (2) | Comment RSSRSS comment feed

What Matters Now - free ebook from Seth Godin

December 24, 2009 15:43 by Aidan

Seth Godin has released a free ebook that brings together the ideas of more than 70 big thinkers discussing what matters now.

At this reflective time of year it is definitely worth a read. Download it here.

 


Tags:
Categories:
Actions: E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

SharePoint Customisation - OOTB vs SPD vs Custom Code

November 18, 2009 11:42 by Aidan

@joyknows has posed an interesting SharePoint question via Twitter -

What would you say are the primary strengths and weaknesses of OOTB customisation vs. SPD vs custom code?

This one is definitely going to take more than 140 characters so here goes...

Out of the box (OOTB) customisation allows any end user familiar with SharePoint to create sites, lists and web parts through the user interface to produce something that meets their specific requirements.

Strengths -

  • Very quick to create customisations
  • Anybody with basic SharePoint knowledge can do it
  • Forces users to create solutions in a "SharePoint way" which encourages consistency

Weaknesses -

  • Doesn't provide much flexibility - compromises have to be made with requirements
  • If you want to repeat the same customisations again then options for recreating the solution are limited - manual repetition of creation steps or templates

SharePoint Designer (SPD) customisation allows power users to get a bit more creative and make use of some of the more advanced options in SharePoint such as custom workflows and connecting to differnt data sources.

Strengths -

  • More options for customisation - will fulfill more of the original requirements
  • Make changes to master pages and page layouts - create a completely new look and feel

Weaknesses -

  • Difficult to deploy customisations made using SPD to other sites - eg. A custom workflow created in SPD is applied to a specific list and cannot be resused on another list. The only option is to manually recreate the workflow again for the next list.
  • It is possible to do a lot of damage very quickly if put into untrained hands
  • Once files are customised by SPD they cannot be changed by custom code

Custom code requires a SharePoint developer to write it but it is the most powerful option that opens up the full SharePoint API, web services and any other code you want to use to customise your solutions.

Strengths -

  • Provides the most options for customisation
  • Customisations can be packaged up as features that are easily deployed and reused in multiple solutions
  • Deployment can be controlled and governed more easily as customisations can only be deployed by people with SharePoint admin permissions

Weaknesses -

  • Requires a SharePoint developer
  • Takes longer to achieve the same results

The above lists are a very brief summary of the pros and cons for each option. In reality it would be possible to have lengthy discussions about each but I think these lists provide a fair summary that should help as a primer for the more important discussion - which option should I choose?

As with most decisions like this the short answer is - it depends. In this case it depends largely on the trade off that you are prepared to make between speed of solution develoment and flexibility/meeting the original requrements exactly.

If you need something fast and are prepared to compromise by not meeting the original requirements 100% perfectly then OOTB is the way to go.

If, on the other hand, you need to have a solution that ticks off every requirement perfectly, that can be easily reproduced across lots of sites and you are prepared to wait a bit longer for delivery then custom code is the answer.

SharePoint Designer is a middle ground that combines the best and worst of all the options. In my opinion it should only be used to quickly prototype something that you later turn into a well packaged custom code solution or where you have to customise to meet a requirement but do not have SharePoint development resources available.

In the interests of full disclosure I am from a SharePoint development background and have also spent a significant amount of time working with SharePoint whilst being constrained to only using OOTB customisations. As a result I am not what I would describe as a typical SharePoint dev - ie. Reach for Visual Studio first and ask questions later!

This may sound like a betrayal of my SharePoint developer brothers and sisters but I would argue that custom code should only be used once you are sure that what is being asked for cannot be achieved using OOTB customisation. That may sound obvious but it is easy to take requirements on face value and assume that what the end user is asking for cannot be compromised on which makes it look as though custom code is the only option. In reality if the end user understands that they can have a solution that meets 80% of the requirements delivered in 2 days using OOTB or a solution that meets 100% of the the requirements in 10 days using custom code those requirements that were previously set in stone suddenly become a bit more flexible.

So in summary, and just to be clear so I don't get flamed by all the SharePoint devs, custom code is great. It provides the most number of customisation options that can be deployed to your SharePoint farm in a repeatable and controlled way. However, I would choose OOTB wherever possible in the interests of speed of delivery and productivity even if that means using your powers of persuasion to talk the end user into settling for a solution that doesn't tick off 100% of the original requirements but does meet the core ones, they will thank you in the end!