Monday, November 23, 2009

Alternative Option to Disabled Field

Disabling fields has been a great way to lock down information within MSCRM. The one issue that I run into with it is that users comment that a disabled field is so "washed out" that it becomes difficult to read.

Another option to use instead of the out of the box disabled, is to make the field read only. It's a very simple script:

crmForm.all.fieldname.readOnly = true;

It leaves the field looking like other fields so that it's not washed out but it cannot be edited from the form. This customization is technically unsupported, but it has been around since the MSCRM 3.0 days and so far Microsoft hasn't locked this script down. We'll find out next version whether or not the script gets carried over or not. But worst case scenario for your scripts would be that they need to be modified to use the disabled option rather than the read only option.

David Fronk
Dynamic Methods Inc.

Friday, November 13, 2009

Easy Emailing from a CRM Contact Record

Has anyone else wanted to be able to click on the email address on a form in CRM and have it email that person/record? Or at least bring up an email message form that can be filled out and sent?



Yes, on the Contact form there is the "Send Email" button, but that sends a CRM email and personally, I'm not a huge fan. They're great for templates but other than that I very much prefer the Outlook experience of emailing.



So, the other day I came up with a good way to get the functionality that I really wanted. I used some script from one of my coworkers that turns the label of a field to a button and then modified the onclick action. Here's what the buttons look like:


And when anyone clicks on the buttons it will take the corresponding email address and use your default mail client (most likely Outlook) and open up an email message for you:


This is all done with script and with only a little fiddling the form is now so much more functional now. And for all you coders out there, here's the part you want, the code:

/********Email Button Creation********/
// Replace the attribute new_button with the button and create a link to the onclick function

function CreateEmailButton() {
var fieldTable = crmForm.all.emailaddress1_c;
var html = "<input onclick='Email_Button_OnClick()' value='Primary' type='button'>";
fieldTable.innerHTML = html;
}
// Function to be triggered onClick
Email_Button_OnClick = function()
{
window.location = "mailto:" + crmForm.all.emailaddress1.DataValue;
}
CreateEmailButton();


It's the little things in life that make us happy, so why not make your CRM users happy by adding some simple solutions to make their jobs easier? I don't necessarily mean this solution, but anything that makes it so that people don't have to do the same function 50 times a day sure brings a big smile to their face :).
David Fronk
Dynamic Methods Inc.

Friday, November 06, 2009

Why should I care whether my data is in a database or not?

This may sound like an obvious question but amazingly enough there are a lot of people who don't always quite get this. When asked how people manage their data and they tell me that they look up their lists in Word, I cringe. Or when people use Excel for all of the note taking needs and then ask for it to me imported into CRM I question the usefulness of such an exercise. Word is great for writing documents and letters. Excel is a mini database and monster of a calculation and reporting tool. CRM, from a data perspective, is a relational database that can track just about anything and relate one set of data to another set.

While I've only seen a handful of people using Word to track data, Excel is used all of the time. And amazingly enough people use Excel like Word. Putting an address of street1 street2 city state zip all in one cell isn't the best use of a cell. Breaking that out into separate data fields, or their own Excel cells makes it so that you sort, query, and group data together. That's the power of relational databases like CRM. With data being broken out and related properly data is able to be queried, grouped, sorted, quantified, calculated, and more properly analyzed. There aren't many limits on what you can do as long as your data is entered and records linked correctly between tables.

There is a huge difference between a CRM system with bad data and a CRM system with good data. One can actually effectively help users to target the proper places to focus their time and the other just misleads and frustrates people.

How do you store your data? Are you tracking everything that is of use to you?

David Fronk
Dynamic Methods Inc.

Tuesday, October 27, 2009

Rollup 7

If you haven't seen it from the numerous other blogs that have already posted this, here's the link to where you can download the rollup. It is cumulative, so be aware of that.

David Fronk
Dynamic Methods Inc.

Tuesday, October 20, 2009

Windows 7 available to all October 22

If you haven't seen all the media that Microsoft is putting out around Windows 7, I'm telling you about it now. I've been using Windows 7 for a little while now and it is great, head and shoulders better than Vista. If you are on a Vista machine, I completely recommend upgrading to Windows 7 ASAP. If you're on XP, I still recommend upgrading, just make sure you have enough time because it esssentially will be like doing a full reinstall.

Check out Windows 7 here. And if you want to see some of the features, here are some videos from Microsoft's website on them.

One other comment regarding any fear people have about upgrading. Vista has taken the brunt of most of the big changes and now Windows 7 just makes all of the difficult stuff seem easy. All of the driver incompatibilities, Vista went through it, Windows 7 will use the same drivers for the most part so it's set for most/all software and hardware. Most of the complaints I had about Vista were virtually gone immediately after the upgrade to Windows 7.

Oh, and CRM totally works on Windows 7, since IE8 works with CRM Windows 7 just had to be able to run IE8.

Anyway, if you haven't had a chance to play with it, get yourself ready for Oct 22.

David Fronk
Dynamic Methods Inc.

Friday, October 09, 2009

Microsoft Dynamics CRM 4.0 Adapter for Microsoft Dynamics GP 10.0

This week Microsoft released their integration adapter for Dynamics CRM and GP. This is now Microsoft's third attempt at integrating their own applications.

For anyone who used their first integration solution with BizTalk server in CRM v1.2, my hat goes off to you. It was a bear to set up, even worse to troubleshoot, and once everything was in place you never breathed on that thing again for fear of it breaking it was so delicate.

The integration with CRM 3.0 and GP 9.0 was much better but still had a lot of limitations. And since the previous attempt was so ugly I think most people avoided it.

And now, we have been introduced to the integration between CRM 4.0 (Rollup 5) and GP 10.0 (SP4) (yes those are the minimum software requirements for the integration). At first glance the tool looks like a lot more time, effort and thought was put into this integration than the other previous attempts. Well, a lot of thought and effort was put into the BizTalk integration I'm sure, it just didn't work.

The integration runs on a service and the console has been built on WFP. In it's current version 1.0 status it links up very well between anything that comes out of the box. Without some customization there is no way to get custom attributes or entities. I'm not surprised by this because that's typically how Microsoft CRM additions start out. They make sure they can get the base entities handled, then they grow out to the custom entities. Case and point, look at CRM v1.2, no custom entities and limited custom attributes, CRM v3.0, custom entities and free reign of custom attributes; out of the box imports, only to out of the box entities in CRM 3.0 and CRM 4.0 allows for imports to custom entitites; etc). What this integration package will include however is it's own SDK so that partners, developers, customers, etc can write their own integration templates, integration links between fields, and integration connections (to other applications).

This integration doesn't provide any upgrade path from previous integrations but it was mentioned how there are plans to include integration templates/connections to other Dynamics applications (Nav, AX, SL, CRM Online etc). But with the release of the SDK coming before the end of the year anyone will be able to work on their own integrations utilizing this tool. That's right, the SDK is going to allow for developers to create connections/adapters to whatever you can connect to, whether it be a Microsoft product or not. Now, here's the catch. They said that this was a "lightly extensible tool" so I'm not sure light they are talking about until I'm able to get a hold of the SDK. If you integrate any Dynamics product with another Dynamics product (CRM, GP, AX, NAV, SL) then the integration is 100% FREE (assuming that you have a current Enhancement/Support plan). However if you integrate with another system then you must purchase a Dynamics Client for Office (DCO) license. From the presentation slide they state:

"...for every person who sends data to Microsoft Dynamics GP or receives data from Microsoft Dynamics GP must have a DCO license."

Couple of high points, things that I liked:

1. The Log/Error catching looked really good. The messages appeared to be detailed, read the problem fix it and then you could retry a given error again and have that push. You could stop a retry (default is to retry an error 7 times) and (again) retry the error after you stopped it.
2. Scheduling when a given adapter would run. Anywhere from Continuously (3 times a second) to Once. Very flexible and easy to set up.
3. SDK promises. Developers will be able to create their own mapping functions (if there were no SUM function you could create it with the SDK) and ability to add custom fields and connect to other systems.

Couple things that I didn't like (personally):

1. A lot of wizards. Wizards are great because they help guide you in a step by step process but it just seemed to me that there were wizards in places that didn't need to have them. For instance there is a wizard for mapping one field to another. If I map them, shouldn't it just map field to field and then if I want to do something more complex I would then edit the connection? Having wizards may be something that a lot of people like and makes this integration tool appealing to them, so don't let me get you down if you like them. I just set up a lot of data migration/integrations and thinking about the time I would have to spend mapping field to field for something that's not in a template already just seemed tedious.
2. I didn't get to see what really goes into writing a script on a mapping. I saw some scripts but thye were always cut of. The script looked like it was similar to VBScript but it definitely wasn't. It also appeared to be similar to Scribe's scripting language that is used between mappings though. So, I'm sure it will be some mesh of the two but at the same time it will be it's own beast to learn. It could be good, I just didn't get to see much of it.
3. Out of the box you can only use the templates that Microsoft provides, which is only between GP and CRM. It's version 1, but it's definitely limited in what it can do out of the box. A lot of development time will need to be spent if someone wants to integrate Vendors for instance. Hopefully a wizard will be built to build templates for GP records and any CRM entity.

