Showing posts with label Customizing. Show all posts
Showing posts with label Customizing. Show all posts

Saturday, October 31, 2009

ISV Utilities for Comparing Customizations and Transferring Configuration Data

Inna Agranov


Microsoft Corporation


February 2009


Summary


Learn how to build and use two new powerful tools developed for Microsoft Dynamics CRM. The Customization Comparison Utility lets you compare the customization files between two Microsoft Dynamics CRM systems and the Configuration Data Utility lets you transfer custom configuration data from one Microsoft Dynamics CRM system to another.


Download the Visual Studio 2008 and Visual C# code samples for this article:



The Readme.doc files that are included with the sample code contain information about how to set up and build the sample applications. The user guides contain detailed information about how to use the sample applications and view the results. You can find the Readme.doc files and user guides in the project folder for each utility.


Applies To


Microsoft Dynamics CRM 4.0


Microsoft Visual Studio 2008


Introduction


Microsoft Dynamics CRM is a highly customizable system. Not only you can modify different sections of the product, you can also create new components to address business needs. The Microsoft Dynamics CRM platform offers a robust set of tools, APIs, and documentation that helps you build custom business applications. As the applications built on the Microsoft Dynamics CRM platform become more and more complex, a need for specialized support tools grows. In this article you will learn about two very useful tools that help you analyze the impact of customizations on the system and maintain consistent configuration data across multiple Microsoft Dynamics CRM systems.


Evaluating the Impact of Customizations with the Customization Comparison Utility


To evaluate the impact of customizations, it is helpful to compare customization files between the source and the target systems before you import customizations. The Customization Comparison Utility helps you accomplish this task.


Analyzing Customizations

Often you have to export custom components from one Microsoft Dynamics CRM environment and import them into another, for example, from development into test or production. However, before you import customizations, it is very helpful to assess the impact of customizations on the target system. The system where you import customizations may have been changed since the last installation. You have to consider the extent of the changes and how they may affect the new installation. While some of the changes, such as renaming of the attributes or adding new attributes, are minor, other modifications, such as deletion of entities or changes in the forms may have a significant effect on the system.


Analyzing and understanding the system customizations may result in more successful deployment of a new version of the application. This analysis minimizes the risk of overwriting important customization data in the target system. For example, if only several attribute names have changed, you may be able to do a plain import using the import/export functionality built into Microsoft Dynamics CRM. However, if some key components were deleted, such as entity forms, you may have to merge the customizations with the changes in the target system. Comparing customization files between the two systems helps you determine which approach will result in more successful deployment. This is also very useful when you are diagnosing the problems between two systems. By comparing the customization files, you can often identify possible causes of the existing problems.


Using the Customization Comparison Utility

The Customization Comparison utility lets you easily compare two Microsoft Dynamics CRM customization.xml files. Unlike other XML comparison tools, this utility can read and understand Microsoft Dynamics CRM schema. The results of comparison show the differences in entities, attributes, forms, views, workflows, security roles, entity maps, and relationships. You can use this tool before you import customizations into a system to evaluate the effect they will have on the system.


Use the tool to compare XML customizations files between the source and the target systems. If you use a zipped customization file, make sure that it contains only one customization XML file. The following illustration shows the results of comparison between two customization files. The compared items include entities, roles, workflows, entity maps, and relationships. You can drill down into each item to see more details. From the entities, you can view the changes in attributes, forms, and system views. You can easily see the changes in source and target. It shows the items that are present in the source file and not present in the target file and the items that are present in the target file, but not in the source file.


Dd442453.a7338331-120b-4f29-ab17-1c94b85e014b(en-us,MSDN.10).gif


In addition to reviewing the results of the comparison in the grid, the tool includes a report that you can easily export to Microsoft Office Excel for additional analysis.


For more information about how to use the tool, see the Customization Comparison user's guide included in the download package for this utility.


Transferring Configuration Data with the Configuration Data Utility


When you work with multiple environments, such as development, test, and production, or multiple Microsoft Dynamics CRM organizations, keeping consistent configuration data across all systems can be very important. The Configuration Data Utility helps you achieve this. It lets you export custom configuration data from a source Microsoft Dynamics CRM system and import it to a target Microsoft Dynamics CRM system.


