Wednesday, June 9, 2010

Flex XML - easy to use!

Today I am working on a project that uses an Adobe Flex application to call a .NET back end web service to call some SSRS reports. For one reason or another, I needed to pass an XML string from the front end app to the back end, and found it was incredibly simple. In one of my Actionscript files of my app, I created an XML type variable and added the parameters for the report. The code looked like this:


var rp:XML = <reportParameters/>;

var service:CrmService = new CrmService();

service.addgetAllCustomersEventListener(customerResult);

service.addEventListener(FaultEvent.FAULT,serviceFaultHandler);



var custreq:GetAllCustomers_request = new GetAllCustomers_request ;

rp.appendChild(<start>{startdt.text}</start>);

rp.appendChild(<end>{enddt.text}</end>);

custreq.reportParameters = rp.toXMLString();

service.getAllCustomers_request_var = custreq;

service.getAllCustomers_send();

As you can see, you dont even need quotes around the XML tags, you can do free-form mixing of the tags with the Actionscript code. The variables appear in the curly braces {}. The method called toXMLString() converts all this into a string that looks like this:

<reportParameters><start>1/12/2010</start><end>3/14/2010</end></reportParameters>

The really exciting part is that the XML object managed the containing <reportParameters> tags so I didnt have to worry about closing it properly.
I really like this because now I do not have to write a lot of tedious code with all the open and closing quotes around each literal string and concatenating them together. I hope someone finds this useful.
I hate writing code where I have to carefully manage all beginning and ending

Friday, March 12, 2010


I watched in horror last night as Anderson Cooper hosted Mike Moore pontificating his socialistic, feel-good agenda without any balanced point of view. He is a film maker that gets people to listen to him by demonizing some stereotypes. Shouldn't AC, as a journalist, be asking Moore some hard questions instead of just giving him a podium so that he can rant?