All in all, I'm actually excited to see where this integration goes. Integration packages from companies like Scribe and Nolan still have a leg up on this integration solution. But Microsoft is offering to allow it to customize it as necessary for any given solution. Scribe provides adapters that do a catch all and those adapters typically are pretty solid. But if you come across any issues with an adapter it has to go through development modifications within Scribe to get a fix. Again, Scribe is pretty good about getting those fixes out but your integration suddenly becomes subject to another company's timeline, and that timeline may or may not match your timeline for the integration being set up. On the other hand, no coding is required from products like Scribe to connect up to other applications, whereas Microsoft's solution will require A LOT of development.

So, how do you get the adapter you ask? Well, you must place an order through Microsoft via PartnerSource. And you must be a Registered Dynamics GP Partner. They want to know who is using it so that they can release any updates/fixes to people who have it installed. Hey, if I had an out of the box integration and 2 months after release I realized that if under a certain condition my tool wiped out all customer numbers, or credit terms, or something very scary that could happen to an accounting system, I would want to push those out as fast as I could as well so that I wasn't sued for screwing up an entire business.

My jury is still out on where this integration will fall within the integration competition market but it's peaked my interest and is definitely worth checking out. Free is free, and even though only out of the box fields can be used out of the box, most people who want to integrate these systems use the name field, the address fields, credit hold, terms, etc.

Currently this version only supports US English language installations. Just be aware of that.

For some more information on this you can check out Microsoft's Sales and Marketing collateral on PartnerSource or CustomerSource at the following locations:

PartnerSource:
https://mbs.microsoft.com/partnersource/partneressentials/partnerreadiness/resourcing/MDCRMGPAdapter

CustomerSource:
https://mbs.microsoft.com/customersource/worldwide/us/productinformation/factsheets/MDCRMGPAdapter

David Fronk
Dynamic Methods Inc.

Monday, October 05, 2009

Sure, anyone can Install MSCRM but...

I've come across a number of, let's call them, not so stellar implementations and helped turn them around for the better. Some of the more interesting implementations I've come across are when no outside help is sought, even though everyone in the company knows full well that no one knows the first thing about Microsoft CRM.

The IT guys install it (usually rather well) and then tell whatever department that demanded it to just run with it because IT installed it and they're done with it.

The requesting department typically doesn't have much technical expertise so they try to rely on the IT department to help them out and there are varying degrees in which IT responds to that request.

Worst case, some remote sales rep is given the task of setting up the system...but still hit his/her numbers, so it gets done "in his/her spare time."

Better case, someone in IT helps to champion the initiative and drives the requirements for the software. One problem that does eventually arise from this is who is the true owner of the application. IT says that it's the given department's application so it's their's. But the department using it says that IT set it up so it should really be their's.

In any case, someone who isn't sure of the full potential or even minimal potential of the software is left to implement this application. There are some implementations like this that go fairly well, but for the most part then end users are not very happy with the end result and fight having to use some crappy system that barely does what they want it to.

This is where the value of a good CRM implementation team/resource makes a world of difference. Whether it be to just train the person or department implementating the application; to bringing someone on to take the implementation by the horns and make it work right. And this is true of any CRM system, not just Microsoft CRM. The challenges that arise include, business processes, the ability to see where processes can be improved upon, streamlined and automated; departmental hand-0ffs, and helping departments know when the ball truly is in their court; technical, translating processes into a program that can actually be used by end users; and training, both administrators and end users. That's just a high level, but in a nut shell, that's what it takes to get a CRM system implemented.

Any CRM system is becoming more and more crucial to businesses these days in order to keep up with customer demand and staying on top of customers in real time. And a bad implementation will leave a bad taste in everyone's mouth, especially for a specific piece of software. So, from an implementor's stand point, please, everyone, do yourself a favor and take the time to implement your CRM system correctly. And for those of us that implement, please take the time necessary to implement your solution correctly because in my mind, the success of the company is directly tied to the success of your implementation.

David Fronk
Dynamic Methods Inc.

Friday, September 25, 2009

Checking the size of your CRM tables

I'm sure this is posted a few other places, so I definitely cannot take the credit for writing this script, but this is a great way to see what entities in CRM are taking up the most space. If space ever becomes an issue, or you're just looking to clean your data a bit and make querying your data a little faster (due to less data to be sifted through), this is a good way to find where you should focus your attention.

Run this SQL script against the Organization data base (OrgName_MSCRM):

SELECT
sys.schemas.[name] AS [Schema],
sys.tables.name AS [Table],
COALESCE([Row Count].[Count], 0) AS [Rows],COALESCE(8192 * [Data Pages].[Count],0) AS [Data Bytes],
COALESCE(8192 * [Index Pages].[Count],0) AS [Index Bytes]
FROM sys.tables
INNER JOIN sys.schemas ON sys.schemas.schema_id = sys.tables.schema_id
LEFT OUTER JOIN (SELECTobject_id,
SUM(rows) AS [Count]
FROM sys.partitions
WHERE index_id < 2
GROUP BY object_id) AS [Row Count] ON [Row Count].object_id = sys.tables.object_id
LEFT OUTER JOIN (SELECTsys.indexes.object_id,
SUM(CASE WHEN a.type <> 1
THEN a.used_pages
WHEN p.index_id < 2
THEN a.data_pages
ELSE 0 END) AS [Count]
FROM sys.indexes
INNER JOIN sys.partitions AS p
ON p.object_id = sys.indexes.object_id
AND p.index_id = sys.indexes.index_id
INNER JOIN sys.allocation_units AS a ON a.container_id = p.partition_id
GROUP BY sys.indexes.object_id) AS [Data Pages]
ON [Data Pages].object_id = sys.tables.object_id
LEFT OUTER JOIN (SELECTsys.indexes.object_id,
SUM(a.used_pages - CASE
WHEN a.type <> 1
THEN a.used_pages
WHEN p.index_id < 2
THEN a.data_pages
ELSE 0 END) AS [Count]
FROM sys.indexes
INNER JOIN sys.partitions AS p
ON p.object_id = sys.indexes.object_id
AND p.index_id = sys.indexes.index_id
INNER JOIN sys.allocation_units AS a ON a.container_id = p.partition_id
GROUP BY sys.indexes.object_id) AS [Index Pages]
ON [Index Pages].object_id = sys.tables.object_id
ORDER BY sys.tables.[name]

Hope this comes in handy to someone else.

David Fronk
Dynamic Methods Inc.

Friday, September 18, 2009

SiteMap Privilege Tag

At times there are users who need to read data from entities but those same users should never really see the full list of items of that entity in a place where they could take action against any of the items.

For example, an entity called "Locations" exists in CRM. Users will need to have the ability to view these Locations in order to enter a Location on a related object form, perhaps an Account. As an administrator you would like to have the list available to you so that you can add to or modify the list for the users. It could be placed in the Settings area and sometimes that is enough to keep people away from the list. But just to be safe you want to guarantee that users cannot do anything to the list.

This is where SiteMap Privilege tags come in. Within each SubArea tag a Privilege tag can be added. When a Privilege tag is applied, CRM will check on the main page load what privileges the user has to see if that user should be able to see the item. If the user does not have rights, then the item is not shown, if the user does have rights then the item is shown.

So, following our example from above the following could be inside the SiteMap:

<SubArea Id="new_location " Entity="new_location">
<Privilege Entity="new_location" Privilege="Write" />
</SubArea>

By setting the privilege to "Write" only those users that have the write privilege will be able to view the entity from the main CRM page. Multiple privileges may be used as well. Here are the possible values from the SDK:

All
AllowQuickCampaign
Append
AppendTo
Assign
Create
Delete
Read
Share
Write

Here's an example with multiple privileges:

<SubArea Id="new_location " Entity="new_location">
<Privilege Entity="new_location" Privilege="Read,Write,Share" />
</SubArea>

And finally, get creative. Just because the area is for an entity doesn't mean that the privilege has to be for the same entity. Perhaps the Location entity should only show up to users who have rights to write to the Knowledge Base. The following would be completely legit as well:

<SubArea Id="new_location " Entity="new_location">
<Privilege Entity="kbarticle" Privilege="Read,Write" />
</SubArea>

Now your main CRM page can be much more dynamic depending on who you are.

David Fronk
Dynamic Methods Inc.

Monday, September 14, 2009

Managing the AsyncOperationBase table entries

Since Update Rollup 3 a new function has been available but most likely not very widely used. That is the function of AsyncRemoveCompletedWorkflows. There is a Microsoft KB article on this that you can read here. But this function makes it so that as soon as a workflow (asynchronous job) is completed it is then marked for deletion.

