Search This Blog

Thursday, April 11, 2013

Enable prefiltering on FetchXML report

I just spent over an hour trying to understand why, all of sudden, something I've always done a certain way seems to NOT work anymore. Ever been there?

I was working on a CRM 2011 report (FetchXML) that I want prefiltered to pick up the selected Invoice records. Should be easy enough, simply add enableprefiltering="true" to the main entity to filter. Right?

Or is it?

For some reason (I was probably recycling a query from somewhere else, as I tend to do), I had given my entity an alias: <entity name="invoice" alias="Inv" enableprefiltering="true" >. The report uploaded to CRM without a hitch, the prefilter ("Advanced Find"-like window) came up to allow me to select filter criteria, but no matter the conditions, the report would NOT filter.

After trying various other options (including eating an ice cream bar, which did nothing for my report performance but made me happier), I removed the alias and ta-da! the filter suddenly works.

You might want to give this a try if you are facing the same issue in a similar context. (I haven't tried to replicate the solution without the ice cream element, so take no chance and go get one!)

~ Brigitte

Monday, January 14, 2013

Viewing Lead notes in related Accounts, Opportunities and Contacts

Anyone who has implemented Microsoft Dynamics CRM sales functionality has sooner or later run into a desperate call from a client who says the notes they added when a prospect was in a "Lead" stage no longer appears now that the "Lead" has been converted to an "Opportunity".

As most CRM consultants know, only activity records (Phone Calls, Tasks, Appointments, Emails, etc) entered in the Lead stage will transfer when the Lead is converted to an Account, Contact and Opportunity.  The notes will not transfer.  Whether this was by design or a design flaw is something the CRM nerds can debate about.  For now, lets look at a solution.

The following is a solution I built that will allow users to be able to view notes entered in the originating Lead record in the resulting Account, Contact or Opportunity records.

Basically, I added a tab on the evolved entity forms that will show the "originating lead" notes.

Original Lead Note




Opportunity Showing Lead Note


Implementing the Solution

To put this solution together, you should be comfortable with CRM 2011 field and form editing, solutions, Iframes, web resources and JavaScript.  Having a bit of knowledge on OData and REST endpoints can't hurt.  The CRM SDK is good resource to get up to speed.

Form Customization

The first thing to do is create a place to view the Lead notes. 

On the Account, Opportunity and Contact Forms (you can put this on all 3 or just the entity where you want to see the lead notes) add a Tab called "Lead Notes" and on the tab place a section and an IFrame.



For the IFrame, enter in a name like IFRAME_LeadNote (you will need to remember this for later for the JavaScript code) and for now, put in "about:blank" for the URL.  We will programmatically change these when the tab is selected.



In my solution, by default I am keeping the Lead Notes tab collapsed and triggering the code when the tab is expanded.  Feel free to trigger on the onload event if you want to have immediate visibility. 



Repeat creating the Tab, Section and IFrame for the Account and Contact forms if you wish.

If you haven't (and why not?) download the CRM 2011 SDK

Add the following jscript web resources to your solution from 

\sdk\samplecode\js\restendpoint\javascriptrestdataoperations\scripts\

json2.js
sdk.rest.js

Eventually, your web resources should look something like this:


Many times there will not be any Lead notes to display or the Account, Contact or Opportunity records may not have evolved from a Lead.  We want to show friendly message that there are no lead notes.  I created a simple HTML web resource that gets displayed when there are no notes to show.

The display will look something like this:



Enter the following and save it as an HTML file, then load it into your solution as a HTML web resource.

<HTML><HEAD><TITLE>No Lead Notes to Display</TITLE></HEAD>
<BODY style="BACKGROUND-COLOR: #f6f8fa" contentEditable=true> 
<STYLE type=text/css>
        .style1
        {
            font-family: Arial, Helvetica, sans-serif;
            font-size: small;
        }
    </STYLE>

<P class=style1>No Lead Notes to Display</P></BODY></HTML>


We now need to enter a script that will do the following;

When the "Lead Notes" tab is selected:
  • Check to see if there is an originating lead.
  • Check to see if the originating lead has any notes.
  • If so, point our IFrame to the Lead's notes.


Here is the JavaScript.  I used the REST endpoint to see if notes exist for the lead.  For more info on how that works, refer to the CRM SDK:

function leadNotes()
{
    //This Function builds proper URL for Iframe (IFD/OnPremise)
    function prependOrgName(sUrl)
    {
        return (IS_PATHBASEDURLS && ORG_UNIQUE_NAME.length > 0) ? ("/" + ORG_UNIQUE_NAME + sUrl) : sUrl;
    }

    //Get some values from CRM Foom
    var Primary = Xrm.Page.data.entity.attributes.get("originatingleadid");
    var IFrame = Xrm.Page.ui.controls.get("IFRAME_LeadNote");
    var NoNotesMsg = Xrm.Page.context.getServerUrl() + "/WebResources/rxrm_noleadnotes";

    //Check if this record was created from a lead
    if (Primary.getValue() != null)
    {
        //Get GUID of lead record
        var GUIDvalue = Primary.getValue()[0].id;

        //Use SDK rest library to see if any notes exists for the related lead
        SDK.REST.retrieveMultipleRecords("Annotation","$select=AnnotationId&$filter=ObjectId/Id eq guid'" + GUIDvalue + "'",
        function (results)
        {
            var firstResult = results[0];
            if (firstResult != null)
            {
                //If notes exist for related lead, show them in custom IFrame
                IFrame.setSrc(prependOrgName("/_controls/notes/notesdata.aspx?id=") + GUIDvalue + " &ParentEntity=3&EnableInlineEdit=false&EnableInsert=false");
            }
            else
            {
                //If no notes, display a friendly message
                IFrame.setSrc(NoNotesMsg);
            }
        },
        errorHandler,
        function ()
        {
            //OnComplete handler
        }
        );
       
    }
    else
    {
        //If record did not come from a lead, display a friendly message
        IFrame.setSrc(NoNotesMsg);
    }

}

function errorHandler(error)
{
    alert(error.message);
}

Save and add the script to the web resources.

You now will need to add the JavaScript libraries to the corresponding Account, Contact and Opportunity forms.  (json2, SDK.rest and the new lead notes script)

To tie this all up, you now need to trigger the "leadNotes" function from "TabStateChange" when the Lead Notes tab is selected on the CRM form:


Repeat for each entity, publish and test!

Note that you will not be able to add notes to the Lead entity, just view them.
You will want to make sure that your users have at least read access to Leads in their security roles in order to view the notes.

Like all things, I assume no responsibility for any of the code or suggestions here. 

Cheers!
Nick



Friday, January 4, 2013

CRM 2011 IFD issue and Rollup 11

Happy New Year!

Over the Christmas break I though it would be a good time to rebuild/reconfigure our development environment.  This is something that I hope to blog about later.

One of the things that I needed to do was to setup CRM 2011 Internet Facing Deployment (IFD) to allow the team to have quick and easy access to the dev orgs without dealing with VPN and RDP issues and performance. 

Setting up CRM IFD is something that I have done a number of times and each time it seems that I learn (ie- have issues) something new.

CRM 2011 requires the use of Active Directory Federation Services (ADFS), SSL certificates and a LOT of patience. 

If anyone were to build a tool that you put in your basic parameters (CRM server name, IP addresses, etc) and have it generate appropriate batch files, powershell scripts and checklists to setup CRM 2011 IFD, there would be a lot of premium beer in it for you.

I have found that good step by step guide for setting up CRM 2011 IFD can be found here: http://www.interactivewebs.com/blog/index.php/server-tips/microsoft-crm-2011-how-to-configure-ifd-hosted-setup/

I have a few notes on my well worn printed out copy, notably that the "setspn" commands need to be run on the CRM server, and the "Transform Windows Account Name to Name" rule in ADFS you need to choose "*Name" (blog posts indicates just "Name") and a few extra IISResets along the way, still, without that blog article, I might still be pulling my hair out.

On my new dev enviroment, I installed CRM 2011, I used the slipstreamed install with Rollup 6 embedded.  I also applied Rollup 11 to keep things up to date (at time of this blog, Rollup 12 was not yet released).

After fighting my way throught this, I ended up getting an "Unexpected Error" when trying to connect to CRM either via the internal or external claims based endpoints.  I was still able to get in via http://servername:port locally.

Digging deeper, I found in the event log that I had unhandled exception error, digging deeper I saw the details "Exception message: Could not find GUID for server: XRM2011$ With SearchFilter:samAccountName"

Thanks to Google, I found this posting:
http://community.dynamics.com/product/crm/f/117/t/93178.aspx

Essentially, you need to do the following steps (cut and pasted from article):

Change the Anonymous user identity of IIS Anonymous Authentication Credentials to Application pool Identity option:

1. On the CRM server, open the Internet Information Services (IIS) Manager;

2. In IIS Manager, click the CRM site;

3. In the Features View, double-click Authentication;

4. Select Anonymous Authentication , and then click Edit in the Actions pane;

5. In the Edit Anonymous Authentication Credentials dialog box, click the Application pool Identity , and then click Ok;

6. Do an IISRESET on CRM and ADFS server.

My situation Resolved! 

Kudos to the contributors to the posting above.  Apparently there will be a hotfix and Rollup 12 will also address this.

Hope this helps!
Cheers
Nick



Thursday, September 20, 2012

Error Registering Plugin with CRM Online created via Office365

I was putting together a demo this week and provisioned a new instance of CRM Online.  For those of you haven't done this yet, the process is now done via Office 365 and there are in a few minor differences.

We began to load up some of our pre-built solutions which seemed to go OK.  We needed to register a plugin that we developed for auto-numbers.  The plug-in registration tool (which we used many time before) came up with an errors.  The first one was "Unable to retrieve organisations from the discovery service".  Upon further reading (and looking at the new customization endpoints in CRM online) we learned that you now need to change the discovery URL from https://dev.crm.dynamics.com to https://disco.crm.dynamics.com

No problem, done.  We were still getting errors, further investigation showed "Unhandled Exception: System.InvalidOperationException: There is an error in XML document (5, 5)." and a whole bunch more information on the error.

After some research, we learned that there were some updates in the latest rollups and the SDK that corresponded with some of the Office365/CRM Online changes.  We ended up recompiling the plugin registration tool using the most up to date CRM SDK and we were then able to retrieve the organizations.  We did run into an error connecting to the organization, but retried 1-2 more times and it did connect (hmmm). 

Lesson learned, keep your tools up to date with CRM instances!


Wednesday, September 5, 2012

CRM 2011 and Windows 8

So Windows 8 showed up on the Action Pack downloads last week so I thought I would give it a spin.  I had not looked at any of the earlier betas or release candidates so I went in fresh.  I am familiar with the (don't call it metro) interface since I have been using a Windows phone for about a year now.

For Dynamics CRM, here were the things to look out for:

First off, the CRM of Outlook client could no longer connect.  We currently have our CRM hosted on www.ITUtility.net , our Canadian based cloud provider.  Normally I would login using my email address when setting up the Outlook connector, but after some digging around I discovered that I could only connect using my actual ITUtility "domain\username" format to login.  The Windows Identity foundation 3.5 needed to be installed as well.

Once I got beyond that, the process would eventually fail when configuring the client.  After installing the client CRM Rollup 10, the situation was resolved.

Running CRM 2011 in IE 10 also posed some issues, there was lots of "there was an error in CRM...." I found a Microsoft KB article that indicated you should run IE in compatibility mode.  This for the most part solved these issues.   One issue that did not go away was the ability to drag and drop a field in form customizations, not entirely sure it was a Windows 8/IE 10 issue but once I logged onto a Windows 7 machine I was able to make the changes I needed.

Windows 8 Summary

Before upgrading I took a good backup image of my laptop and went ahead with an in-place upgrade. Everything went fairly well. I was not too keen having to associate my Windows Live ID to the login, but it is what it is.

My laptop is not touch screen, so I think I am missing out in some of the experience.   Using Windows 8 is an odd mix of the new (don't call it Metro) interface and the "traditional" windows interface.  It reminded me of using Windows 95 with DOS programs.  Using the two interfaces becomes a bit cumbersome.  The other thing was the absence of the "Start" button.  I was able to find a freeware app that put it back, there seems to be a lot of debate online about it, I think Microsoft is trying to push folks to the new interface, but if that were the case, then the entire old desktop should have been flushed, not taking key pieces away one bit at a time.  Some of the new Windows 8 style apps were cool, like remote desktop and OneNote, however it takes some time to get used to the new way to adjust settings, minimize and switch applications, all the while will still using the old way for the "traditional" apps.

Suffice to say I ran Windows 7 recovery and restored the backup image, so I am now back to the comfortable Windows 7 interface.

Overall, Windows 8 is not as horrible like Vista, but I think Microsoft tried unsuccessfully to bridge the old and new, and like mint and chocolate, both good seperately, disgusting when mixed together.

When the majority of the apps that I use (Office, CRM) have moved over to this interface and I won't ever need to use the old desktop, is when I will upgrade permanently.  Until then, I think I will be sticking Windows 7, after all, it *was* my idea. 

Friday, February 24, 2012

Contact Info / Label (CRM 2011)

Although the built-in Word Mail Merge can create nice personalized mailing labels, sometimes users don't want to go through all the steps Word requires to generate just one label. That is why we add a "Contact Info Summary" concatenation on most of our clients' Account and Contact forms, for a quick copy-paste option.

The code below applies to Contacts, but it can be easily adapted for the Account, Lead and Address forms.

1.    Start by creating a new memo attribute (“Multiple lines of text”) that will hold your concatenated label. In our example, we named it “new_contactinfosummary”. We recommend making it non-searchable to keep the fields list cleaner.

2.    Add the field to the form. Layout is up to you, obviously, but we recommend making it read-only, to ensure that users don’t start typing in there, thinking individual fields will update from there (true story…).


3.    Add the following 2 functions in a web resource.

function BuildContactInfoSummary() {
    //------- Load the function to build the Contact Info Summary
    var Label = "";

    if (Xrm.Page.getAttribute("salutation").getValue() != null)
    { Label = Xrm.Page.getAttribute("salutation").getValue() + " "; }

    if (Xrm.Page.getAttribute("firstname").getValue() != null)
    { Label = Label + Xrm.Page.getAttribute("firstname").getValue() + " "; }

    if (Xrm.Page.getAttribute("lastname").getValue() != null)
    { Label = Label + Xrm.Page.getAttribute("lastname").getValue(); }

    if (Xrm.Page.getAttribute("jobtitle").getValue() != null)
    { Label = Label + ", " + Xrm.Page.getAttribute("jobtitle").getValue(); }

    var OrgName = Xrm.Page.getAttribute("parentcustomerid").getValue();
    if (OrgName != null)
    { Label = Label + "\r\n" + OrgName[0].name; }

    if (Xrm.Page.getAttribute("address1_line1").getValue() != null)
    { Label = Label + "\r\n" + Xrm.Page.getAttribute("address1_line1").getValue(); }

    if (Xrm.Page.getAttribute("address1_line2").getValue() != null)
    { Label = Label + "\r\n" + Xrm.Page.getAttribute("address1_line2").getValue(); }

    //ENABLE THE FOLLOWING IF YOUR FORM INCLUDES STREET 3:
    //        if (Xrm.Page.getAttribute("address1_line3").getValue() != null)
    //        { Label = Label + "\r\n" + Xrm.Page.getAttribute("address1_line3").getValue(); }

    if (Xrm.Page.getAttribute("address1_city").getValue() != null)
    { Label = Label + "\r\n" + Xrm.Page.getAttribute("address1_city").getValue(); }

    if (Xrm.Page.getAttribute("address1_stateorprovince").getValue() != null)
    { Label = Label + ", " + Xrm.Page.getAttribute("address1_stateorprovince").getValue(); }

    if (Xrm.Page.getAttribute("address1_postalcode").getValue() != null)
    { Label = Label + "   " + Xrm.Page.getAttribute("address1_postalcode").getValue(); }

    if (Xrm.Page.getAttribute("address1_country").getValue() != null)
    { Label = Label + "    " + Xrm.Page.getAttribute("address1_country").getValue(); }

    if (Xrm.Page.getAttribute("telephone1").getValue() != null)
    { Label = Label + "\r\nBusiness Phone: " + Xrm.Page.getAttribute("telephone1").getValue(); }

    if (Xrm.Page.getAttribute("emailaddress1").getValue() != null)
    { Label = Label + "\r\n" + Xrm.Page.getAttribute("emailaddress1").getValue(); }

    Xrm.Page.getAttribute("new_contactinfosummary").setValue(Label);
    Xrm.Page.getAttribute("new_contactinfosummary").setSubmitMode("always");
}

function UpdateContactInfoSummary() {
    //------Update the Contact Info Summary on updatable records
    if (Xrm.Page.ui.getFormType() == 2) {

        //------Force a save if the Contact Info Summary was empty ** NOTE: remove this following statement if you DO NOT want to force a save -- i.e., if you have onSave code that you do not want triggered right away
        if (Xrm.Page.getAttribute("new_contactinfosummary").getValue() == null) {
            BuildContactInfoSummary();
            Xrm.Page.data.entity.save();
        }
        else {
            BuildContactInfoSummary();

            //------Disable the "do you want to save?" alert if the Contact Info Summary hasn't changed
            if (crmForm.all.new_contactinfosummary.IsDirty) crmForm.detachCloseAlert();
        }
    }
}

4.    Add UpdateContactInfoSummary as an onLoad event and BuildContactInfoSummary as an onSave event.

5.    Save and publish customizations.

Wednesday, February 22, 2012

Report Uploading Error

I was getting an error uploading custom reports on a customer's CRM 4.0 deployment.  When I would upload the report, I would get the following error:


Checking Google and CRM Forums it seems like there are a lot of people with this error.  A common mistake is creating a report in a new version of Visual Studio (2008) and targeting an older version of SQL (2005) reporting services.  This was not my problem, and I had been able to upload reports before.

Now, not exactly sure why, but I have had issues with reports on CRM before, and the process of playing around with encryption keys has resolved some issues.

On the SQL Report Server, I went to Start -> All Programs -> Microsoft SQL Server 2008 -> Configuration Tools -> Reporting Services Configuration Manager



I clicked connect and then clicked on encryption keys, and then backup. 

I entered a filename and path, passwords and that was it! 



I exited Reporting Services Configuration Manager and I could now upload custom CRM reports with ease.

I hope this helps someone in the future.  If anyone could give an explanation why this would fix it, I would appreciate it!

Cheers
Nick