Fundamental economics has proven that if a business is making a profit, then more competition will spring up and squeeze the profit margins so that everyone benefits. And the key to making that work is when individual people are making choices about what is best for them. By having the insurance companies bypass the individual and work directly with providers, we lose the efficiencies of a working market. And contrary to Mr. Moore’s claims, as reported by CNN (http://www.cnn.com/2009/POLITICS/07/06/canadian.health.care.system/index.html), government healthcare in Canada is not only incapable of providing a service as good as , people are dying to get service.

When Pres. Obama was campaigning for office, I liked that he espoused a belief that individuals were the solution to our problems, but so far the majority of politicians in DC have completely ignored the individual as a solution, and have been focused on building new institutions that they can control.

Yes, the US healthcare system does need to be changed, but we need more people to take responsibility for taking better care of themselves, and becoming smarter consumers.

Tuesday, February 2, 2010

Compare previous field values in CRM 4 using Javascript

A customer asked me to have a pull-down field populate a "comment" field (it was actually a large varchar field) with the text the user selected in the pull-down (this was to support a legacy data integration issue). That seemed easy enough, but there was a catch: if the user changes the pull-down to another value, then they wanted the previously selected text to be removed from the comment field.

I am not going into the details of how to add JS to CRM code, but I can recommend looking at http://blogs.inetium.com/blogs/azimmer/archive/2009/03/08/five-tips-for-productive-form-scripting-in-crm-4-0.aspx


First, I needed a function that would add and remove text from the "comment" field. I loaded this in the form OnLoad event:


function updateComment1 (tf, cComment){
try {
if (tf == true) {
if(crmForm.all.new_comments.DataValue != null && crmForm.all.new_comments.DataValue.length > 0){
crmForm.all.new_comments.DataValue = crmForm.all.new_comments.DataValue + Chr(13)+ cComment;
}else{
crmForm.all.new_comments.DataValue = cComment;
}
}else{
crmForm.all.new_comments.DataValue = crmForm.all.new_comments.DataValue.replace(cComment,"");
crmForm.all.new_comments.DataValue = crmForm.all.new_comments.DataValue.replace(/\r\n\r\n/m,"\r\n");
}

}catch(err){
// do nothing - the comments are empty and we dont care
}
}




This code will take two arguments: one will tell it what to do, and the second is the string to either insert or remove from the faux comment field. If the first argument is true, then the string is inserted into the comment field, otherwise the string is removed (if it exists). The caveat to this is that if the user changes the spelling of the string, then this will not remove it.

Next I created a function to accept the pull-down field as an argument and handle sending the update to the first function:


function updateComment2 (oField) {
updateComment1(false, oField.prev_value) // this will remove the old text from comments
if(oField.SelectedText.substr(0,7)!="No Pref"){
updateComment1(true, oField.SelectedText) // this will put the new text in the field
}
oField.prev_value = oField.SelectedText; // reest the previous value for the next time around

}


In this system, the pull-down has a default value of "No Pref" which means the user did not have a preference for this item, and the reference to this should be removed from the comment field. Notice that there is also a property of the field called "prev_value" which is not normally part of MS CRM form fields. When the form loads, I added a couple lines of code to capture the current state of these controls:


crmForm.all.new_preference1.prev_value = crmForm.all.new_preference1.SelectedText;
crmForm.all.new_preference2.prev_value = crmForm.all.new_preference2.SelectedText;



Using this trick will allow you to add any number of new properties to a form field.

Then in each of the fields OnChange events, I added a call to my updateComment2 function. For example, the OnChange event of the new_preference1 field would look like:


updateComment2(crmForm.all.new_preference1);



When the user changes the pull-down, it calls my custom function updateComment2 and passes a reference to itself which I will use to inspect its previous value and remove the old the string from the comment field before adding the new selected text back in.

I could have combined some of this code, but have it broken down this way because I am using these functions in other places in the form by checkboxes, radio buttons and such and this gives me some flexibility to re-use code.

Tuesday, January 26, 2010

SSRS Select permission was denied on the object

Note to self: When I create a SSRS report for CRM, always use "filtered" views in the query for the report - never use the other tables or views. Here is the situation:

I had created a report for use in an Iframe of CRM, and it was getting the error "Select permission was denied on the object ..." and it named one of my tables in CRM. The query ran just fine when I was logged in as the administrator, but when the users got it, it gave me that error. Permissions for objects (entities) in MS CRM are applied to the filtered views in order to enforce access controls to the data. When you view a CRM entity form and the browser tries to render your report in the Iframe, SSRS is using your network credentials to determine which records you are allowed to see.

Dont try to take a shortcut and use base entities or non-filtered views when creating a report - you will be wasting your time. If your database is optimized properly, the report should run just as fast when using the filtered views.

SSRS query execution failed for dataset

I had written a nifty new report that I was implementing for a client in CRM 4.0 to be displayed in an Iframe in the Account entity form. After uploading the report using SSRS report manager (http://server_name/reports) and customizing the account form, it worked great for me, but the users got the error "Reporting Services Error...An error has occured during report processing. Query Execution failed for dataset 'DataSource1' "

The first thing to do is turn on the "Enable Remote Errors" feature of SSRS.
1. Open SQL Management Studio and connect to your instance of Reporting Services
2. Right click on the server name in the object explorer and choose properties
3. Click on the Advanced option (on left side) then change EnableRemoteErrors to True

Open your browser and re-run the report to see the actual error you are getting.

SSRS security with CRM 4.0

So I am knocking my brans out trying to add a couple security groups to a custom report folder I created on SSRS and the answer is deceivingly simple.

The problem was that after I created the folder, it needed permissions for a couple additional groups: ReportingGroup and SQLAccessGroup. when I typed one of those names in the New Role Assignment for my folder security, it said the group did not exist. The solution is to copy the group name _and_ the GUID that follows it and paste it into the new group name field.

Saturday, January 2, 2010

CRM Auto Filtering

I have been reading up on MS CRM auto filtering which allows you to create a report that you can associate with an entity and then use it on a view or a single record (http://blogs.javista.com/2009/03/18/microsoft-dynamics-crm-pre-filtering-tips/). I started creating some reports this way, but then decided that I also wanted to call the reports programatically and for that I would need parameters. My solution is to make my actual report work with parameters, then create a 'wrapper' report that uses the auto filtering capability, then calls the real report as a sub-report.