This hotfix is proactive only. Therefore, when the hotfix is installed and activated, only new workflow records are deleted automatically. If the AsyncOperationBase and WorkflowLogBase tables are already large because of these workflow records, you must perform a cleanup of these tables by using the Microsoft SQL Server cleanup script that is included in the following Microsoft Knowledge Base article:
968520 (http://support.microsoft.com/kb/968520/ ) Performance is slow if the AsyncOperationBase table becomes too large in Microsoft Dynamics CRM 4.0 (from KB article 968755).

I have had some clients not manage this table very well and it made their system a bit slower or just waste data space. One client had over 3 million rows in this table and their Company_MSCRM database was over 15GB. I cleaned out the table and brought the database size down to 1.4GB. That's a lot of space being wasted. If you want the logs, then it's not wasted space but I doubt that every row of that table needs to be saved, so figure out what workflow types you need and keep those and clear out the rest.

Another great blog regarding this issue can be found here. Ben goes into a lot more depth and really talks through some great ways to manage your DB, especially the AsyncOperationBase table.

Hope this is helpful to others.

David Fronk
Dynamic Methods Inc.

Friday, September 04, 2009

Scribe MVP



Scribe Software has just announced their MVP program and honored me with being invited and accepted into their MVP community.

Scribe Most Valuable Professionals represent the most experienced and skilled Scribe users from among our over 800 partners, 10,000 customers and related software vendors. Scribe MVP’s are invited to join the program based on their skills, experience and contribution to the Scribe OpenMind community. For details on the Scribe MVP program click here.

As a note, the current 13 MVP's (as far as I am aware) were all invited/nominated by Scribe employees and the technical team. Don't quote me on that but since they state in their "How to become an MVP" document that you are either "nominated by someone from Scribe, someone else, or yourself", no one other than Scribe knew this was coming. Meaning the invites could only have come from the people within their company. Which speaks to the expertise and involvement of these initial MVP's with Scribe's software and the team behind it. To see the full listing of Scribe MVP's click here.

And if you are unfamiliar with Scribe's services you should definitely check out their website. For data imports, data movement, and system integrations Scribe has a very robust platform and capability to connect and push/pull data from almost any data source. Their library of application adapters is growing and they have found a good niche in the Microsoft Dynamics arena. Did anyone else notice that all of the MVP's are from the Microsoft Dynamics CRM realm? Microsoft CRM typically takes companies from an old CRM system, or Excel Sheets, Outlook contacts, or any other random place that people have decided to track information regarding customers or something that makes up the X in their new XRM solution. Scribe bridges that gap by giving visibility to data and mapping data with custom logic so that the data can be imported correctly and even have some clean up done on the way into the new system.

My congradulations to all of the other Scribe MVP's and thanks to Scribe and their team for this honor.

David Fronk
Dynamic Methods Inc.

Saturday, August 29, 2009

Rollup 6 is now available

Rollup 6 is a cumulative set of updates so if you haven't applied any rollups yet this should get you all taken care of.

Download Rollup 6 here.

David Fronk
Dynamic Methods Inc.

Friday, August 21, 2009

Using Fiddler to troubleshoot webpage errors

There are cases where I get the dreaded error message telling me:


"An error occured. Try this action again. If the problems continues, check the Microsoft Dynamics CRM Community for solutions or contact your organization's Microsoft Dynamics CRM Administrator. Finally, you can contact Microsoft Support."


When there are no errors in the server Event Log usually you have to resort to running a trace and then sifting through the huge text file to find the error. However, Fiddler can give you the error without having to be on the server and without having to sift through huge text files for one line of an error message.



Start up Fiddler, reproduce the error and then I typically look at the timeline, that shows a big error symbol. Double click on that symbol and you'll see the error you couldn't otherwise see.




Something rather simple but can make troubleshooting that much faster.

David Fronk
Dynamic Methods Inc.

Friday, August 14, 2009

Expose Associate and Disassociate SDK Messages

I had a need to run plugins off of the Associate and Disassociate of a many to many relationship and quickly found out that those triggers aren't exposed. So, I did some poking around and found from Aaron Elder an unsupported hack to enable them. You basically change a couple of zero's to one's and then the triggers are exposed in the Plugin Registration tool and off you go. Here's Aaron's original post if you want to check it out. And here's another post from a Microsoft rep talking about this very topic.

Here's the SQL query that he wrote and posted for everyone to use:


-- ============================================================================-- Enable Associate and Disassociate Plug-in Events Script v1.0-- ------------------------------------------------------------------------------ (c) 2009 Aaron Elder-- ============================================================================-- DISCLAIMER:-- This script is provided "AS IS" with no warranties, and confers no rights.-- ============================================================================-- While this is obviously "unsupported", I think the fact that these events-- are not available is a bug and hopefully it will be fixed in a rollup.-- ============================================================================USE AscentiumCrmDev_MSCRMGO-- Find the deployments SDK Filter ID for the-- Associate and Disassociate Entity SDK MessagesDECLARE @DisassociateEntitiesFilterId uniqueidentifierDECLARE @AssociateEntitiesFilterId uniqueidentifierSET @DisassociateEntitiesFilterId = (SELECT SdkMessageId FROM SdkMessageBase WHERE [Name] = 'DisassociateEntities')SET @AssociateEntitiesFilterId = (SELECT SdkMessageId FROM SdkMessageBase WHERE [Name] = 'AssociateEntities')-- Enable the Associate and Disassociate Filters to be valid for custom processing-- Custom Processing means "you register plug-ins against it"-- Note: We only do this for the "generic" (OTC == 0) case, just to be saferUPDATE SdkMessageFilterBase SET IsCustomProcessingStepAllowed = 1
WHERE SdkMessageId = @DisassociateEntitiesFilterId AND PrimaryObjectTypeCode = 0

UPDATE SdkMessageFilterBase SET IsCustomProcessingStepAllowed = 1
WHERE SdkMessageId = @AssociateEntitiesFilterId AND PrimaryObjectTypeCode = 0

What I am going to add is the method to get the ID's from within your plugin. These messages don't use any image information so don't even register images for them. Just the message, entity name and the rest you can leave default.

Here's the code to get the ID's:

stringprimaryEntityid="";
stringsecondaryEntityid="";
switch(context.MessageName)
{
case"AssociateEntities":
if(context.InputParameters.Properties.Contains("Moniker1"))
{
associatedEntity1=(Moniker)context.InputParameters.Properties["Moniker1"];
primaryEntityid=associatedEntity1.Id.ToString();
}
if(context.InputParameters.Properties.Contains("Moniker2"))
{
associatedEntity2=(Moniker)context.InputParameters.Properties["Moniker2"];
secondaryEntityid=associatedEntity2.Id.ToString();
}
if(context.InputParameters.Properties.Contains("RelationshipName"))
{
relationshipname=context.InputParameters.Properties["RelationshipName"].ToString();
}
break;
case"DisassociateEntities":

if(context.InputParameters.Properties.Contains("Moniker1"))
{
associatedEntity1=(Moniker)context.InputParameters.Properties["Moniker1"];
primaryEntityid=associatedEntity1.Id.ToString();
}
if(context.InputParameters.Properties.Contains("Moniker2"))
{
associatedEntity2=(Moniker)context.InputParameters.Properties["Moniker2"];
secondaryEntityid=associatedEntity2.Id.ToString();
}
if(context.InputParameters.Properties.Contains("RelationshipName"))
{
relationshipname=context.InputParameters.Properties["RelationshipName"].ToString();
}
break;
}



With this being unsupported you never know what is going to happen and you're not going to find any documentation. I found rather quickly that I was able to overload the Disassociate message without too much trouble. So, I ended up in changing my plugin to run asynchronously and that got it to work without error. The errors I saw were related to time out errors or the server not being available. The event logs will even show you the webpage that is being called when you run the plugin that does all of the webservice stuff.



Fiddle with it, play with it, enjoy the new freedom! And cross your fingers that these messages become supported in the next version.



David Fronk
Dynamic Methods Inc.

Friday, August 07, 2009

Modifying the number of items in the Outlook MRU

Philip Richardson posted about this a long time ago, but his post has actually not available any more. This is a great hack to make an end user's life a lot easier. By default the Outlook Most Recently Used (MRU) list is set to 7 items. A lot of users I talk to like it to be longer. And there is a simple registry modification that can be made to increase (or decrease) the length of the list.

Add the following reg key to the client machine that wants the length of the MRU changed:

HKEY_CURRENT_USER\Software\Microsoft\MSCRMClient
Value Name: MaxRegardingObjectListCount
Type: REG_DWORD

Then just put the number you want displayed (in Decimal format) and you're all set. You will most likely need to close your Outlook and reopen it for the changes to take effect.

Also, please note that you should know what you are doing when you are changing the registry (be careful), as if you modify it incorrectly it could make your application, or computer not work properly any more. Modifying the registry is done at your own risk.

But that should get you going. Enjoy,

David Fronk
Dynamic Methods Inc.

Friday, July 31, 2009

Setting Notes back to Auto Expand

There have been a few times where the Notes section and an IFrame end up on the same tab in CRM. And typically people want the IFrame to show whatever is being displayed to auto expand with the page so that the webpage, report or whatever it's displaying will look good. However, when you do that, it modifies the Notes so that they do not auto expand any more. And since you are not able to modify the Notes properties from the user interface, getting Notes to auto expand with the growth of the window has just become more difficult.

The way around this is to export the XML of the entity and modify the Note XML node. Here is what you Notes XML should look like:

<section showlabel="true" showbar="true" locklevel="1" id="{B798FA27-F9FC-4580-988C-0BA75C444488}" IsUserDefined="0" height="auto" labelwidth="115">
<labels>
<label description="Notes" languagecode="1033" />
</labels>
<rows>
<row>
<cell colspan="2" showlabel="false" rowspan="5" auto="true" id="{8f4963e9-b4cb-4713-b370-62070594185b}">
<labels>
<label description="Note Text" languagecode="1033" />
</labels>
<control id="notescontrol" classid="{06375649-c143-495e-a496-c962e5b4488e}" />
</cell>
</row>
<row />
<row />
<row />
<row height="auto" />
</rows>
</section>

The important points to take away are the height = "auto", auto="true" and the rowspan="5" options. For whatever reason if I didn't set the rowspan equal to 5 the auto growth wouldn't work.

Set the XML right, reimport the XML, publish and you're Notes will be fixed.

David Fronk
Dynamic Methods Inc.

Friday, July 24, 2009

DM Convergence - August 5th Microsoft Irvine Office

If you haven't already heard Dynamic Methods is holding it's own Convergence for anyone interested in learning more about Microsoft Dynamics CRM and GP. You can click here to register to attend.

The event will be held at:

Microsoft Corporation
Three Park Plaza
Suite 1600
Irvine, CA 92614
USA

Here's what the agenda looks like:

Agenda: 8:30 AM - Registration and Welcome9:00 AM - Kickoff and Introduction9:15 AM - Keynote speaker - Andrea Edwards from Franklin Covey: Business at the Speed of Trust
10:10 AM - Microsoft Roadmap - Michael Strand
10:30 AM - GP & CRM Highlights11:00 PM - Training and Breakout Sessions
GP - 50 Tips and Tricks
SharePoint - Business Workflow
CRM - Advanced Find and Reporting Benefits
CRM - CRM as an XRM System
12:00 PM - Lunch
1:00 PM - Training and Breakout Sessions
GP - 10.0 Enhancements and 3rd Party Tools
GP - Report ing SRS, Excel Link, and SmartList Builder
CRM - Tips and Tricks
CRM - Accelerators and DM Products
2:45 PM - Training and Breakout Sessions
GP - Business Portal
GP - FRx Tips and Tricks
CRM - Workflow and Sales Force Automation
CRM - Power of Scripting
4:30 PM - Closing

Registration is $99 ($49 if you register before 7/27/09).

Hope to see you there!

David Fronk
Dynamic Methods Inc.

Friday, July 17, 2009

Dynamic Methods attains Scribe Elite

Dynamic Methods has recently entered the small circle of Scribe Elite Partners. Having strong Microsoft Dynamics CRM and GP practices, along with knowing the integration between the two has helped Dynamic Methods to achieve this title. With that at the core use of Scribe as well as data migrations from numerous systems and integrations with other current and legacy systems makes the use of Scribe invaluable to Dynamic Methods and its customers.

Scribe Software Corporation provides cost-effective, no-coding solutions that can be used as the only tool businesses need to integrate virIualty any application, data source or Software as a Service (SaaS) platform. Scribe solutions are simple to configure and provide ease or modification as business processes change.

If you have not heard about or used Scribe check out their homepage. Dynamic Methods isn't on the Partner's page yet but that should be fixed in the near future.

David Fronk
Dynamic Methods Inc.

Friday, July 10, 2009

Custom Entity versus Out of the Box Entity

MSCRM is great in that it gives administrators the ability to add custom entites to track anything and everything they want. MSCRM really gives a good solid backbone to not just a CRM system but an XRM system. But making too many entities can become VERY combersome for end users. At the same time an administrator has to decide what should be tracked and where the best place to track it really is. There certainly are plenty of times where an out of the box Order doesn't fit the needs of a client but they still need to user Orders. So, creating a custom object called Order isn't something unheard of. However, by choosing to go this route I lose a lot of out of the box functionality. That may be ok, and it may even be the reason the out of the box entity wasn't used. My hope is to help lay out some of the factors that play into choosing to use a custom entity or an out of the box entity.

1. Accounts and Contacts - Typically everyone uses these, but I've seen cases where one or the other didn't fit the companies business model. The more a system moves to XRM the less important a contact may become. But know this if you opt to use something in place of one of these two objects you lose sync with Outlook Contacts, which is a sync to your phone. Mailings and email blasts have been built around these objects where you can't do the same thing with a custom object. And if you are going to use Marketing Lists you had better use one of these because you can't have a Marketing List against a custom object.

2. Leads - The main thing lost here is the automatic push to Accounts, Contacts and Opportunities. This definitely can be reproduced and done whatever way necessary through custom code, but essentially you are having to redo something that you already had. Marketing Lists and email functionality also are special around this object in that custom objects don't get to do what you could with a Lead.

3. Opportunities - Opportunities have special statuses, and SDK triggers, around the winning or losing of a given Opportunity. You can mimic the same functionality, you just have to build in extra logic that MS already put in. If you are using Opportunity Products they automatically have math done for you that rolls up to the Opportunity record (total revenue based off of product pricing). Not to mention the pricing that's built into the Opportunity Products. One pro for the custom object is that there are fields on here that you can remove or tweak and you won't have any idea that you are effecting background code. Have you ever set the Topic to not be required? If you do then you'll definitely see Opportunities without a Topic appear, and when someone tries to set the Opportunity to Won or Lost, you won't be able to because background code needs something there. Sometimes the Opportunity is overkill but you just have to know what you're getting into.

4. Quotes, Orders, Invoices - I put all of these together because they are so close in everything they do. If you want to integrate to an accounting system any out of the box integration is going to integrate these objects with the accounting system. So, going custom means custom integration. The products under each object is exactly the same as Opportunities, so be aware of that. And the other thing lost is the out of the box flow from Opportunity to Quote, to Order, to Invoice.

5. Products - There is a very robust and complex Product Catalog that is built into CRM that handles pricing, UoM, Discounts, etc. If it's overkill for your company then custom is the way to go. But you lose a lot of pricing capabilities that have to be redone if you don't use the Product.

6. Cases - You lose the use of Queues if you replace Cases. There is also the code that closes the Case and makes the Close Case activity, but there are other ways to accomplish the same thing.

7. Contracts - If you need detailed product itemized Contracts you're missing out. Contracts do a lot at a very granular level to help in managing whether things are under contract or not. However, if you don't care about having a Contract that could have 8 items that could all have their warranty/contract end on a different date, then I'd almost suggest using a custom object, it's just cleaner. The other thing you lose with not using Contracts is the automatic daily check to see if something is expired. CRM automatically moves Contract statuses according to dates, that would have to be rebuilt if a custom object were used.

8. Custom Objects - The pro about custom objects is that they are vanilla for you and ready for you to do whatever you want to them. The downside is that you have to manually build out each process, flow, or custom action. But that can be seen as an upside just as well. Custom Objects don't get the same kind of email and marketing capabilities but out side of these things, Custom Objects work really well and can easily replace out of the box objects if necessary.

I think that's good for now. Let me know your thoughts and if there's any object I missed that you're debating between either using out of the box or custom, let me know and I'll add it to the list.

David Fronk
Dynamic Methods Inc.

Thursday, July 02, 2009

Rollup 5 is now available

Rollup 5 is now available for download. Here's the link.

Note that this is a cumulative update that includes Rollups 1, 2, 3, and 4. Some of the highlights on the fixes include

1. Improvements to load speeds of forms with a lot different types of fields
2. The Microsoft Dynamics CRM 4.0 client for Outlook does not load the toolbar
3. Microsoft Outlook crashes when you enable the "Track in CRM" feature for a delegate contact after you install Update Rollup 4 for Microsoft Dynamics CRM 4.0
4. Error message if the "OnChange()" event is enabled for a lookup field in a entity form and if this field is changed after a "Duplicates detected" message occurs in Microsoft Dynamics CRM 4.0: "Stack overflow at line: 0"

And more. For more information check the full details page here.

David Fronk
Dynamic Methods Inc.

Monday, June 29, 2009

Choosing what records to Sync Offline

Finding the location of how to modify what records are actually synchronized between a user’s personal Outlook and CRM isn’t always apparent to the average user. The good news is that once you find it, modifying it is very easy and just like the Advanced Find tool. With this post I hope to help people find this setting and see the power of managing your own records for offline synchronization.

First, if you do not have the ability to “Go Offline” then you will only be able to modify your synchronization with contacts (without going offline, activities are the only other items that sync with your install). If you have the Outlook client that allows you to “Go Offline” then you have the full capability to modify each record type according to your security role.

Here’s where to find the setting:

From within Outlook, click on the “CRM” Menu, and then choose “Modify Local Data Group.”


A new window will appear showing all of your active data groups. You can create a new group, delete a group, or deactivate any of the groups shown in your window.
To edit a data group double click on the group. This will bring up an Advanced Find window. Modify the query and whatever is returned in the query is what you will sync to your personal computer once saved. By adding date ranges, records owned by certain users, or other options will expand or limit what is actually synchronized.


To synchronize all California Contacts that I owned, I would use the query below:


If you need to reset back to the default “My Contacts” Group, use the option under “More Actions”.


You can rename a group.


You are only allowed to have one data group for each record type. It doesn’t matter if it is active. If you think you don’t have a data group, it’s probably inactive. (The only record type you can have in your local data groups are contacts, unless you have the offline client.)


Also, bear in mind that you are only allowed one data group per record type.


To delete a group, highlight and click the delete button. I personally don’t recommend doing this; I recommend deactivating and creating your own.


To deactivate a data group, just highlight the group and click on the red square within a circle button. This makes is so that you keep any filter but don’t apply that filter’s logic when synchronizing.


To activate an inactive group, go to the “Inactive Data Groups” tab, highlight the group to activate, and click on the arrow within the circle.

Remember, you need to have your contacts synching or it doesn’t matter what you do with your local data group.
Also, be sure to check the box to update the outlook company field with the CRM Parent Account Name.

David Fronk
Dynamic Methods Inc.

Friday, June 19, 2009

Cool CRM 4.0 tools that may not be generally known

I have come across a number of different tools, some shown to me by Microsoft reps, others by other partners, some by clients and still some (more typically) by my coworkers. I always find it funny when I have a tool that I've been using for a really long time but I never told my coworkers about (or that situation in reverse). All of a sudden life is so much easier. So, here's a list of some tools that I have found and use to make my life easier.

1. Microsoft Dynamics CRM 4.0 Demonstration Tools
The Microsoft Dynamics CRM 4.0 Demonstration Tools provide a simple user interface that allows you to easily enter and edit data to populate or modify your instance of Microsoft Dynamics CRM. It also allows you to load and store your data in XML format, so that you can reuse your data in the future.
This is one that one of my sales team members showed me how it helped him with his demos. I told him it would be great for implementation too.

2. MSCRM Plugin Registration Tool
PluginRegistration tool is enhanced version of the tool that is published with Microsoft Dynamics CRM 4.0 SDK (if you're using plugins I hope you know about this one, if you don't, it will change your life)

3. Microsoft CRM Support Tools
Things like the diagnostic tool for tracing and the email connector logger.

4. Microsoft Dynamics 4.0 Performance Toolkit
Helps to stress test an environment. A lot of set up but you get a lot of good data.

5. Microsoft Dynamics Internet Facing Deployment Configuration Tool
You could set up IFD manually, but why would you do that when this tool makes it so easy?

6. Microsoft Dynamics CRM Accelerators
I've blogged about these before, but these essentially are free "modules", external portals, or reports that help make CRM be more effective to you and your organization. Codeplex has a number of other CRM tools that you can easily search for and try out.

7. Microsoft Dynamics CRM 4.0 Logical Database Diagram
Maps whatever entities you choose in Visio. If you keep your select entities to only a few, this can be very useful. But don't expect to use this for your entire system. This maps out EVERY relationship on any specified entity (activities, notes, users, imports, plus all the regular ones you want).

8. Stunnware's FetchXML Wizard
Great for scripting. Stunnware has lots of other great tools, so poke around and see what you can find.

There are lots more. If you have any that you really like, post it in a comment.

David Fronk
Dynamic Methods Inc.

Saturday, June 13, 2009

Money Fields and Multicurrency

I was adding fields to an existing entity, and one field I accidentally made a money field rather than a float. So, I went back and deleted the field and recreated it as a float. No big deal. Well, it is a big deal if you have ever had multiple currencies in your system. All of a sudden, users were getting the infamous "Object reference not set to the instance of an object." error. I looked on the server and found that the error was coming from the following plugin:

Microsoft.Crm.ObjectModel.MultiCurrencyPlugin

That wasn't any plugin I had ever put on the server so I was surprised to see it. As it turns out, once a money field is added to an entity within a system that has ever utilized multiple currencies, there must ALWAYS be a money field on the form. Otherwise you get the above error. I tried deleting the extra currencies in the system to see if that would fix the problem; it didn't. I guess something changes once you add more than one currency that doesn't change back. I ended up in having to add a money field to the entity. I didn't put it on the form, and I'll never use any data from it, it's just there to prevent that error from popping up. Awesome.

Hopefully this helps someone else.

David Fronk
Dynamic Methods Inc.

Friday, June 05, 2009

Annoying Outlook Pop-up windows

I have seen some users of the Outlook client be pestered by pop-ups every time they open any CRM window from within Outlook. The message they get is:



One fix that was found for this issue is to go to the Internet Option Settings in Internet Explorer and turn "Protected Mode" OFF on the INTERNET ZONE under the Security tab. You will be warned that your computer will be at risk of getting something bad the easies solution to that is responsible web browsing. For whatever reason doing this on the Intranet or Trusted Sites zones didn't fix the problem (even though the CRM site was put in each zone).
Perhaps there are other better ways out there but this is one that works.
David Fronk
Dynamic Methods Inc.

Friday, May 29, 2009

Setting the Full name format

I'm not sure how many administrators are aware of this but in the Settings --> Administration --> System Settings area of CRM there is an option to set the "full-name format." The most common are typically "FirstName LastName" or "LastName, FirstName". You have many more options here available to you.

However, please note that when you change this setting it effects any records created after the change, it DOES NOT update all of the existing records in the system. I once made the change after a client had been using the system for nearly a year and they then had a mix of contacts whose names appeared in different formats. It's really weird to look through a list of contacts where some are formatted one way and others are formatted another way.

So, if you are going to make this change, make it before you start putting data into your CRM system. Otherwise, if you have to make the change and you already have data in the system then you could perform an UNSUPPORTED update through SQL to the fullname field. It's simple and typically it doesn't take long to run (it just depends on the number of records you have). But it works and that's the import thing.

But now you know.

David Fronk
Dynamic Methods Inc.

Friday, May 22, 2009

The CRM_CalendarType parameter is missing a value

I've seen a number of posts that reference this issue and typically most people suggest to do the following:

1. Log on to the Microsoft Dynamics CRM 4.0 Web client as an administrator.
2. Click Settings , click Administration , and then click Security Roles .
3. Double-click the security role that you use.
4. On the Business Management tab, set the Read privilege of the User Settings entity at least to the Business Unit level.
5. Click Save and Close.
6. try to run the report

I recently saw an issue where this didn't work. What had caused the error was the uninstall of the CRM SSRS Data Connector. This uninstall did something to the SSRS Data Source that all of the CRM reports were using. This was confirmed by changing the way the authentication was configured. If a user was hardcoded into the Data Connector then everything would work, but all reports were run as that user. If the Data Connect was set to Windows Credentials then the CRM_CalendarType error would appear (that parameter could vary). Then if "Credentials Supplied by the User running the report" was used, an unauthorized error would appear.

What was found was that NTML had been turned off both the CRM and SSRS web sites. But turning NTML back on everything began to work again.

David Fronk
Dynamic Methods Inc.

Friday, May 15, 2009

Share Reassigned Records with Original Owner

There is a rather obscure system setting that gets overlooked in a vast majority of CRM implementations, it relates to sharing records with the original owner.

In the Settings --> Administration --> System Settings window, right on the General Tab. There is a section marked as "Set whether reassigned records are shared with the original owner". You can then choose whether or not to share reassigned records with the original owner.

What this does is any time you reassign a record it will share the record with the previous owner. Not just the original creator, but every owner after. So, this could be a great way for people outside of the sales department to follow up on leads that they have passed onto the sales team. See how deals they provided the company have panned out. Or cases created by the sales team can be viewed again to see how the customer support team handled a situation that a sales rep reported.

On the other hand, this could be a potential security nightmare for some companies where users should only see their own records. So, any time a sales person switches territories, or customer service reps who should only be servicing specific customers could potentially see more than is intended.

The good news is that fixing this is as simple as changing this option in the System Settings from "Yes" to "No". This will not undo anything that is already shared, but it will stop the system from sharing anything more if you don't want it to.

Knowing how data can be viewed helps when there is a "security breach" and suddenly people can see more than they are supposed to see.

David Fronk
Dynamic Methods Inc.

Friday, May 08, 2009

Sharing Records Automatically

From the number of implementations that I've done I believe sharing to be greatly underutilized. Part of the reason is that it is rather clicky in order to set up someone with the rights to see a record. It's hidden in the "More Actions" menu and then you can share with a user or a team. Teams help to facilitate mass sharing but still, most users and typical CRM administrators don't even know that teams exist.

Most implementations just open things up at the business unit level, or even the global level (depending on the size of the company) and don't even worry about sharing. However, there are times when certain information can be sensitive and necessary to restrict access to. Typically these things can be activities, opportunities, cases, services billed, hours worked, etc.

For instance, suppose sales reps aren't allowed to see support cases but are allowed to see the accounts that they manage. Any good account manager would want to know what support issues their account has been having before engaging on a new business proposal, so obviously the sales rep should get to see the cases related to the account.

All that is required is a couple of plugins at two main points and upon creation of a case and reassignment of an account. Whenever a case is created, get the account manager of the account on the case and share the case with that user. If the account gets reassigned, remove the share from the old account manager and add rights to the new account manager. Now with simple logic you can make data more accessible to those who should see the data without them having to do anything more than their regular job.

One side note, be aware that the more items there are under a parent record the longer the reassignments of records will take. For instance, if I reassign an account with 50 cases that's going to take a lot longer to complete the reassignment than it would if there were 5 cases, or even none. Just keep that in mind as you develop your sharing solution.

Pretty simple, and the SDK has some great examples on how to do this. Look up "AccessRights Enumeration", "GrantAccess Message", and "RevokeAccess Message" in the SDK and you should have everything you need.

Here's a quick example on how to share and give all rights to a user:

SecurityPrincipal principal = new
SecurityPrincipal();
principal.Type = SecurityPrincipalType.User;
principal.PrincipalId = new
Guid("7B222F98-F48A-4AED-9D09-77A19CB6EE82");
PrincipalAccess access = new
PrincipalAccess();
access.Principal = principal;
access.AccessMask = AccessRights.ReadAccess;

TargetOwnedDynamic target = new
TargetOwnedDynamic();
target.EntityId = new
Guid("6A92D3AE-A9C9-4E44-9FA6-F3D5643753C1");
target.EntityName = "incident";

GrantAccessRequest readGrant = new
GrantAccessRequest();
readGrant.PrincipalAccess = access;
readGrant.Target = target;
GrantAccessResponse readGranted = (GrantAccessResponse)crmService.Execute(readGrant);

access.AccessMask = AccessRights.WriteAccess;
readGrant.PrincipalAccess = access;
GrantAccessResponse writeGranted = (GrantAccessResponse)crmService.Execute(readGrant);

access.AccessMask = AccessRights.AppendAccess;
readGrant.PrincipalAccess = access;
GrantAccessResponse appendGranted = (GrantAccessResponse)crmService.Execute(readGrant);

access.AccessMask = AccessRights.AppendToAccess;
readGrant.PrincipalAccess = access;
GrantAccessResponse appendToGranted = (GrantAccessResponse)crmService.Execute(readGrant);

access.AccessMask = AccessRights.AssignAccess;
readGrant.PrincipalAccess = access;
GrantAccessResponse assignGranted = (GrantAccessResponse)crmService.Execute(readGrant);

access.AccessMask = AccessRights.DeleteAccess;
readGrant.PrincipalAccess = access;
GrantAccessResponse deleteGranted = (GrantAccessResponse)crmService.Execute(readGrant);

And here is an example on how to revoke access:

SecurityPrincipal principal = new
SecurityPrincipal();
principal.Type = SecurityPrincipalType.User;
principal.PrincipalId = new
Guid("7B222F98-F48A-4AED-9D09-77A19CB6EE82");
PrincipalAccess access = new
PrincipalAccess();
access.Principal = principal;
access.AccessMask = AccessRights.ReadAccess;

TargetOwnedDynamic target = new
TargetOwnedDynamic();
target.EntityId = new
Guid("6A92D3AE-A9C9-4E44-9FA6-F3D5643753C1");
target.EntityName = "incident";
GrantAccessRequest readGrant = new
GrantAccessRequest();
readGrant.PrincipalAccess = access;
readGrant.Target = target;
GrantAccessResponse readGranted = (GrantAccessResponse)crmService.Execute(readGrant);

Happy sharing!

David Fronk
Dynamic Methods Inc.

Friday, May 01, 2009

Open new Modal Window from onLoad

There are times where administrators and/or executives/managers want to alert users opening a given record about something important on a given record. If people need to be warned that they shouldn't call the contact because they are marked as "Do Not Call" or an Account is marked as being "On Hold". Those can typically be done through alerts. But if logic is needed off of related objects, such as only allowing 3 items per Order, or if a number of Cases have been opened within a given period of time, that's not as easy to do with JScript.

That means that you would need to take your logic to a webpage on the load of the given entity. But since you are opening another web page (through the window.open method) users would be able to click around it and ignore it, making the work of the web page useless.

If you use the window.showModalDialog method then you can change all that. A Modal Dialog requires users to take action on the newly opened window before they can get to the record they are trying to open. The method is very similar to the window.open method, allowing you to control the size of the page, what bars show (status, menu, etc) on the web page. Here's the code:


if(crmForm.ObjectId != null)
{
var url = "/ISV/Test/OrderDetailCheck.aspx?id=" + crmForm.ObjectId;
//window.open(url);
window.showModalDialog(url, "Order Detail Check","dialogWidth:200px;dialogHeight:150px;center:yes;status:no");
}

Just put this in the OnLoad of your entity and you now have a custom page that you can fully customize, modify and design that users must look at take action on before they can access a record.

David Fronk
Dynamic Methods Inc.

Friday, April 24, 2009

Shared Variable in JScript

An occasion came up where the value of a field needed to be masked but still allow the correct value to be saved to the database. Envision sensitive information like social security numbers, credit card numbers, etc. These are things that data entry people need to enter but not necessarily see the entire number after they enter it.

You could use another field to house the real information and hide that field on the form so no one can see it, but then you run the risk of having that information in another place unnecessarily. Also, if someone is going to this length to make sure users can't see this information they probably want to make sure that the data gets encrypted in the database so that users couldn't get the information from the grid any way.

So, to keep this more hidden and more secure you actually can use a variable between your methods on the same document. It's actually really easy, here's how:

In the OnLoad of the form write:

document.newvariable = 5;

Now in your OnChange or OnSave you can reference that variable the same way.

crmForm.all.new_securefield.DataValue = document.newvariable;

So, if you wanted to mask something:

In the OnLoad:
document.originalvalue = crmForm.all.new_securefield.DataValue;
crmForm.all.new_securefield.DataValue = "xxxxxxxx" + crmForm.all.new_securefield.DataValue.SubString(8, crmForm.all.new_securefield.DataValue.Length - 8);

And now in the OnSave:
//Hide the field so the real value doesn't appear just before the save
crmForm.all.new_securefield.style.visibility = 'hidden';
crmForm.all.new_securefield.DataValue = document.newvariable;

Simple but effective for keeping data secure on the form. I'm sure there are many more uses for global variables like this, this is just one way that it can be implemented.

David Fronk
Dynamic Methods Inc.

Thursday, April 16, 2009

Microsoft CRM Developer Toolkit

I'm probably late in getting this up but the MSCRM Developer Toolkit is now available at the following link:

http://code.msdn.microsoft.com/E2DevTkt

Be aware that you must be running Visual Studio 2008 and CRM 4.0 in order for this to work. Here are the highlights of what the toolkit offers from within Visual Studio:


1. View All CRM Entities - Displays a listing of CRM entities that are dynamically available from the CRM Explorer within Visual Studio 2008
2. Create and Update CRM Entities - Allows for creating new entities and updating existing entities from within the CRM Explorer experience
3. Create a Wrapper Class - Provides the ability to auto-generate wrapper classes for entities, which exposes the CRM entities and their corresponding attributes as classes and properties respectively to enable development of code to interact with the entities
4. Generate Plug-in Code - Enumerates the available Plug-ins for an entity and generates the code necessary to jumpstart the plug-in development process
5. Integrate the Build and Deploy Process - Simplifies the process of building and deploying a CRM solution
6. Deploy Across Multiple Servers - Assists in deployment and maintenance of Windows installer packages across multiple environments

Please be aware that in their documentation they actually do come out and say that this tool is UNSUPPORTED and is provided, AS IS. Not exactly sure why they would include that since this is put out by Microsoft but there you go. Use at your own risk.

David Fronk
Dynamic Methods Inc.

Monday, April 13, 2009

Changing Default SQL Port

In order to keep data more secure requests have come in to have SQL run on a different port. This helps to avoid typical SQL port scans and keep your database off of the "easy to target" list. Changing the database and having CRM work after the change is actually pretty simple.

Please note that this configuration change requires modifying of the registry and updating the MSCRM_Config database. Both of these actions are NOT SUPPORTED by MS Support. So, perform at your own risk.

Here's how it works:

1.Open SQL Server Configuration Manager


2. Choose your instance of SQL that you want to change the port on and open the "TCP/IP" Property.


3. A new window will open.


4. Click on the "IP Addresses" tab and scroll to the bottom. Under the "IPAll" section change the "TCP Port" to the port desired. Click Ok.


You will be told that the changes will not take effect until SQL services have been restarted. Restart the Services and you are all set for this step.

Next you will need to change three keys in the MSCRM hive of the registry on the CRM server:
1. configdb
2. database
3. metabase

Each of these keys will have a "Data Source" switch that has the name of the SQL server as the Data Source. In order to tell the connection to use the specified port you will need to add a comma "," and then the port. For example:

Provider=SQLOLEDB;Data Source=SQLSERVER,1234;Initial Catalog=CompanyName_MSCRM;Integrated Security=SSPI

Lastly, you will need to update the Organization table of the MSCRM_Config DB. Just like you updated the registry keys previously, the same thing will need to be done to the "ConnectionString" column of the Organization table. Run the following SQL scripts:

SELECT ConnectionString, Id from Organization

This will give you the current connection string being used. Copy and paste the value into your query page. Add the comma "," to the Data Source and then update the table.

UPDATE Organization
SET ConnectionString = 'Provider=SQLOLEDB;Data Source=SQLSERVER,1234;Initial Catalog=CompanyName_MSCRM;Integrated Security=SSPI'
where Id = '(put in the Organization Id from your select that you ran previously)'

And now, as long as your Window's Firewall is set up to allow traffic over the newly chosen port, you're all set. Watch out for those firewall rules as they can make a perfectly implemented configuration change all for not.

Enjoy your newly secured solution!

David Fronk
Dynamic Methods Inc.

Friday, April 03, 2009

Case Sensitive Searches in CRM

There have been a few instances that have come up where customers have requested the ability to make a certain field case sensitive. Typically this is for key fields, like foreign keys. But since the MSCRM database table collation is typically not set up for case sensitivity you don't get the option.

You can however set the collation at the column level and make just the field you want case sensitive.

Here are the steps:

1. Open Microsoft SQL Server Management Studio
2. Expand the <OrganizationName>_MSCRM
3. Pick the table you want (for example dbo.AccountBase) and expand the table
4. Expand the Columns folder
5. Right click on the column you want to set as being case sensitive
6. Choose Modify
7. In the right window panes make sure the field you want to change is highlighted
8. In the bottom pane of the right window (Column Properties) find the "Collation" property and click on the elipses in the right hand column to edit the property.
9. A new window will come up and you will see a checkbox for "Case Sensitive", check that box.
10. Click OK
11. Restart the SQL services
12. Just to be safe restart IIS

Now you're all set with a new case sensitive field.

Also, just to add the disclaimer. THIS IS NOT SUPPORTED by MS Support, so apply at your own risk. You have been warned. I have yet to see any issue arise from this, but my job is to make you aware.

David Fronk
Dynamic Methods Inc.

Friday, March 27, 2009

Viewing "Customizations" Area while Outlook Client is Open

I made mention to one of the Microsoft CRM Product Managers that the fact that I cannot access "Customizations" from the Outlook client, or the Web client when I have Outlook open seems silly to me. When the Outlook client first came out it was titled "The Sales for Outlook Client" and with that title not including "Customizations" made sense. But now the client has moved far from that title and this really shouldn't be an issue for end users.

The Product Manager looked at me in a confused way and said, "Why don't you just update the Site Map?" I couldn't believe that something so simple could solve my problem. Previously I've had users go to a separate URL, like the IP address, or I would set up another host header to work around this. But I tried this and this way is much better.

All you have to do is export the Site Map and find the XML tag "nav_syscust" under the "Settings" area tag and add:

Client = "All"

Save, import, publish and you're all set. Here's the full line:

<SubArea Id="nav_syscust" ResourceId="Homepage_SystemCustomization" Icon="/_imgs/area/18_syscust.gif" Url="/tools/systemcustomization/systemcustomization.aspx" Client="All" />

Enjoy,

David Fronk
Dynamic Methods Inc.

Tuesday, March 17, 2009

Convergence Summary

Convergence this year was held in the New Orleans Conference Center, which is rather large. Here's what Wikipedia has to say about it:

The New Orleans Morial Convention Center (formerly the Ernest N. Morial Convention Center) is convention center in New Orleans, Louisiana, United States. The lower end of building one is located 1,640 feet (500 m) upriver from Canal Street on the banks of the Mississippi River. It is named after former Mayor of New Orleans Ernest N. Morial. As of 2006, it has about 1.1 million square feet (102,000 m²) of exhibit space, covering almost 11 blocks, and over 3 million square feet (280,000 m²) of total space. The front of the main building is 1 kilometer long (for full article click here).

Microsoft had about two thirds of the Convention Center rented out so running from classes on one end of the first floor to the other end of the third floor took a fair amount of time to walk to.

I was able to sit in on a lot of user experience sessions with the Dynamics CRM team to discuss their thoughts on the future for the product. Unfortunately I am sworn to secrecy (signed NDA) about anything that was discussed but I did ask if I could share one or two specific things. Since anything and everything could still be changed there wouldn't be much point in me sharing much anyway. However, I can share that the team has heard the cries from the community and is working very hard to add functionality and improve other existing items. One of the specific things that the Outlook team is focusing on is increasing the RELIABILITY and STABILITY of the Outlook client. All of the issues that were mentioned the team had full knowledge of and was working on getting those things resolved. I must say that after sitting through those sessions (where the product team was raked over the coals) they were very coridial, professional, and understanding. One of the biggest things that I got out of these sessions was that I will submit my errors to Microsoft much more often now because I know there really are people reading them on the other end, I've met them and shook their hands.

That all being said, I'm going to try to bullet point out everything to make this a bit more readable/scannable for those just looking for highlights. So, here it goes. These are some of the highlights that I picked up from the show (not in any particular order):

1. If you haven't seen any of the CRM Accelerators, go check them out at codeplex.com

2. SQL 2010 is going to have a lot of great new enhancements one of which will be managing multi-terrabyte systems quickly

3. Performance Point will become a part of SQL and SharePoint (most likely pieces will go to each, with either minimal or no overlap between the two systems)

4. Microsoft's CRM to GP integration - great for out of the box integrations, any additional fields will have to be added by someone with "developer" type skills. Plugins and triggers will most likely have to be written. Interface looks clean but the extensibility doesn't appear to be as strong.

5. If you went to Convergence and do not own CRM you can sign up for CRM Online for $9.99/user for up to 20 users for 6 months. That's a steal.

6. CRM Developer Toolkit (available in April) - Visual Studio add-on. Looks solid, makes developing much easier by being able to see all objects, fields, etc within Visual Studio. This is code complete and documentation is all that is really being completed.

7. Don't look at MSCRM just as a CRM solution but an xRM solution. It's extensibility really makes it so that customers don't have to be your center, you can have whatever you want as the center of your Relationship Management system you want.

8. Newsfeed Accelerator - use workflow to augment your user's daily actions to further the data that is put into the system. Use a user's actions and workflow to populate you system to give a more full 360 degree view of what is going on in your CRM system and with the relationships between what you track in your system.


I don't do the show justice as there was a lot learned and gained from attending. For those in the Southern California Area, keep your eyes open for the Dynamic Methods Convergence (Titled "DM Convergence") where we will be putting on a similar but very focused event focusing on things from this year's Convergence specifically for Dynamics GP and CRM where we will have classes and give people the ability to "Ask the Experts" just about anything they want so we can help everyone along in whatever stage or scenario they are in. With Convergence having just finished we are looking into what content we want to present as well as when we will be holding it. Most likely we will be holding the event in May, so keep stay tuned for updates.

Also, this is specifically targeted at Southern California Dynamics GP and CRM users but that doesn't mean you can't come. If you're really interested stay tuned as I should be posting a method of registration or contact in the near future. We typically just have a 1 day event so the travel doesn't always justify the attendance.

David Fronk
Dynamic Methods

Friday, March 13, 2009

Quick Convergence Note

Convergence is almost over (only a half of a day left) and while I thought I was going to be able to put up a couple of posts a day I quickly found out that a lot of my time was spent running from one end of the New Orleans Converence Center to the other...this place is huge! I almost feel like I should have trained for speed walking before I came here :).

