Friday, May 25, 2012

Timeout expired on Dynamics CRM 4.0

Today I got a timeout expired error when calling a query to dynamic crm (from web service). I saw the query from trace and I when I executed it from sql server it elapsed 31 seconds. The problem was that the default timeout of sql queries in Microsoft Dynamics CRM 4.0 is 30 seconds.
This timeout can be overriden from registry by adding a DWORD value with the timeout time in seconds to the following registry key:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSCRM\OLEDBTimeout]

Good reference of timeout specifications can be found here

Tuesday, May 22, 2012

Pass multivalue parameter to drillthrough report


Recently I had a request to create a drillthrough report for an aging report (actually 5 reports). I had 2 choices. One to create 5 reports or two to make one with multivalue parameters (each one of the parent reports must pass different values witch were static). Of course I decided to follow the second option. In order to do that I created the desired parameter in the parent report and I set it as multivalue and as internal.



Next I set the available values, and I set the same values and as defaults




Finally on the textbox witch I wanted to trigger the drillthrough action I inserted the parameter (OrderStatus is a multivalue parameter of the drillthrough report)




The text exression of the parent parameter was



Running Unit Tests From Network Drive

I used visual studio 2010 to create some unit tests for a custom application and I got the following error message "Error loading U:\Visual Studio 2010\Projects\LoyaltyViewer\LoyaltyViewerTest\bin\Debug\LoyaltyViewerTest.dll: Could not load file or assembly 'file:///U:\Visual Studio 2010\Projects\LoyaltyViewer\LoyaltyViewerTest\bin\Debug\LoyaltyViewerTest.dll' or one of its dependencies. Operation is not supported. (Exception from HRESULT: 0x80131515)". I googled the problem and what I found what the problem was. It appeared that visual studio could not load the assembly from a remote drive. To fix the problem, I followed the instructions from this post. The workaround is to create set COMPLUS_LoadFromRemoteSources=1.


Open a command prompt and type "setx COMPLUS_LoadFromRemoteSources 1"

or

Create an environment variable named COMPLUS_LoadFromRemoteSources
Set the value to 1

Tuesday, December 28, 2010

Custom Isv.Config behavior based on User Security Roles

In Microsoft Dynamics CRM we can embed our custom solution throw sitemap, isv.config and iframe. If we want to have a custom behavior in isv.config based on User Security Roles we can inject javascript to do that.

Here is a custom button on toolbar that has custom javascript inside isv.config:

 
<ToolBar ValidForCreate="0" ValidForUpdate="0">
  <Button Icon="/_imgs/ico_16_1013.gif" ValidForCreate="0" 
ValidForUpdate="0" PassParams="1" WinMode="0" JavaScript="…………">
    <Titles>
      <Title LCID="1033" Text="Export To CSV" />
    </Titles>
      <ToolTips>
      <ToolTip LCID="1033" Text="Export To CSV" />
    </ToolTips>
  </Button>
</ToolBar>


 
Inside javascript we want a function to return all roles of a specific user by creating s SOAP message request:

//*********************
function GetCurrentUserRoles()
{
 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>role</q1:EntityName>" +
 " <q1:ColumnSet xsi:type=\"q1:ColumnSet\">" +
 " <q1:Attributes>" +
 " <q1:Attribute>name</q1:Attribute>" +
 " </q1:Attributes>" +
 " </q1:ColumnSet>" +
 " <q1:Distinct>false</q1:Distinct>" +
 " <q1:LinkEntities>" +
 " <q1:LinkEntity>" +
 " <q1:LinkFromAttributeName>roleid</q1:LinkFromAttributeName>" +
 " <q1:LinkFromEntityName>role</q1:LinkFromEntityName>" +
 " <q1:LinkToEntityName>systemuserroles</q1:LinkToEntityName>" +
 " <q1:LinkToAttributeName>roleid</q1:LinkToAttributeName>" +
 " <q1:JoinOperator>Inner</q1:JoinOperator>" +
 " <q1:LinkEntities>" +
 " <q1:LinkEntity>" +
 " <q1:LinkFromAttributeName>systemuserid</q1:LinkFromAttributeName>" +
 " <q1:LinkFromEntityName>systemuserroles</q1:LinkFromEntityName>" +
 " <q1:LinkToEntityName>systemuser</q1:LinkToEntityName>" +
 " <q1:LinkToAttributeName>systemuserid</q1:LinkToAttributeName>" +
 " <q1:JoinOperator>Inner</q1:JoinOperator>" +
 " <q1:LinkCriteria>" +
 " <q1:FilterOperator>And</q1:FilterOperator>" +
 " <q1:Conditions>" +
 " <q1:Condition>" +
 " <q1:AttributeName>systemuserid</q1:AttributeName>" +
 " <q1:Operator>EqualUserId</q1:Operator>" +
 " </q1:Condition>" +
 " </q1:Conditions>" +
 " </q1:LinkCriteria>" +
 " </q1:LinkEntity>" +
 " </q1:LinkEntities>" +
 " </q1:LinkEntity>" +
 " </q1:LinkEntities>" +
 " </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;
 return(resultXml);
}
//*********************

Then we need a function to check if specified user has specified role:

//*********************
function UserHasRole(roleName) {
    //get Current User Roles, oXml is an object
    var oXml = GetCurrentUserRoles();
    if (oXml != null) {
        //select the node text
        var roles = oXml.selectNodes("//BusinessEntity/q1:name");
        if (roles != null) {
            for (i = 0; i < roles.length; i++) {
                if (roles[i].text == roleName) {
                    //return true if user has this role
                    return true;
                }
            }
        }
    }
    //otherwise return false
    return false;
}
//*********************

Finally we have the actual code for button. Our intention is to check if a user has a specific security role (by name) and if he has it, to restrict him from making executing the action of button.
 
if(!UserHasRole("No CSV Export"))
{
  // OK pass and go to custom solution for making the export
  window.open('/ISV/CRMISVCustoms/ExportToCSV.aspx?orgname=' + ORG_UNIQUE_NAME,'ExportCSV','width=500,height=200,resizable=yes');
}
else
{
   // Not authorized
   alert('You are not authorized to Export in csv');
}


Monday, December 13, 2010

Microsoft Dynamics CRM limits export to 10000 rows to Excel

Our customer is making lists of contacts to send then in third parties for process. The number of contacts in those list can be larger than 50000. When we made an export to excel we saw that only 10000 contacts where exported. It turned out that there was a limitation in the organization database for exporting only 10000 rows from excel. The solution was easy. We changed the limit value from sql server (table OrganizationBase field MaxRecordsForExportToExcel). The query was:

update OrganizationBase set
      MaxRecordsForExportToExcel = 65500

After the query we made a restart of iis and everything worked.