Storing Configuration Data in Custom Entities

In Microsoft Dynamics CRM you often use custom entities to store business information. However, you could also use custom entities to store system configuration data. For example, if an application integrates Microsoft Dynamics CRM with a third-party system, you could create a configuration entity with attributes such as pollingtime, url, and retries to store the configuration data needed for the integration. This is very convenient because the data stored in the configuration entity can be used by the system administrators to configure a new application or update an existing application. To keep the configuration data up to date, you may have to frequently upload the new data, or have an automated task to do it.


Using the Configuration Data Utility gives you a simple and efficient way to transfer custom configuration data from one system to another. One of the main benefits of this utility is that you can import configuration data from multiple custom entities at the same time. While it only imports and exports data for custom entities, the tool can handle useful scenarios, such as importing records that reference other records that are also being imported.


Dd442453.Important(en-us,MSDN.10).gifImportant


For the tool to work correctly, the schema for the source entities and the target entities must be identical.


Dd442453.note(en-us,MSDN.10).gifNote


In more complex cases, use the Microsoft Dynamics CRM data export and import tools or Data Migration Manager to transfer data for custom and system entities.


For more information about these tools, see Microsoft Dynamics CRM online Help.


Using the Configuration Data Utility

Use the Configuration Data Utility to export the source system configuration data and import it into a target system. The tool provides a convenient interface that lets you select the custom entities that contain the configuration data in the source system, save the data into a data file, and then import the records from the data file into a target system.


To run the tool, you must be a system administrator with appropriate privileges to create, read, and update entity instances.


The following illustration shows the entities in the source system that are selected for export.


Dd442453.0b8f0a81-1a17-4d77-9419-1cdc12427223(en-us,MSDN.10).gif


For import, specify the target server where you import the configuration data and the data file that you created during export, as shown in following illustrations.


Dd442453.9436a94c-f84f-4151-8d85-edc09ecaa422(en-us,MSDN.10).gif


Dd442453.5841695f-63ff-4ebb-a3b4-143657a9f759(en-us,MSDN.10).gif


The tool offers a command line version that you can run from a command prompt.


For more information about how to use the tool, see the Configuration Data Utility user's guide included in the download package for this utility.


Additional Information


Download the Microsoft Dynamics CRM 4.0 Software Development Kit (SDK) from the Microsoft Download Center.


For more information about custom entities, see Entity Customization.

Friday, October 30, 2009

SiteMap Privilege Tag

Dynamic Methods Microsoft CRM Blog


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.

Thursday, February 12, 2009

Adding A Filtered Lookup In CRM

by Danny Varghese 02.03.09


Another common question I see in blogs from users are is there a way to add filtered lookups? That is only allow users to "lookup" certain records that related to that particular one. Here's a real life example:

Say you have an account that has a 1:N parental relationship with entity A. Now let's say there's another entity B that has N:1 referential relationships with both account, and entity A. There is a way on entity B so that after you select, on the lookup, a record of the account you want to relate to it, to filter the second lookup of entity A to only those related to the account you just selected. i.e.

Parental Relationship

Account --> Entity A

Referential Relationship

Entity B -- Account

Entity B -- Entity A

With simple JavaScript, when a user selects the lookup value for the account, the lookup for Entity A can be filtered to point to only those entity A's that are related to the account you just chose. Here's the code to place on the form of Entity B:

crmForm.all.<lookup field for entity A>.additionalparams = 'search=' + encodeURIComponent(crmForm.all.<lookup field for account>.DataValue[0].name);

That's it! Simple, yet effective.

Friday, December 19, 2008

Customize Marketing List (List Member View) (EASY WAY)

Microsoft Dynamics CRM Team Blog posted this

The ability to Customize the List Member View of a marketing list has not been made available in the Customization area of the UI, but can still be achieved with the UI in other means by using the Advanced Find feature.

clip_image002
Fig 1: Marketing List Detail Form displaying “List Member View”