Convergence has been great so far, I've gotten to sit in a lot of User Experience Labs with the CRM development team, where they basically show us a preview of what they are considering for the next version of CRM and get the customer's and partner's feelings on the direction they have, or are considering. All in attendance of those sessions had to sign NDA's (Non-Discloures Agreements) so I'm not allowed to talk about the details of the labs.

I was able to attend a handful of other sessions and ask some questions to other CRM experts, including the support team, and I will be posting more once my walking/running marathon is over.

David Fronk
Dynamic Methods Inc.

Friday, March 06, 2009

On-Mouse-Over Custom Tool Tips

Ever want to give users more information into what they should enter into a field? You can either make the label of a given field really long, put a field in a section on it's own, and write the description out in the section title, or you could use scripts to override the tool tip of the field.

Here's the script:

var oPopup = window.createPopup();
var oPopupBody = oPopup.document.body;
oPopupBody.style.fontFamily = 'Tahoma';
oPopupBody.style.border = '1px solid black';

function My_OrgName_showRatingPopup ()
{
oPopupBody.innerHTML = "<div><table style='font-size:xx-small'>";
oPopupBody.innerHTML += "<tr><td><b></b></td><td> Custom Tool Tip Text Here</td></tr></table></div>";
var x_coord = -100;
var y_coord = 20;
var width = 350;
var height = 90;
var documentElement = event.srcElement;
oPopup.show(x_coord, y_coord, width, height, documentElement);
}
//Be sure to modify the field name here so that you attach your OnMouseOver event
//to the correct field. The "_c" indicates the label of the field.
crmForm.all.new_customfield_c.attachEvent('onmouseover', My_OrgName_showRatingPopup);

