Thursday, October 27, 2011

Testlink–trac integration

We are using testlink for test case management, and using trac for bug tracking, we were looking for integration between the 2 tools.
I found out there is built in support for different bug tracking tool in testlink, all we need to do is just to enable this integration
The integration work like the following, you can link any execution of test case to one or more bugs, and when viewing these tese cases it will show the bug id, bug status, bug summary. Also when displaying reports, same bug information is displayed
To enable the integration:
1- Go to testlink directory, open the file
2- Look for the line:  $g_interface_bugs = 'NO';
3- Change to $g_interface_bugs = 'TRAC';
4- Save and close
To setup the integration with trac
1- Go to cfg folder
2- open the file trac.cfg.php
3- Update the setting with your trac url
define('BUG_TRACK_DB_HOST', 'http://hostURL/trac/');
4- update the mapping between testlink project and trac project
$g_interface_bugs_project_name_mapping = array(
    'testlink project name' => 'trac project name'
5- Save and close

Wednesday, June 1, 2011

CRM4: inserting data field from custom field in related entity depending on the contact language

We faced a situation where we had some data fields in a phone call template, but we wanted to use custom field for this data field depending on the language of the contact, also we had some picklist that is always coming in the user context language, and we wanted it to depend on the contact language
To solve this, I have updated the template with some text pattern for each field, for the picklist and the custom fields, then I have created a plugin for the phone call, with the below steps
1- Get the contact language
2- Get the custom field depending on the language
3- Get the localized picklist label for the language
4- Search the phone call description for patterns, and replace with the localized value
5- Update the phone call with the new description
To get the localized lookup label I used the metadata service to get all pick list values, then compared each picklist option with the value and the language
                        Option[] deptOptions = RetrieveEntityPicklistValues(metaService, EntityName.incident.ToString(), _attCaseInternalStatus);
                        foreach (Option option in deptOptions)
                        {
                            if (option.Value.Value == (int)internalStatus)
                            {
                                foreach (LocLabel label in option.Label.LocLabels)
                                {
                                    if (label.LanguageCode.Value == languageCode)
                                    {
                                        newCaseInternalStatus = label.Label;
                                        break;
                                    }
                                }
                                break;

                            }
                        }


        public Option[] RetrieveEntityPicklistValues(IMetadataService metaService, string strEntityType, string pickListName)
        {
            try
            {
                RetrieveAttributeRequest request = new RetrieveAttributeRequest();
                request.EntityLogicalName = strEntityType;
                request.RetrieveAsIfPublished = true;
                request.LogicalName = pickListName;

                RetrieveAttributeResponse response = (RetrieveAttributeResponse)metaService.Execute(request);
                AttributeMetadata retreivedAttributeMetadata = response.AttributeMetadata;
                if (retreivedAttributeMetadata is PicklistAttributeMetadata)
                {
                    return ((PicklistAttributeMetadata)retreivedAttributeMetadata).Options;
                }
            }
            catch (Exception eGlobalException)
            {
                throw;
            }
            return null;
        }


Same concept can be applied with any template, a more generic solution could be developed by creating a plugin on template retrieval that replaces the values for any retrieved template

Monday, May 23, 2011

Viewstate is not maintained in iframe inside MS CRM form

We had a page that is hosted inside CRM form, the page contains list with a checkboxes beside each each row. When clicking apply, certain action should be performed on the selected items. things are working fine on the development machine, but when hosting inside the CRM form, when clicking “apply”, the action wasn’t applied on the selected items, we discovered later that the code that loops over the checked items, doesn’t run as if there is no records checked.

Doing some search I found that CRM web.config by default has the following line

enableViewState="false" i.e. by default Viewstate is not enabled in CRM.

Changing this to enableViewState="true" and restarting IIS, every thing worked fine and actions were applied successfully.

There is another option which is to enable this in the page directives like the following

<%@ Page Language="C#" ... EnableViewState="true" %>

Viewstate is not maintained in iframe inside MS CRM form

We had a page that is hosted inside CRM form, the page contains list with a checkboxes beside each each row. When clicking apply, certain action should be performed on the selected items. things are working fine on the development machine, but when hosting inside the CRM form, when clicking “apply”, the action wasn’t applied on the selected items, we discovered later that the code that loops over the checked items, doesn’t run as if there is no records checked.
Doing some search I found that CRM web.config by default has the following line
enableViewState="false" i.e. by default Viewstate is not enabled in CRM.
Changing this to enableViewState="true" and restarting IIS, every thing worked fine and actions were applied successfully.
There is another option which is to enable this in the page directives like the following
<%@ Page Language="C#" ... EnableViewState="true" %>

Allowing concurrent user terminal sessions on windows 2008

We had a server running windows 2008, we were several persons working on the same machine at the same time, we all were using one user credentials. Each time one of us was connecting remotely to the server, it was disconnecting the other person who was working at that time, so only 1 session was allowed per user on the server

I was looking for the option to enable multiple sessions per user, doing some search, finally i found it

Click on start
Type "Remote desktop session host configuration" and hit enter
You will find an option on the screen that says "Restrict each user to a single session"

Double click that option, and uncheck this option and click OK



Then you will be able to connect several users remotely to windows 2008 using the same user credentials

Thursday, April 28, 2011

Modifying non customizable entities in CRM 4.0

We wanted to add extra columns for the Queues view, while the Queue item is not customizable entity we found a way posted in several blogs, by modifying the "isCustomizable" setting from the DB directly with the below statement

UPDATE Entity
SET ISCUSTOMIZABLE = 1
WHERE NAME = 'queueitem'

After doing this, we were able to open the Queue Item entity and modify the View, we added more columns, then with javascript we modified the values for this columns.

It is very important to change back the settings as it was after finishing the modification by running the same script again and setting it back to 0


UPDATE Entity
SET ISCUSTOMIZABLE = 0
WHERE NAME = 'queueitem'




Monday, March 7, 2011

Escaping single quote in server side script in asp page

We had a javascript function that was using server side property like the following,

<a href="#" onclick="MyFunction('<%=SomeProperty %>')">Link</a>

When "SomeProperty" contains single quote "'" this was causing script errors in the page.




To solve this error, just add the following after SomeProperty

.ToString().Replace("'","\\'").Replace("\"","&quot;")

so that it will look like this at the end

<a href="#" onclick="MyFunction('<%=SomeProperty.ToString().Replace("'","\\'").Replace("\"","&quot;") %>')">Link</a>