A Marketing List can only be 1 of 3 types, an Account, Contact, or Lead. By default each of these 3 entities has a view associated with it named “All Members”, "Active Members", and "Inactive Members". The view that is displayed for the List Member View is based on the marketing list type. For example if the List is an Account type Marketing List, then only the Account entity views of “All Members”, “Active Members”, and “Inactive Members” will be available. The Lead and Contact entities also has these three views, but they will not be available to a Marketing List of type Account.

I will provide an example below of adding a single column only to the “All Members” view for all 3 entities, “Account”, “Contact”, and “Lead” for a total of 3 view modifications. Note: You must have permissions for Customizations to perform the following steps.

How To:

Step 1: Launch Advanced Find

Step 2: When Advanced Find Dialog opens, change the “Look for” Combo box to be “Views”

Step 3: Change the Select Option to “View”, “Equals”

Step 4: Use the Lookup to find “All Members”. NOTE: You will see 3 “All Members” listed in your Lookup window, each one represents an Account, Contact, or Lead “All Members View”. For this example select all three. Optional, you can save your view query for future use.

clip_image004
Fig 2: Advanced Find Dialog

Step 5: Click Find on the Advanced Find Dialog and you should now have a results page listing three “All Members” Views, representing the “All Members” view for an Account, Contact, and Lead. Double Click on Each View to open.

Step 6: When each View is Opened, Select the “Add Columns” button and a property list will appear. Choose a property from the list you want to have displayed as a column by check enabling the box next to the property, in this example I will be choosing the property “E-mail”. Exit the property dialog by clicking ‘OK’ after making your selection.

clip_image006
Fig 4: All Members View for Account after adding the E-mail Column

Step 7: You are free to make other modifications to this View as well, such as column and sort order. Make your changes, Select “Save and Close”, and repeat (if desired) to the other “All Members” views returned by the Advanced Find Query.

Step 8: Important! Finally we need to publish these changes before they can become active. The saved view you modified will appear as an additional item (draft) until it is published and overwrites the existing View. Navigate in the system to ‘Settings’ -> ‘Customization’ -> ‘Customize Entities’. Under the menu Item “More Actions” Select “Publish All Customizations” or you can Use the “Publish” Button.