Now just hover over your field label and you'll see you new custom tooltip pop up.

David Fronk
Dynamic Methods Inc.

Friday, February 27, 2009

Questions for Convergence anyone?

I will be attending Convergence in New Orleans next month and I will be working hard to talk with as many of the experts as I can and getting as much info as I can from the sessions as I can. However, I've found that going to events like this is much more effective if I have some questions in mind to try to get answered. I have some questions of my own that I will be asking but Convergence but I thought it would beneficial to the community to see what you want to know about even though you may not be able to attend.

If anyone out there isn't attending but has a question that is general enough for the product, road map, etc I'd love to try to find out for you. I can't guarantee that I'll be able to get every question answered but I'll do my best to take your questions and post them with answers/responses direct from Microsoft. Also, I happen to leverage the Scribe tool a fair amount and I will be meeting with them so I will even take Scribe questions relating to migrating/integrating with MSCRM.

My goal is to post multiple times a day while I'm at Convergence so stay tuned during Convergence week for lots of updates from the Microsoft world.

David Fronk
Dynamic Methods Inc.

SRS 2008 (SQL 2008) Export to WORD

Just one more reason to upgrade SQL to 2008, SRS out of the box has the ability to export directly to Word. I've seen SRS render it's exports to PDF in funky ways and you're stuck with however SRS exports since you can't modify your PDF's. However, with the export to Word things are much cleaner and you can even tweak the document a bit before you send to PDF from Word.