This will solve the problem


Note: when i tried to do this from the code behind, replacing the quote, it didn't working

Wednesday, September 22, 2010

SQL Server - Stored Procedure returning table with dynamic columns

We had a stored procedure that returns some data, later we wanted to add some columns to this data, and these columns are dynamic.
We found several articles on how to use pivot to create dynamic columns in tables, for example
http://www.simple-talk.com/community/blogs/andras/archive/2007/09/14/37265.aspx

and others,

All using the same method, constructing the column headers in a variable, then creating inline sql and using pivot statement and this variable as the columns

In our case we had already a very big select statement, that we didn't want to alter, we just wanted to add more columns to it.

We thought of using table user defined function, but then we had to define the table columns, which we can't do, as it should be dynamic.

We thought also of using a view, then to join with this view, but we can't use pivot in views

We thought also of using a separate stored procedure and calling this stored procedure from the original one, but we found that this is not supported solution.

Finally we tried something and it worked, we alerted the original stored procedure like the following: We inserted the output of the first select statement into a temp table, and then added the second select and pivot in an inline sql statement, and in this statement we inner joined with our temp table.

An example of what we did

Suppose the first statement is like the following

Select * from table1

and our pivot statement is like the following


@query = 'select * from table2 pivot (count(columnName1) for ColumnContainingData in (' + @columnNames + ')'

where columnsName1 is the column that we will perform the aggregate function on, @columnNames is a variable with column names comma seperated and surrounded with []

the final statement looked lke the following

select * into #tempTable from
(select Select * from table1) t
@query = 'select * from table2 pivot (count(columnName1) for ColumnContainingData in (' + @columnNames + ') t2 inner join #tempTable on #tempTable .SomeId = t2.SomeId'

Handling comma separated values parameter in a stored procedure without using inline sql

I have seen lots of implementation for comma separated values parameters, all using inline SQL to construct the query.
for example:
Suppose the parameter is @param having the value '1,2,3'
and we are selecting rows with state in (1,2,3)

Then the query would look like this

query='select * from TableName where state in (' + @param + ')'
exec query

Since i don't like inline SQL, i was looking for another methods

I found this method somewhere, i don't remember where exactly. It is based on constructing a table, and inserting the comma separated values in this  table, then in the query either we can inner join with this table to get the desired values only or we can use where clause

example on constructing this temp table



declare @param nvarchar(50)
set @param = N'1,2,3,4'
IF EXISTS
(SELECT * FROM tempdb.dbo.sysobjects WHERE ID = OBJECT_ID(N'tempdb..#temptable'))
BEGIN
DROP TABLE #temptable
END

CREATE TABLE #temptable(Code int)

   DECLARE @code varchar(10), @Pos int

    SET @param = LTRIM(RTRIM(@param))+ ','
    SET @Pos = CHARINDEX(',', @param, 1)

    IF REPLACE(@param, ',', '') <> ''
    BEGIN
        WHILE @Pos > 0
        BEGIN
                SET @code = LTRIM(RTRIM(LEFT(@param, @Pos - 1)))
                IF @code <> ''
                BEGIN
                        INSERT INTO #temptable (code)
                        VALUES (CAST(@code AS int)) --Use Appropriate conversion
                END
                SET @param = RIGHT(@param, LEN(@param) - @Pos)
                SET @Pos = CHARINDEX(',', @param, 1)

        END
    END
--select * FROM #temptable

Next in the main query, it can be like this

Select * FROM TableName
INNER JOIN #temptable on TableName.State = #temptable.code

or

Select * FROM TableName
where state in (select code from #temptable)

Wednesday, September 8, 2010

MS CRM Plugin development best practices

While i was debugging, I noticed that update plugin was lots of times, and each time it was called all case properties was sent in the context, While not all of them are updated. so i started searching on how to make sure that only the updated property is sent to the update plugin.
I found this article which is very useful
http://blogs.inetium.com/blogs/azimmer/archive/2010/01/25/plugin-best-practices-in-crm-4-0.aspx

In summary what i was doing wrong is like the following:
- I was doing retrieve entity then after, i was doing update to that entity, while the correct thing is that to do update without doing retrieve.
- When retrieving for any other reason, i was getting all columns, the correct thing to do is to get the desired columns only