Important Note: Use the “Publish” button To ONLY publish the highlighted Entity row from the Grid (for example if you customized the memberlist view for Contacts, then select the ‘Contact’ entity item in the grid before pressing Publish. If Using “Publish All Customizations”, be aware that every customization pending in the system will be published!

clip_image008

Result: The List Member View has been modified…

clip_image010
Fig 5: Modified List Member View

Cheers,

Jim Schumacher

Friday, August 22, 2008

Problems Running CRM 4.0 Reports Post-Installation or Upgrade, Even after installing Microsoft CRM Data Connector

by Shelley Lane 07.16.08

When installing CRM 4.0 (or upgrading from 3.0) in an environment where SQL Server, SQL Reporting Services and CRM will all be on separate physical machines, you must use the Microsoft CRM Data Connector to bypass authentication issues. Once you’ve done this, your servers will all be able to communicate without issue and your reports will work swimmingly!

 

Well, almost. Recently, I encountered two separate instances (a new install and an upgrade, both using the Data Connector) where we had run all of the installs without any problems, but attempts at running any reports lead to the dreaded "Page Cannot Be Displayed" error.

 

In one case, the event log on the SQL Reporting Services server had several security audit failures. In there other case, there were no errors to be seen. However, both situations were the result of our Report Manager not being properly configured.

Follow these steps to verify that yours is configured correctly and, hopefully, save yourself some time.

  1. Open up Report Manager (http://SRSServer/Reports)
  2. Click on OrgName_MSCRM
  3. On the right-hand side, on the toolbar, click Show Details
  4. Click on the 4.0 folder
  5.  Then locate and click on MSCRM_DataSource
  6.  Verify that Connection Type is set to "Microsoft CRM Data Extension" and Connect using: is set to "Credentials supplied by the user running the report"
  7. Click Apply

 

Tuesday, July 22, 2008

Client Side Scripting - Retrieving the current user information (CRM 4.0 version)

STUNNWARE POST



A while back I posted a solution about the various techniques to retrieve information about the current user in CRM 3.0. I received an email lately asking for help about how it is done in CRM 4.0, an it seemed time to update the article.

The new solution uses the Microsoft CRM web services to retrieve the user id, business unit id, organization id and the first, last and full name of the currently logged on user. I have attached a simple test form with the following OnLoad event:

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 xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");

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

var resultXml = xmlHttpRequest.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");

crmForm.all.sw_firstname.DataValue = (firstNameNode == null) ? null : firstNameNode.text;
crmForm.all.sw_lastname.DataValue = (lastNameNode == null) ? null : lastNameNode.text;
crmForm.all.sw_name.DataValue = (fullNameNode == null) ? null : fullNameNode.text;
crmForm.all.sw_systemuserid.DataValue = (systemUserIdNode == null) ? null : systemUserIdNode.text;
crmForm.all.sw_businessunitid.DataValue = (businessUnitIdNode == null) ? null : businessUnitIdNode.text;
crmForm.all.sw_organizationid.DataValue = (organizationIdNode == null) ? null : organizationIdNode.text;

And the test form shows up like this:

Besides the code dealing with the XML result, the SOAP message was of course constructed with the JavaScript Web Service Tool.

Monday, July 21, 2008

Microsoft CRM Outlook client and authentication balloons

Posted by Mike Snyder on July 1, 2008

You know those little "balloons" that pop up from time to time in the Outlook 4.0 client? Below are some registry settings to change the Outlook client's behavior around network connectivity, notifications and so on. Our support manager recommend increasing ClientAuthAllowRetries to 10 and ClientAuthNotificationThrottle to 60000 (60 seconds), but you can obviously tweak to fit to your unique environment.

Regkey Name

Default

Description

ClientAuthNotificationThrottle30000Specifies the required elapsed time before which another balloon notification may be displayed (helps prevent too frequent balloon notifications).

ClientAuthRenewPeriod

60000

Specifies how frequently the hoster process will check if it should renew authentication.

ClientAuthVerifyConnectionPeriod

30000

Specifies how frequently the hoster process will check connectivity to the web application by downloading a tiny icon (anonymous access).

ClientAuthVerifySignedInPeriod

5000

Specifies how frequently the hoster process will check if authentication has been lost (ex: detect if cookies have been deleted or the CRM ticket has expired).

ClientAuthAllowRetries

3Specifies the number of failed authentication attempts (after this an error will be shown or the client will move to the offline state).

Posted by Mike Snyder on July 1, 2008 in Microsoft Dynamics CRM 4.0

Friday, July 18, 2008

Moving a Left Hand Nav item to a TAB in CRM 4.0

First you need to get the ID of the left hand Nav item you want to move. I used IE Develpoer Tool Bar. Or the naming is very straight forward. In this Case I created 2 custom entities. Price002 and Price003. Now the names look better on my screen but it keeps it easy to understand. The parent entity is Price002 and I have a related entity showing up on the left hand nav called Price003. If you did not modify any of the items on the relationship the ID should be nav_new_new_price002_new_price003. I know it looks wierd but when you create the relationship between two "new" custom entities you get new_[entity1]_[entity2].
Now that we have that I created a iframe and called it pa.
Now add the following to your on page load event.

var nav_new_new_price002_new_price003;
nav_new_new_price002_new_price003= document.all.nav_new_new_price002_new_price003;

if (nav_new_new_price002_new_price003!= null)
{
nav_new_new_price002_new_price003.style.display="none"
a = "/"+ORG_UNIQUE_NAME + "/userdefined/areas.aspx?oId=" + crmForm.ObjectId + "&oType="+crmForm.ObjectTypeCode +"&security="+document.crmFormSubmit.crmFormSubmitSecurity.value+"&tabSet=new_new_price002_new_price003";
if (crmForm.FormType == 2 || crmForm.FormType == 3 || crmForm.FormType == 4)
{
document.all.IFRAME_pa.src=a;
}
}

MSCRM 4 - Remove 'Add Existing xxxxx to this record' button

April 23, 2008 19:54 by davehawes

I've been working on a MS CRM 4 project and found that the custom entities that we added displayed an 'Add Existing xxxxx to this record' button when it was not required and created a lot of confusion amoung the users.

Microsoft have said they will make this optional 'In the next release' but that is not soon enough for me!

After working through various ideas on how to solve this with Ian Crowther and Steve Vallance we came up with the following fix. Thanks also to 'Dynamic Methods' for this post about hiding buttons: http://dmcrm.blogspot.com/2008/01/hiding-buttons-in-mscrm-40.html

This javascript should be added to the onLoad event of the entity where you are having the problem. You then need to call the function removeExistingButton passing in the name of the dataArea div tag and the title of the button you need to remove. (this can be found by using the IE Developer toolbar):

HideAssociatedViewButton('new_business_new_surveys', 'Add existing Survey to this record');
HideAssociatedViewButton('new_account_new_eventinvite', 'Add existing Event Invite to this record');

function HideAssociatedViewButton(loadAreaId, buttonTitle)
{
    var navElement = document.getElementById('nav_' + loadAreaId);
    if (navElement != null)
    {
        navElement.onclick = function LoadAreaOverride()
        {
            // Call the original method to launch the navigation link
            loadArea(loadAreaId);

            var associatedViewIFrame = document.getElementById(loadAreaId + 'Frame');
            if (associatedViewIFrame != null)
            {
                associatedViewIFrame.onreadystatechange = function HideTitledButton()
                {
                    if (associatedViewIFrame.readyState == 'complete')
                    {
                        var iFrame = frames[window.event.srcElement.id];
                        var liElements = iFrame.document.getElementsByTagName('li');
                        for (var i = 0; i < liElements.length; i++)
                        {
                            if (liElements[i].getAttribute('title') == buttonTitle)
                            {
                                liElements[i].style.display = 'none';
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
}

Wednesday, July 16, 2008

Dynamically changing the name of a tab

Posted by Dynamic Methods at 6/13/2008 07:06:00 AM
This comes from one of my coworkers, great hack. This works not only in the onLoad but also on the onChange of any field on the form. This is a great, simple script that might help users out a bit more.

Code:
var title = crmForm.all.primarycontactid.DataValue;

if(title != null)
{
document.all.tab4Tab.innerText = title[0].name;
}


You will need to change your tab4Tab to whatever tab you have on the form (remember, tabs start at 0 for the first position so make sure you get your numbering correct).

Simple as that. Now your tab will show the text of the name of the Primary Contact. Oh, one stipulation, the size of the tab will not regrow using this code, only the text. So, if your tab is named "Test" and I were to replace it with "David Fronk" then my name would get "wordwrapped" and it could look pretty funny. So, make your initial name something longer. If I come across how to dynamically grow the tab so as to fit the name being placed in it I'll definitely post that up here as well.

Enjoy!

David Fronk
Dynamic Methods Inc.

Reports in IFrames - Updated for CRM 4.0

Posted by David Jennaway at 11:45


One of my earlier posts here and on the CRM Team Blog was about writing reports to display in IFrames and via ISV.Config. This was written for CRM 3.0, and although the principle remains the same for CRM 4.0, a couple of changes are required to the report parameters.

Extra Parameters passed by CRM
To support multi-tenancy and multi-language deployments, CRM 4.0 passes additional parameters on the query string when the 'pass record object-type...' option is set for the IFrame. These extra parameters are orgname, UserLCID and OrgLCID.

For the report to work in reporting services you will have to add parameters with these names to your report. The orgname parameter has to be a string, the UserLCID and OrgLCID can be either strings or integers. As with the type and typename parameters, these new parameters don't have to be used in the report, they just need to exist for reporting services to accept values for them on the query string.

Changes to the query string for ISV.Config buttons
In CRM 4.0, Microsoft have standardised the parameters such that they are the same for IFrames and ISV.Config buttons. This means that your report should have parameters id, type, typename, orgname, UserLCID and OrgLCID.

Adding Activities to the Contact form in an iFrame

Posted: Friday, June 20, 2008 4:50 PM by Eric Boocock

Adding Activities to the Contact form in an iFrame

I came across the details on how to do this when reading a blog posting from Matt Wittemann a couple years back.  I still use it and thought you might be interested.  Another capability to demonstrate the flexibility of the configuration options of Microsoft Dynamics CRM Online.

 

1. Create an iFrame on the Contact form with the following properties.

clip_image002 clip_image004

2. Note the iFrame Name. The color coding will come in handy later. In this example I use IFRAME_Activities.

3. Install the Internet Explorer Developer Toolbar

4. Open a CRM contact record, copy the URL

5. Open a new IE window and enable the IE Developer toolbar

6. Paste the contact URL to load the Contact record with the IE dev toolbar enabled. Click on the toolbar icon for “Select Element by Click”
clip_image007

7. Find the Activities id by clicking on Activities from the left nav bar. Ensure to select the whole Activities area, not just the logo or the text. See outlined in blue in the screenshot below. Note the id: NavActivities from the middle window of the toolbar.
clip_image009

8. Click on the toolbar icon for “Select Element by Click” to disable it and click on Activities in the left nav bar to open the Contacts’ Activities list view in CRM. Enable the “Select Element by Click” functionality and click to the left of Filter On: Next 30 Days to select the windows highlighted in blue below.
clip_image011

9. Note the src value (areas.aspx?oId=…) from the middle window of the toolbar. In particular the part of the string after the CRM GUID starting at “&oType=2&security=…..”

10. Include the nav values and src value in the following script. The script is complete with values highlighted.

**********************************************************************************

//Render Activities in iFrame
if (crmForm.FormType != 1)
{
var navActivities;
navActivities = document.all.navActivities;
if (navActivities != null)
{
navActivities.style.display = "none";
document.all.IFRAME_Activities.src="areas.aspx?oId=" + crmForm.ObjectId +
"&oType=2&security=852023&tabSet=areaActivities";
}
else
{
alert("navActivities Not Found");
}
}

**********************************************************************************

11. Open the contact form to edit

12. Create a new tab called Address and move the current Address section to that tab
clip_image013

13. Create a new section on the General tab called Activities and show the divider. Add the IFRAME_Activities to the Activities section.
clip_image015

14. Add the previously edited jscript to the Contact form OnLoad event and Enable.
clip_image017

15. Publish your contact entity customizations.

16. Result will be the Contact form with Activities rendering in an iFrame on the form rather than appearing in the left nav bar.
clip_image019

 

Enjoy,

- Eric Boocock

Tuesday, May 27, 2008

Display KB Articles Your Way

Sunday, May 25, 2008 11:43 PM by Simon Hutson
---------------------------------------------

Pseudo Silk Kimono...


I don't know if it bothers anyone else, but it really bugs me the way KB Articles are displayed in the case entity within CRM 4.0. The problem is there is that the KB Article is displayed by a custom control on the form which cannot be customised. Not only do KB Articles share a form tab with Notes, but you have to click a checkbox to display your selected article - I never understood this design "feature". But by far and away the worst problem is that you can't change the size of the KB Article viewer, so that even for the shortest article you can only see a few lines of text at a time.


Default Case Form Layout


After a little digging around the page using the Internet Explorer Developer Toolbar, I found out that the KB Article custom control was nothing more than a glorified IFrame, displaying the "/CS/articles/viewer/default.aspx" page and passing the Article Id as a parameter.


The easiest way to expand the KB Article window is to replace the custom control with a standard IFrame and a few lines of JScript. However, by default the section containing the control is locked preventing you from deleting it within the form designer. Luckily, you can modify this behaviour by exporting the case entity, modifying the XML file and re-importing.


The first step is to change the "locklevel" attribute on the "section" element from 1 to 0.


Locklevel Attribute


Next, delete the the JScript event code that passes the Article ID to the KB Article custom control.


JScript Event Code


Finally, delete the row that contains the custom control itself.


Custom Control


Once you have saved the change, re-imported and published them to CRM, you can go ahead and just use the standard customisation tools to create an IFrame and some custom script on the form OnLoad event and the kbarticleid OnChange event. After a couple of minutes work, I ended up with something much more useable than the out-of-the-box KB Article viewer.


New Case Form Layout


I've attached a copy of my customizations.xml file here for you to import into your own CRM system. However, bear in mind that if you have already modified the case entity, then you may lose your customizations.


This posting is provided "AS IS" with no warranties, and confers no rights.

Thursday, May 22, 2008

Hiding a Section

David Fronk of Dynamic Methods Inc. wrote this
----------------------------------------------
Hiding a section has been an interesting customization to figure out. I definitely got help by reading through posts and groups, but then again, who doesn't? When hiding things in CRM typically it's done by referencing a specific control name, something like the tab number or the field name. Sections are strange in that they don't have any of the normal "English" identifiers that one would expect. It's actually reference directly through a GUID. Each section gets assigned a GUID upon creation, so writing code that is dynamic for hiding sections directly really wasn't pretty...or possible.

However, if you reference a section indirectly things actually get much easier. For example, everything in the CRM forms are contained within something larger. Fields are contained by Sections, which are contained by Tabs, which are contained by the web form itself. That means that there is a direct parent/child relationship between objects on the form. JScript has thought about this and allows you to reference ParentNode's through code.

With this new knowledge referencing sections actually becomes very easy. All that has to be done is make a reference to a field on the form and then get it's parent node and do what you need to do to it.

Here's the code:

document.getElementById("ownerid").parentNode.parentNode.style.display = "none";

You'll notice that I have to parentNode references, that's not a mistake, this is the progression on how to get to the section. Fields are actually contained by Labels and Labels are contained by Sections on a form. I didn't realize this until I tried using only the first parentNode reference. Play with it a bit and you'll see what I mean.

Then to make the section visible again just use empty quotes:

document.getElementById("ownerid").parentNode.parentNode.style.display = "";

And now you have full control over what to make visible to users upon any condition you want.

Happy coding!

David Fronk
Dynamic Methods Inc.

Hiding Views in CRM 4.0 Using Plug-in

Darren Liu, Darren's CRM Blog
Copy of his post
------------------------------------


There are many new moving parts added to CRM 4.0 and I am learning something new every day from the community, the projects that I am working on and the people around me. What I have learned this week by working with Sean McNellis at Microsoft is to hide Views using a simple CRM 4.0 plug-in.

As many of you may already know that Microsoft took off the capabilities of sharing views which many people used in CRM 3.0 to hide unwanted System Views from the user's view list. There have been many posts in the CRM newsgroup community on how to hide the views.

My colleague, Jeremy Hofmann found a clever way of hiding the views by updating a bit field in SavedQueryBase table against the MSCRM database. Unfortunately manipulating with the MSCRM database is not encouraged and also not supported by Microsoft. So what can we do?

What I have learned is that we can manipulate with the SavedQuery entity through a simple plug-in to control what shows up on the user's view drop down list. There are many neat things that you can do through the savedquery class offered by the SDK, you can read about it in the 4.0 SDK.

In this post, I will show you how to hide some Contact System views by writing a simple plug-in. I will intercept the retrieve operation that CRM used for getting the views and then append more condition logics to the its query expression.

Before:


ScreenHunter_01 Feb. 25 22.10

C# Code:

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.Sdk.Metadata;
using Microsoft.Crm.Sdk.Query;
using Microsoft.Crm.SdkTypeProxy;
using Microsoft.Crm.SdkTypeProxy.Metadata;

namespace CrmAddon.Crm.Plugin
{
public class HideContactViewsPlugin : IPlugin
{
public void Execute(IPluginExecutionContext context)
{


            // Query the SavedQueryBase table to retrieve the Query Id
Guid[] Views = new Guid[] {
new Guid("9818766E-7172-4D59-9279-013835C3DECD"), //NA-Contacts: No Orders in Last 6 Months
new Guid("9C241A33-CA0B-4E50-AE92-DB780D5B2A12"), //NA-Contacts: Responded to Campaigns in Last 6 Months
};

if (context.InputParameters != null && gHiddenViews.Length > 0)
{
if (context.InputParameters.Properties.Contains(ParameterName.Query))
{
QueryExpression qe = (QueryExpression)context.InputParameters.Properties[ParameterName.Query];

//only apply this action if the query is for 'views' or saved queries
if (qe.EntityName == "savedquery")
{
if (qe.Criteria != null)
{
if (qe.Criteria.Conditions != null)
{


                                //Append more condition logic to the default query that's used by CRM. In this case, I filtered on the savedqueryid to exclude the views from the Ids identified above.


ConditionExpression queryCondition = new ConditionExpression("savedqueryid", ConditionOperator.NotIn, Views);
qe.Criteria.Conditions.Add(queryCondition);
context.InputParameters.Properties[ParameterName.Query] = qe;
}
}
}
}
}
}
}
}


Plug-in Registration:


Message: RetrieveMultiple
Primary Entity: savedquery
Stage of Execution: Pre Stage
Execution Mode: Synchronous


Sample Registration Snapshot:


...


<Step


    CustomConfiguration = ""


    Description = "Hide Contact View Plug-in"


    FilteringAttributes = ""


    ImpersonatingUserId = ""


    InvocationSource = "0"


    MessageName = "RetrieveMultiple"


    Mode = "0"


    PluginTypeFriendlyName = "Hide Contact Views"


   PluginTypeName = "CrmAddon.Crm.Plugin.HideContactViewsPlugin"


    PrimaryEntityName = "savedquery"


    SecondaryEntityName = ""


    Stage = "10"


    SupportedDeployment = "0" >


</Step>

...



After:



image



As you can see that the "Contacts: No Orders in Last 6 Months" and "Contacts: Responded to Campaigns in Last 6 Months" views are removed from the drop down list. The new CRM 4.0 SDK is really powerful and you can definitely do more with it. E.g. hide/show the view based on the user id or team, etc...



I hope this will help you on your next CRM project. :)



Displaying a Report in an IFrame of a CRM Entity Form

Zahara Hirani published the following on his blog.
------------------------------
Recently Danny Varghese wrote a blog on displaying related entities in an IFrame of a CRM form. Let’s give it a little twist – Displaying a Report in an IFrame of a CRM Form.

For this example, we created a custom report that takes in the Account Id as a parameter and displays the campaign activities associated to that Account. Now let’s add the report to display on an account and show all campaign activities that have taken place with that account.

For this,

Open CRM and navigate to the Settings Module.
Now navigate to Customizations and select Customize Entities.
Select the Account entity for edit and navigate to the Forms and Views.
Select the Form for edit.
Add a Tab to the Account called ‘Campaign Activity’.
Add a section in that tab called ‘Campaign Activity Report’ and add an IFrame to the section.
For the URL of the IFrame, enter ‘about:blank’.
We will now add logic in the form OnLoad event that will create the report URL and append the Account Id for the report to use to display the campaign activities.

//Get Account Id and remove the {} from the start and end of the guid
var accountId = crmFormSubmit.crmFormSubmitId.value;
accountId = accountId.substring(1, accountId.length -1)

//Get Reporting URL
var url = 'http://localhost:5555/ReportServer?%2fCrowe+Chizek_MSCRM%
2fAccount+Campaign+Activity&rs:Command=Render&rs:Format=HTML4.0&
rc:Toolbar=false&rc:Parameters=false&AccountId=' + accountId;

document.getElementById('IFRAME_CampaignActivity').src = url;

In the above code you will notice, we had to remove the ‘{}’ from the account id the Form returns. The easiest way to get the report URL is to open the report using the report server.

For this,

Navigate to the reporting services report server (e.g. http://localhost/reportserver)
Now Navigate to the CRM Reports Folder. (e.g. Crowe_Chizek_MSCRM)
Now navigate to the custom report you created. (e.g. Account Campaign Report in our scenario).

Since we want the report in an IFrame, we do not want the report viewer toolbar and parameters to show. Hence the ‘rc:Toolbar=false&rc:Parameters=false”. Since we want the report to render in HTML 4.0, we can specify the format to render the report in by specifying ‘rs:Format=HTML4.0’. Last but not the least we add the Account Id to the querystring so that the report can pick up the Account Id from the querystring and use it to return only campaign activities associated to that account.

Now save and close the form and publish the entity.

Navigate to an account that has campaign activities and you should see the new tab and report render in the IFrame.