Great out of the box functionality,

David Fronk
Dynamic Methods Inc.

Friday, February 20, 2009

Autofill Account from Contact (custom fields)

There are many times where I have come across requests to fill in fields automatically based on other fields in order to help cut down the time for data entry and also to help keep data integrity higher. One of the great ways to do this is to help in filling out "related" lookup fields. For instance, on an Opportunity a lot of companies can't always decide whether they want to see an Account or an Account in the Customer field. Or, management decides on Accounts and then the end users put Contacts in the Customer field because that's what makes sense to each role. However, this is a disaster for reports and getting the correct metrics at the end of a month, quarter, or year. A majority of the time it just makes more sense to show both Account and Contact fields on the Opportunity.

There is a script that can be used to help fill in one of the lookups for your end users. If you have them fill in the Contact field first you can figure out who that Contact works for by looking up their Parent Customer field. Sure, you could do this in a Plugin/Callout, but why do that when you can have the end user see it all filled out right in front of them? It makes a big difference to the end users. There are only a couple of lines that should have to be modified:

1. lookupItem = crmForm.all.[insert your Contact field here].DataValue;
2. crmForm.all.[your Account field].DataValue = larrray;

Outside of that if you shouldn't have to change anything if you are querying an Account via the ContactId. If you want to change the query that's up to you. Last thing before I post the script, this uses the 2006 WSDL, so don't expect this to work come CRM 5.0. We might get lucky and it could still work, but just know that it might not.

Here's the script:

var lookupItem = new Array;
lookupItem = crmForm.all.new_clientcontactid.DataValue;
var clientid;
if (lookupItem != null)
{
clientid = lookupItem[0].id;

var prodxml = GetClientInfo();
var companyid = "";

function GetClientInfo()
{
var xml = "" + "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<soap:envelope soap="\" href="http://schemas.xmlsoap.org/soap/envelope/">http://schemas.xmlsoap.org/soap/envelope/\</a>" xmlns:xsi=\"<a href="http://www.w3.org/2001/XMLSchema-instance/">http://www.w3.org/2001/XMLSchema-instance\</a>" xmlns:xsd=\"<a href="http://www.w3.org/2001/XMLSchema/">http://www.w3.org/2001/XMLSchema\</a>">" + "<soap:body>" + " <query q1="\" href="http://schemas.microsoft.com/crm/2006/Query/">http://schemas.microsoft.com/crm/2006/Query\</a>" xsi:type=\"q1:QueryExpression\" xmlns=\"<a href="http://schemas.microsoft.com/crm/2006/WebServices/%22%3e">http://schemas.microsoft.com/crm/2006/WebServices\"></a>" + "<q1:entityname>contact</q1:EntityName>" +"<q1:columnset type="\">" + "<q1:attributes>" + "<q1:attribute>parentcustomerid</q1:Attribute>" + "</q1:Attributes>" + "</q1:ColumnSet>" + "<q1:distinct>false</q1:Distinct>" + "<q1:criteria>" + "<q1:filteroperator>And</q1:FilterOperator>" + "<q1:conditions>" + "<q1:condition>" + " <q1:attributename>contactid</q1:AttributeName>" + "<q1:operator>Equal</q1:Operator>" + "<q1:values>" + "<q1:value type="\">" + clientid + "</q1:Value>" + "</q1:Values>" + "</q1:Condition>" + "</q1:Conditions>" + "</q1:Criteria>" + "</query>" + "</soap:Body>" + "</soap:Envelope>" + "";
var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
xmlHttpRequest.Open("POST", "/mscrmservices/2006/CrmService.asmx", false);
xmlHttpRequest.setRequestHeader("SOAPAction","<a href="http://schemas.microsoft.com/crm/2006/WebServices/RetrieveMultiple">http://schemas.microsoft.com/crm/2006/WebServices/RetrieveMultiple</a>");
xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
xmlHttpRequest.send(xml);

var resultXml = xmlHttpRequest.responseXML;
//alert("resultxml = " + resultXml);

var entityNodes = resultXml.selectNodes("//RetrieveMultipleResult/BusinessEntities/BusinessEntity");

for (var i = 0; i < entityNodes.length; i++)
{
var entityNode = entityNodes[i];

var companyidnode = entityNode.selectSingleNode("q1:parentcustomerid");

companyid = (companyidnode == null) ? null : companyidnode.text;
}

/** get the name of the company **/
var xml1 = "" + "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<soap:envelope soap="\" href="http://schemas.xmlsoap.org/soap/envelope/">http://schemas.xmlsoap.org/soap/envelope/\</a>" xmlns:xsi=\"<a href="http://www.w3.org/2001/XMLSchema-instance/">http://www.w3.org/2001/XMLSchema-instance\</a>" xmlns:xsd=\"<a href="http://www.w3.org/2001/XMLSchema/">http://www.w3.org/2001/XMLSchema\</a>">" + "<soap:body>" + " <query q1="\" href="http://schemas.microsoft.com/crm/2006/Query/">http://schemas.microsoft.com/crm/2006/Query\</a>" xsi:type=\"q1:QueryExpression\" xmlns=\"<a href="http://schemas.microsoft.com/crm/2006/WebServices/%22%3e">http://schemas.microsoft.com/crm/2006/WebServices\"></a>" + "<q1:entityname>account</q1:EntityName>" +"<q1:columnset type="\">" + "<q1:attributes>" + "<q1:attribute>name</q1:Attribute>" + "</q1:Attributes>" + "</q1:ColumnSet>" + "<q1:distinct>false</q1:Distinct>" + "<q1:criteria>" + "<q1:filteroperator>And</q1:FilterOperator>" + "<q1:conditions>" + "<q1:condition>" + " <q1:attributename>accountid</q1:AttributeName>" + "<q1:operator>Equal</q1:Operator>" + "<q1:values>" + "<q1:value type="\">" + companyid + "</q1:Value>" + "</q1:Values>" + "</q1:Condition>" + "</q1:Conditions>" + "</q1:Criteria>" + "</query>" + "</soap:Body>" + "</soap:Envelope>" + "";
var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
xmlHttpRequest.Open("POST", "/mscrmservices/2006/CrmService.asmx", false);
xmlHttpRequest.setRequestHeader("SOAPAction","<a href="http://schemas.microsoft.com/crm/2006/WebServices/RetrieveMultiple">http://schemas.microsoft.com/crm/2006/WebServices/RetrieveMultiple</a>");
xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
xmlHttpRequest.send(xml1);

var resultXml1 = xmlHttpRequest.responseXML;

var entityNodes = resultXml1.selectNodes("//RetrieveMultipleResult/BusinessEntities/BusinessEntity");

for (var j = 0; j < entityNodes.length; j++)
{
var entityNode = entityNodes[j];

var namenode = entityNode.selectSingleNode("q1:name");

var companyname = (namenode == null) ? null : namenode.text;
}

var larray = new Array;
var l = new Object();
l.id = companyid;
l.typename = 'account';
l.name = companyname;
larray[0] = l;
crmForm.all.new_clientcompanyid.DataValue = larray;

return resultXml;
}
}

Please note, I tested this in CRM Online and it doesn't work. Perhaps the 2006 WSDL isn't exposed with CRM Online, I'm not 100% sure, but just be aware that this script won't work there. Sorry.

David Fronk
Dynamic Methods Inc.